* Update StormLib to Version 8.04
This commit is contained in:
parent
8dd5fb940b
commit
f098525843
@ -1,7 +1,7 @@
|
||||
include_directories (${PROJECT_SOURCE_DIR}/src/dep/include ${PROJECT_SOURCE_DIR}/src/shared ${PROJECT_SOURCE_DIR}/src/Client)
|
||||
|
||||
set(PSEUWOW_LIBS
|
||||
PseuGUI DefScript IrrKlang irrlicht shared zthread StormLib zlib ${OPENSSL_LIBRARIES} ${OPENSSL_EXTRA_LIBRARIES}
|
||||
PseuGUI DefScript IrrKlang irrlicht shared zthread StormLib_static zlib ${OPENSSL_LIBRARIES} ${OPENSSL_EXTRA_LIBRARIES}
|
||||
)
|
||||
|
||||
link_directories (${CMAKE_INSTALL_PREFIX})
|
||||
@ -19,7 +19,7 @@ add_subdirectory (GUI)
|
||||
|
||||
|
||||
|
||||
add_executable (pseuwow
|
||||
add_executable (pseuwow
|
||||
Realm/RealmSession.cpp
|
||||
Realm/RealmSocket.cpp
|
||||
|
||||
@ -57,6 +57,6 @@ SCPDatabase.cpp
|
||||
|
||||
|
||||
# Link the executable to the libraries.
|
||||
target_link_libraries (pseuwow ${PSEUWOW_LIBS})
|
||||
target_link_libraries (pseuwow ${PSEUWOW_LIBS})
|
||||
|
||||
install(TARGETS pseuwow DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
@ -1,44 +1,294 @@
|
||||
include_directories (${PROJECT_SOURCE_DIR}/src/dep/include)
|
||||
|
||||
set(STORMLIB_SOURCES huffman/huff.cpp
|
||||
wave/wave.cpp
|
||||
SAttrFile.cpp
|
||||
SCommon.cpp
|
||||
SCompression.cpp
|
||||
SFileCompactArchive.cpp
|
||||
SFileCreateArchiveEx.cpp
|
||||
SFileExtractFile.cpp
|
||||
SFileFindFile.cpp
|
||||
SFileOpenArchive.cpp
|
||||
SFileOpenFileEx.cpp
|
||||
SFileReadFile.cpp
|
||||
SListFile.cpp
|
||||
pklib/crc32_pk.c
|
||||
pklib/explode.c
|
||||
pklib/implode.c
|
||||
misc/crc32.cpp
|
||||
misc/md5.cpp)
|
||||
|
||||
if(UNIX)
|
||||
set(STORMLIB_SOURCES ${STORMLIB_SOURCES} StormPortLinux.cpp)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(STORMLIB_SOURCES ${STORMLIB_SOURCES}
|
||||
bzip2/blocksort.c
|
||||
bzip2/bzip2.c
|
||||
bzip2/bzip2recover.c
|
||||
bzip2/bzlib.c
|
||||
bzip2/compress.c
|
||||
bzip2/crctable.c
|
||||
bzip2/decompress.c
|
||||
bzip2/dlltest.c
|
||||
bzip2/huffman.c
|
||||
bzip2/mk251.c
|
||||
bzip2/randtable.c
|
||||
bzip2/spewG.c
|
||||
bzip2/unzcrash.c
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(StormLib ${STORMLIB_SOURCES})
|
||||
project(StormLib)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
set(SRC_FILES
|
||||
src/adpcm/adpcm.cpp
|
||||
src/huffman/huff.cpp
|
||||
src/jenkins/lookup3.c
|
||||
src/lzma/C/LzFind.c
|
||||
src/lzma/C/LzmaDec.c
|
||||
src/lzma/C/LzmaEnc.c
|
||||
src/pklib/explode.c
|
||||
src/pklib/implode.c
|
||||
src/sparse/sparse.cpp
|
||||
src/FileStream.cpp
|
||||
src/SBaseCommon.cpp
|
||||
src/SBaseFileTable.cpp
|
||||
src/SCompression.cpp
|
||||
src/SFileAddFile.cpp
|
||||
src/SFileAttributes.cpp
|
||||
src/SFileCompactArchive.cpp
|
||||
src/SFileCreateArchive.cpp
|
||||
src/SFileExtractFile.cpp
|
||||
src/SFileFindFile.cpp
|
||||
src/SFileListFile.cpp
|
||||
src/SFileOpenArchive.cpp
|
||||
src/SFileOpenFileEx.cpp
|
||||
src/SFilePatchArchives.cpp
|
||||
src/SFileReadFile.cpp
|
||||
src/SFileVerify.cpp
|
||||
)
|
||||
|
||||
set(TOMCRYPT_FILES
|
||||
src/libtomcrypt/src/hashes/hash_memory.c
|
||||
src/libtomcrypt/src/hashes/md5.c
|
||||
src/libtomcrypt/src/hashes/sha1.c
|
||||
src/libtomcrypt/src/math/ltm_desc.c
|
||||
src/libtomcrypt/src/math/multi.c
|
||||
src/libtomcrypt/src/math/rand_prime.c
|
||||
src/libtomcrypt/src/misc/base64_decode.c
|
||||
src/libtomcrypt/src/misc/crypt_argchk.c
|
||||
src/libtomcrypt/src/misc/crypt_find_hash.c
|
||||
src/libtomcrypt/src/misc/crypt_find_prng.c
|
||||
src/libtomcrypt/src/misc/crypt_hash_descriptor.c
|
||||
src/libtomcrypt/src/misc/crypt_hash_is_valid.c
|
||||
src/libtomcrypt/src/misc/crypt_libc.c
|
||||
src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c
|
||||
src/libtomcrypt/src/misc/crypt_prng_descriptor.c
|
||||
src/libtomcrypt/src/misc/crypt_prng_is_valid.c
|
||||
src/libtomcrypt/src/misc/crypt_register_hash.c
|
||||
src/libtomcrypt/src/misc/crypt_register_prng.c
|
||||
src/libtomcrypt/src/misc/zeromem.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_boolean.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_choice.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_integer.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utctime.c
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_bit_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_boolean.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_integer.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_octet_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_printable_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_sequence.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utctime.c
|
||||
src/libtomcrypt/src/pk/asn1/der_sequence_free.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c
|
||||
src/libtomcrypt/src/pk/asn1/der_length_short_integer.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_exptmod.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_free.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_import.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_make_key.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c
|
||||
)
|
||||
|
||||
set(TOMMATH_FILES
|
||||
src/libtommath/bncore.c
|
||||
src/libtommath/bn_fast_mp_invmod.c
|
||||
src/libtommath/bn_fast_mp_montgomery_reduce.c
|
||||
src/libtommath/bn_fast_s_mp_mul_digs.c
|
||||
src/libtommath/bn_fast_s_mp_mul_high_digs.c
|
||||
src/libtommath/bn_fast_s_mp_sqr.c
|
||||
src/libtommath/bn_mp_2expt.c
|
||||
src/libtommath/bn_mp_abs.c
|
||||
src/libtommath/bn_mp_add.c
|
||||
src/libtommath/bn_mp_addmod.c
|
||||
src/libtommath/bn_mp_add_d.c
|
||||
src/libtommath/bn_mp_and.c
|
||||
src/libtommath/bn_mp_clamp.c
|
||||
src/libtommath/bn_mp_clear.c
|
||||
src/libtommath/bn_mp_clear_multi.c
|
||||
src/libtommath/bn_mp_cmp.c
|
||||
src/libtommath/bn_mp_cmp_d.c
|
||||
src/libtommath/bn_mp_cmp_mag.c
|
||||
src/libtommath/bn_mp_cnt_lsb.c
|
||||
src/libtommath/bn_mp_copy.c
|
||||
src/libtommath/bn_mp_count_bits.c
|
||||
src/libtommath/bn_mp_div.c
|
||||
src/libtommath/bn_mp_div_2.c
|
||||
src/libtommath/bn_mp_div_2d.c
|
||||
src/libtommath/bn_mp_div_3.c
|
||||
src/libtommath/bn_mp_div_d.c
|
||||
src/libtommath/bn_mp_dr_is_modulus.c
|
||||
src/libtommath/bn_mp_dr_reduce.c
|
||||
src/libtommath/bn_mp_dr_setup.c
|
||||
src/libtommath/bn_mp_exch.c
|
||||
src/libtommath/bn_mp_exptmod.c
|
||||
src/libtommath/bn_mp_exptmod_fast.c
|
||||
src/libtommath/bn_mp_expt_d.c
|
||||
src/libtommath/bn_mp_exteuclid.c
|
||||
src/libtommath/bn_mp_fread.c
|
||||
src/libtommath/bn_mp_fwrite.c
|
||||
src/libtommath/bn_mp_gcd.c
|
||||
src/libtommath/bn_mp_get_int.c
|
||||
src/libtommath/bn_mp_grow.c
|
||||
src/libtommath/bn_mp_init.c
|
||||
src/libtommath/bn_mp_init_copy.c
|
||||
src/libtommath/bn_mp_init_multi.c
|
||||
src/libtommath/bn_mp_init_set.c
|
||||
src/libtommath/bn_mp_init_set_int.c
|
||||
src/libtommath/bn_mp_init_size.c
|
||||
src/libtommath/bn_mp_invmod.c
|
||||
src/libtommath/bn_mp_invmod_slow.c
|
||||
src/libtommath/bn_mp_is_square.c
|
||||
src/libtommath/bn_mp_jacobi.c
|
||||
src/libtommath/bn_mp_karatsuba_mul.c
|
||||
src/libtommath/bn_mp_karatsuba_sqr.c
|
||||
src/libtommath/bn_mp_lcm.c
|
||||
src/libtommath/bn_mp_lshd.c
|
||||
src/libtommath/bn_mp_mod.c
|
||||
src/libtommath/bn_mp_mod_2d.c
|
||||
src/libtommath/bn_mp_mod_d.c
|
||||
src/libtommath/bn_mp_montgomery_calc_normalization.c
|
||||
src/libtommath/bn_mp_montgomery_reduce.c
|
||||
src/libtommath/bn_mp_montgomery_setup.c
|
||||
src/libtommath/bn_mp_mul.c
|
||||
src/libtommath/bn_mp_mulmod.c
|
||||
src/libtommath/bn_mp_mul_2.c
|
||||
src/libtommath/bn_mp_mul_2d.c
|
||||
src/libtommath/bn_mp_mul_d.c
|
||||
src/libtommath/bn_mp_neg.c
|
||||
src/libtommath/bn_mp_n_root.c
|
||||
src/libtommath/bn_mp_or.c
|
||||
src/libtommath/bn_mp_prime_fermat.c
|
||||
src/libtommath/bn_mp_prime_is_divisible.c
|
||||
src/libtommath/bn_mp_prime_is_prime.c
|
||||
src/libtommath/bn_mp_prime_miller_rabin.c
|
||||
src/libtommath/bn_mp_prime_next_prime.c
|
||||
src/libtommath/bn_mp_prime_rabin_miller_trials.c
|
||||
src/libtommath/bn_mp_prime_random_ex.c
|
||||
src/libtommath/bn_mp_radix_size.c
|
||||
src/libtommath/bn_mp_radix_smap.c
|
||||
src/libtommath/bn_mp_rand.c
|
||||
src/libtommath/bn_mp_read_radix.c
|
||||
src/libtommath/bn_mp_read_signed_bin.c
|
||||
src/libtommath/bn_mp_read_unsigned_bin.c
|
||||
src/libtommath/bn_mp_reduce.c
|
||||
src/libtommath/bn_mp_reduce_2k.c
|
||||
src/libtommath/bn_mp_reduce_2k_l.c
|
||||
src/libtommath/bn_mp_reduce_2k_setup.c
|
||||
src/libtommath/bn_mp_reduce_2k_setup_l.c
|
||||
src/libtommath/bn_mp_reduce_is_2k.c
|
||||
src/libtommath/bn_mp_reduce_is_2k_l.c
|
||||
src/libtommath/bn_mp_reduce_setup.c
|
||||
src/libtommath/bn_mp_rshd.c
|
||||
src/libtommath/bn_mp_set.c
|
||||
src/libtommath/bn_mp_set_int.c
|
||||
src/libtommath/bn_mp_shrink.c
|
||||
src/libtommath/bn_mp_signed_bin_size.c
|
||||
src/libtommath/bn_mp_sqr.c
|
||||
src/libtommath/bn_mp_sqrmod.c
|
||||
src/libtommath/bn_mp_sqrt.c
|
||||
src/libtommath/bn_mp_sub.c
|
||||
src/libtommath/bn_mp_submod.c
|
||||
src/libtommath/bn_mp_sub_d.c
|
||||
src/libtommath/bn_mp_toom_mul.c
|
||||
src/libtommath/bn_mp_toom_sqr.c
|
||||
src/libtommath/bn_mp_toradix.c
|
||||
src/libtommath/bn_mp_toradix_n.c
|
||||
src/libtommath/bn_mp_to_signed_bin.c
|
||||
src/libtommath/bn_mp_to_signed_bin_n.c
|
||||
src/libtommath/bn_mp_to_unsigned_bin.c
|
||||
src/libtommath/bn_mp_to_unsigned_bin_n.c
|
||||
src/libtommath/bn_mp_unsigned_bin_size.c
|
||||
src/libtommath/bn_mp_xor.c
|
||||
src/libtommath/bn_mp_zero.c
|
||||
src/libtommath/bn_prime_tab.c
|
||||
src/libtommath/bn_reverse.c
|
||||
src/libtommath/bn_s_mp_add.c
|
||||
src/libtommath/bn_s_mp_exptmod.c
|
||||
src/libtommath/bn_s_mp_mul_digs.c
|
||||
src/libtommath/bn_s_mp_mul_high_digs.c
|
||||
src/libtommath/bn_s_mp_sqr.c
|
||||
src/libtommath/bn_s_mp_sub.c
|
||||
)
|
||||
|
||||
set(ZLIB_BZIP2_FILES
|
||||
src/bzip2/blocksort.c
|
||||
src/bzip2/bzlib.c
|
||||
src/bzip2/compress.c
|
||||
src/bzip2/crctable.c
|
||||
src/bzip2/decompress.c
|
||||
src/bzip2/huffman.c
|
||||
src/bzip2/randtable.c
|
||||
src/zlib/adler32.c
|
||||
src/zlib/compress2.c
|
||||
src/zlib/crc32.c
|
||||
src/zlib/deflate.c
|
||||
src/zlib/inffast.c
|
||||
src/zlib/inflate.c
|
||||
src/zlib/inftrees.c
|
||||
src/zlib/trees.c
|
||||
src/zlib/zutil.c
|
||||
)
|
||||
|
||||
set(TEST_SRC_FILES
|
||||
test/Test.cpp
|
||||
)
|
||||
|
||||
add_definitions(-D_7ZIP_ST -DBZ_STRICT_ANSI)
|
||||
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
message(STATUS "Using MSVC")
|
||||
add_definitions(-D_7ZIP_ST -DWIN32)
|
||||
else()
|
||||
message(STATUS "Using mingw")
|
||||
endif()
|
||||
set(SRC_ADDITIONAL_FILES ${ZLIB_BZIP2_FILES} ${TOMCRYPT_FILES} ${TOMMATH_FILES})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
message(STATUS "Using Mac OS X port")
|
||||
set(LINK_LIBS z bz2)
|
||||
set(SRC_ADDITIONAL_FILES ${TOMCRYPT_FILES} ${TOMMATH_FILES})
|
||||
endif()
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL Linux)
|
||||
message(STATUS "Using Linux port")
|
||||
option(WITH_LIBTOMCRYPT "Use system LibTomCrypt library" OFF)
|
||||
if(WITH_LIBTOMCRYPT)
|
||||
set(LINK_LIBS z bz2 tomcrypt)
|
||||
else()
|
||||
set(LINK_LIBS z bz2)
|
||||
set(SRC_ADDITIONAL_FILES ${TOMCRYPT_FILES} ${TOMMATH_FILES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(StormLib SHARED ${SRC_FILES} ${SRC_ADDITIONAL_FILES})
|
||||
target_link_libraries(StormLib ${LINK_LIBS})
|
||||
|
||||
add_library(StormLib_static STATIC ${SRC_FILES} ${SRC_ADDITIONAL_FILES})
|
||||
target_link_libraries(StormLib_static ${LINK_LIBS})
|
||||
set_target_properties(StormLib_static PROPERTIES OUTPUT_NAME StormLib)
|
||||
|
||||
option(WITH_TEST "Compile Test application" OFF)
|
||||
if(WITH_TEST)
|
||||
add_executable(StormLib_test ${TEST_SRC_FILES})
|
||||
target_link_libraries(StormLib_test StormLib_static)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(StormLib PROPERTIES FRAMEWORK true)
|
||||
set_target_properties(StormLib PROPERTIES PUBLIC_HEADER "src/StormLib.h src/StormPort.h")
|
||||
set_target_properties(StormLib PROPERTIES LINK_FLAGS "-framework Carbon")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
set_target_properties(StormLib PROPERTIES SOVERSION 0)
|
||||
endif()
|
||||
|
||||
# install(TARGETS StormLib StormLib_static RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
|
||||
# install(FILES src/StormLib.h src/StormPort.h DESTINATION include)
|
||||
|
||||
|
||||
22
src/dep/src/StormLib/Info.plist
Normal file
22
src/dep/src/StormLib/Info.plist
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>net.zezula.${PRODUCT_NAME:rfc1034Identifier}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>8.01</string>
|
||||
</dict>
|
||||
</plist>
|
||||
275
src/dep/src/StormLib/Makefile.linux
Normal file
275
src/dep/src/StormLib/Makefile.linux
Normal file
@ -0,0 +1,275 @@
|
||||
#####################################################################
|
||||
###
|
||||
#
|
||||
# Makefile for compiling StormLib under linux
|
||||
#
|
||||
# Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
|
||||
# Created at: Mon Jan 29 18:26:01 CEST 2001
|
||||
# Computer: whiplash.flachland-chemnitz.de
|
||||
# System: Linux 2.4.0 on i686
|
||||
#
|
||||
# Copyright (c) 2001 BMX-Chemnitz.DE All rights reserved.
|
||||
#
|
||||
#####################################################################
|
||||
###
|
||||
|
||||
##############################################################
|
||||
# updated on Monday 3, 2010 by Christopher Chedeau aka vjeux #
|
||||
# updated on April 24, 2010 by Ivan Komissarov aka Nevermore #
|
||||
##############################################################
|
||||
|
||||
C++ = g++
|
||||
CC = gcc
|
||||
AR = ar
|
||||
DFLAGS = -D__SYS_ZLIB
|
||||
OFLAGS =
|
||||
LFLAGS = -lbz2 -lz
|
||||
CFLAGS = -fPIC -D_7ZIP_ST
|
||||
CFLAGS += $(OFLAGS) $(DFLAGS)
|
||||
|
||||
OBJS = src/adpcm/adpcm.o \
|
||||
src/FileStream.o \
|
||||
src/huffman/huff.o \
|
||||
src/SBaseCommon.o \
|
||||
src/SBaseFileTable.o \
|
||||
src/SCompression.o \
|
||||
src/SFileAddFile.o \
|
||||
src/SFileAttributes.o \
|
||||
src/SFileCompactArchive.o \
|
||||
src/SFileCreateArchive.o \
|
||||
src/SFileExtractFile.o \
|
||||
src/SFileFindFile.o \
|
||||
src/SFileListFile.o \
|
||||
src/SFileOpenArchive.o \
|
||||
src/SFileOpenFileEx.o \
|
||||
src/SFilePatchArchives.o \
|
||||
src/SFileReadFile.o \
|
||||
src/SFileVerify.o \
|
||||
src/sparse/sparse.o
|
||||
|
||||
COBJS = src/libtomcrypt/src/hashes/sha1.o \
|
||||
src/libtomcrypt/src/hashes/hash_memory.o \
|
||||
src/libtomcrypt/src/hashes/md5.o \
|
||||
src/libtomcrypt/src/misc/crypt_hash_is_valid.o \
|
||||
src/libtomcrypt/src/misc/crypt_prng_descriptor.o \
|
||||
src/libtomcrypt/src/misc/crypt_register_prng.o \
|
||||
src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.o \
|
||||
src/libtomcrypt/src/misc/crypt_find_hash.o \
|
||||
src/libtomcrypt/src/misc/zeromem.o \
|
||||
src/libtomcrypt/src/misc/base64_decode.o \
|
||||
src/libtomcrypt/src/misc/crypt_register_hash.o \
|
||||
src/libtomcrypt/src/misc/crypt_find_prng.o \
|
||||
src/libtomcrypt/src/misc/crypt_prng_is_valid.o \
|
||||
src/libtomcrypt/src/misc/crypt_hash_descriptor.o \
|
||||
src/libtomcrypt/src/misc/crypt_libc.o \
|
||||
src/libtomcrypt/src/misc/crypt_argchk.o \
|
||||
src/libtomcrypt/src/math/multi.o \
|
||||
src/libtomcrypt/src/math/ltm_desc.o \
|
||||
src/libtomcrypt/src/math/rand_prime.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_ia5_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utctime.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_boolean.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_octet_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_object_identifier.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_bit_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_integer.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_sequence.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_choice.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_octet_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_printable_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_bit_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_short_integer.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utctime.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_integer.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_boolean.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_sequence_free.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_short_integer.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_printable_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utf8_string.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_make_key.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_free.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_simple.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_import.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_hash.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_exptmod.o \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.o \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.o \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.o \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_map.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_points.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.o \
|
||||
src/libtommath/bn_mp_exptmod_fast.o \
|
||||
src/libtommath/bn_mp_jacobi.o \
|
||||
src/libtommath/bn_mp_mod.o \
|
||||
src/libtommath/bn_mp_signed_bin_size.o \
|
||||
src/libtommath/bn_mp_invmod.o \
|
||||
src/libtommath/bn_mp_is_square.o \
|
||||
src/libtommath/bn_mp_neg.o \
|
||||
src/libtommath/bn_mp_reduce_2k.o \
|
||||
src/libtommath/bn_mp_xor.o \
|
||||
src/libtommath/bn_mp_karatsuba_mul.o \
|
||||
src/libtommath/bn_mp_dr_setup.o \
|
||||
src/libtommath/bn_mp_mul.o \
|
||||
src/libtommath/bn_mp_init_multi.o \
|
||||
src/libtommath/bn_mp_clear.o \
|
||||
src/libtommath/bn_s_mp_sqr.o \
|
||||
src/libtommath/bn_mp_rshd.o \
|
||||
src/libtommath/bn_s_mp_sub.o \
|
||||
src/libtommath/bn_mp_sub.o \
|
||||
src/libtommath/bn_mp_toradix.o \
|
||||
src/libtommath/bn_mp_reduce.o \
|
||||
src/libtommath/bn_mp_prime_is_prime.o \
|
||||
src/libtommath/bn_mp_prime_next_prime.o \
|
||||
src/libtommath/bn_mp_exptmod.o \
|
||||
src/libtommath/bn_mp_mod_2d.o \
|
||||
src/libtommath/bn_reverse.o \
|
||||
src/libtommath/bn_mp_init.o \
|
||||
src/libtommath/bn_fast_s_mp_sqr.o \
|
||||
src/libtommath/bn_mp_sqr.o \
|
||||
src/libtommath/bn_mp_cnt_lsb.o \
|
||||
src/libtommath/bn_mp_clear_multi.o \
|
||||
src/libtommath/bn_mp_exch.o \
|
||||
src/libtommath/bn_fast_s_mp_mul_digs.o \
|
||||
src/libtommath/bn_mp_grow.o \
|
||||
src/libtommath/bn_mp_read_radix.o \
|
||||
src/libtommath/bn_mp_mul_2.o \
|
||||
src/libtommath/bn_mp_shrink.o \
|
||||
src/libtommath/bn_mp_div_2.o \
|
||||
src/libtommath/bn_fast_mp_invmod.o \
|
||||
src/libtommath/bn_mp_prime_miller_rabin.o \
|
||||
src/libtommath/bn_mp_to_unsigned_bin.o \
|
||||
src/libtommath/bn_mp_prime_rabin_miller_trials.o \
|
||||
src/libtommath/bn_mp_2expt.o \
|
||||
src/libtommath/bn_mp_cmp_mag.o \
|
||||
src/libtommath/bn_mp_to_signed_bin.o \
|
||||
src/libtommath/bn_mp_get_int.o \
|
||||
src/libtommath/bn_mp_montgomery_reduce.o \
|
||||
src/libtommath/bn_mp_dr_reduce.o \
|
||||
src/libtommath/bn_mp_fwrite.o \
|
||||
src/libtommath/bn_mp_and.o \
|
||||
src/libtommath/bn_mp_exteuclid.o \
|
||||
src/libtommath/bn_fast_mp_montgomery_reduce.o \
|
||||
src/libtommath/bn_s_mp_mul_high_digs.o \
|
||||
src/libtommath/bn_mp_reduce_setup.o \
|
||||
src/libtommath/bn_mp_lcm.o \
|
||||
src/libtommath/bn_mp_abs.o \
|
||||
src/libtommath/bn_mp_cmp.o \
|
||||
src/libtommath/bn_mp_submod.o \
|
||||
src/libtommath/bn_mp_div_d.o \
|
||||
src/libtommath/bn_s_mp_mul_digs.o \
|
||||
src/libtommath/bn_mp_mul_d.o \
|
||||
src/libtommath/bn_mp_to_unsigned_bin_n.o \
|
||||
src/libtommath/bn_mp_prime_random_ex.o \
|
||||
src/libtommath/bn_mp_rand.o \
|
||||
src/libtommath/bn_mp_div_2d.o \
|
||||
src/libtommath/bn_mp_addmod.o \
|
||||
src/libtommath/bn_mp_init_copy.o \
|
||||
src/libtommath/bn_mp_read_unsigned_bin.o \
|
||||
src/libtommath/bn_mp_toradix_n.o \
|
||||
src/libtommath/bn_fast_s_mp_mul_high_digs.o \
|
||||
src/libtommath/bn_mp_toom_sqr.o \
|
||||
src/libtommath/bn_mp_to_signed_bin_n.o \
|
||||
src/libtommath/bn_mp_reduce_2k_setup_l.o \
|
||||
src/libtommath/bn_mp_div.o \
|
||||
src/libtommath/bn_prime_tab.o \
|
||||
src/libtommath/bn_mp_karatsuba_sqr.o \
|
||||
src/libtommath/bn_mp_gcd.o \
|
||||
src/libtommath/bn_mp_prime_is_divisible.o \
|
||||
src/libtommath/bn_mp_set_int.o \
|
||||
src/libtommath/bn_mp_prime_fermat.o \
|
||||
src/libtommath/bn_mp_cmp_d.o \
|
||||
src/libtommath/bn_mp_add.o \
|
||||
src/libtommath/bn_mp_sub_d.o \
|
||||
src/libtommath/bn_s_mp_exptmod.o \
|
||||
src/libtommath/bn_mp_init_size.o \
|
||||
src/libtommath/bncore.o \
|
||||
src/libtommath/bn_mp_radix_smap.o \
|
||||
src/libtommath/bn_mp_reduce_2k_l.o \
|
||||
src/libtommath/bn_mp_montgomery_calc_normalization.o \
|
||||
src/libtommath/bn_mp_mod_d.o \
|
||||
src/libtommath/bn_mp_set.o \
|
||||
src/libtommath/bn_mp_or.o \
|
||||
src/libtommath/bn_mp_sqrt.o \
|
||||
src/libtommath/bn_mp_invmod_slow.o \
|
||||
src/libtommath/bn_mp_count_bits.o \
|
||||
src/libtommath/bn_mp_read_signed_bin.o \
|
||||
src/libtommath/bn_mp_div_3.o \
|
||||
src/libtommath/bn_mp_unsigned_bin_size.o \
|
||||
src/libtommath/bn_mp_mulmod.o \
|
||||
src/libtommath/bn_mp_clamp.o \
|
||||
src/libtommath/bn_mp_reduce_2k_setup.o \
|
||||
src/libtommath/bn_mp_toom_mul.o \
|
||||
src/libtommath/bn_mp_montgomery_setup.o \
|
||||
src/libtommath/bn_mp_expt_d.o \
|
||||
src/libtommath/bn_mp_copy.o \
|
||||
src/libtommath/bn_mp_dr_is_modulus.o \
|
||||
src/libtommath/bn_mp_sqrmod.o \
|
||||
src/libtommath/bn_mp_reduce_is_2k_l.o \
|
||||
src/libtommath/bn_mp_mul_2d.o \
|
||||
src/libtommath/bn_mp_fread.o \
|
||||
src/libtommath/bn_mp_init_set.o \
|
||||
src/libtommath/bn_mp_add_d.o \
|
||||
src/libtommath/bn_mp_zero.o \
|
||||
src/libtommath/bn_s_mp_add.o \
|
||||
src/libtommath/bn_mp_radix_size.o \
|
||||
src/libtommath/bn_mp_init_set_int.o \
|
||||
src/libtommath/bn_mp_n_root.o \
|
||||
src/libtommath/bn_mp_lshd.o \
|
||||
src/libtommath/bn_mp_reduce_is_2k.o \
|
||||
src/pklib/implode.o \
|
||||
src/pklib/crc32.o \
|
||||
src/pklib/explode.o \
|
||||
src/zlib/crc32.o \
|
||||
src/zlib/trees.o \
|
||||
src/zlib/compress2.o \
|
||||
src/zlib/adler32.o \
|
||||
src/zlib/inftrees.o \
|
||||
src/zlib/inffast.o \
|
||||
src/zlib/deflate.o \
|
||||
src/zlib/inflate.o \
|
||||
src/zlib/zutil.o \
|
||||
src/lzma/C/LzFind.o \
|
||||
src/lzma/C/LzmaEnc.o \
|
||||
src/lzma/C/LzmaDec.o \
|
||||
src/jenkins/lookup3.o
|
||||
|
||||
LIB = libStorm.so
|
||||
SLIB = libStorm.a
|
||||
|
||||
all: $(OBJS) $(COBJS) $(LIB) $(SLIB)
|
||||
|
||||
$(LIB): $(OBJS) $(COBJS)
|
||||
$(C++) $(ARCH) -shared -o $(LIB) $(OBJS) $(COBJS) $(LFLAGS)
|
||||
|
||||
$(SLIB): $(OBJS) $(COBJS)
|
||||
$(AR) rcs $(SLIB) $(OBJS) $(COBJS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(COBJS) $(LIB)
|
||||
|
||||
$(OBJS): %.o: %.cpp
|
||||
$(C++) -o $@ $(CFLAGS) -c $<
|
||||
|
||||
$(COBJS): %.o: %.c
|
||||
$(CC) -o $@ $(CFLAGS) -c $<
|
||||
|
||||
$(LIB): $(OBJS) $(COBJS)
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
install $(LIB) /usr/local/lib
|
||||
mkdir -p /usr/local/include/StormLib
|
||||
cp src/StormLib.h /usr/local/include/StormLib
|
||||
cp src/StormPort.h /usr/local/include/StormLib
|
||||
ldconfig
|
||||
253
src/dep/src/StormLib/Makefile.mac
Normal file
253
src/dep/src/StormLib/Makefile.mac
Normal file
@ -0,0 +1,253 @@
|
||||
#####################################################################
|
||||
#
|
||||
# Makefile for compiling StormLib with g++ on Mac
|
||||
#
|
||||
# Author: Ladislav Zezula
|
||||
# Created: Mon May 10 14:13:00 CEST 2010
|
||||
# System: Mac OS X (64bit)
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
CPP = g++
|
||||
CC = gcc
|
||||
CFLAGS = -Wall
|
||||
LFLAGS = -lbz2 -lz -framework Carbon
|
||||
ARCH = -arch x86_64
|
||||
DFLAGS = -D__SYS_BZLIB -D__SYS_ZLIB -D_7ZIP_ST
|
||||
AR = ar
|
||||
ARFLAGS= rcs
|
||||
|
||||
LIBRARY = libStorm.dylib
|
||||
|
||||
OBJS_CPP = src/adpcm/adpcm.obj \
|
||||
src/huffman/huff.obj \
|
||||
src/sparse/sparse.obj \
|
||||
src/FileStream.obj \
|
||||
src/SBaseCommon.o \
|
||||
src/SBaseFileTable.o \
|
||||
src/SCompression.obj \
|
||||
src/SFileAddFile.obj \
|
||||
src/SFileAttributes.obj \
|
||||
src/SFileCompactArchive.obj \
|
||||
src/SFileCreateArchive.obj \
|
||||
src/SFileExtractFile.obj \
|
||||
src/SFileFindFile.obj \
|
||||
src/SFileListFile.obj \
|
||||
src/SFileOpenArchive.obj \
|
||||
src/SFileOpenFileEx.obj \
|
||||
src/SFilePatchArchives.obj \
|
||||
src/SFileReadFile.obj \
|
||||
src/SFileVerify.obj
|
||||
|
||||
|
||||
OBJS_C = src/jenkins/lookup3.o \
|
||||
src/libtomcrypt/src/hashes/hash_memory.obj \
|
||||
src/libtomcrypt/src/hashes/md5.obj \
|
||||
src/libtomcrypt/src/hashes/sha1.obj\
|
||||
src/libtomcrypt/src/math/ltm_desc.obj \
|
||||
src/libtomcrypt/src/math/multi.obj \
|
||||
src/libtomcrypt/src/math/rand_prime.obj \
|
||||
src/libtomcrypt/src/misc/base64_decode.obj \
|
||||
src/libtomcrypt/src/misc/crypt_argchk.obj \
|
||||
src/libtomcrypt/src/misc/crypt_find_hash.obj \
|
||||
src/libtomcrypt/src/misc/crypt_find_prng.obj \
|
||||
src/libtomcrypt/src/misc/crypt_hash_descriptor.obj \
|
||||
src/libtomcrypt/src/misc/crypt_hash_is_valid.obj \
|
||||
src/libtomcrypt/src/misc/crypt_libc.obj \
|
||||
src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.obj \
|
||||
src/libtomcrypt/src/misc/crypt_prng_descriptor.obj \
|
||||
src/libtomcrypt/src/misc/crypt_prng_is_valid.obj \
|
||||
src/libtomcrypt/src/misc/crypt_register_hash.obj \
|
||||
src/libtomcrypt/src/misc/crypt_register_prng.obj \
|
||||
src/libtomcrypt/src/misc/zeromem.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_bit_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_boolean.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_choice.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_integer.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_octet_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_printable_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_short_integer.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utctime.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_bit_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_boolean.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_ia5_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_integer.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_object_identifier.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_octet_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_printable_string.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_sequence.obj \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_short_integer.obj \
|
||||
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utctime.obj \
|
||||
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utf8_string.obj \
|
||||
|
||||
src/libtomcrypt/src/pk/asn1/der_sequence_free.obj \
|
||||
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_map.obj \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.obj \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.obj \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_points.obj \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.obj \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.obj \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.obj \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.obj \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.obj \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.obj \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_exptmod.obj \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_free.obj \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_import.obj \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_make_key.obj \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_hash.obj \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_simple.obj \
|
||||
src/libtommath/bncore.obj \
|
||||
src/libtommath/bn_fast_mp_invmod.obj \
|
||||
src/libtommath/bn_fast_mp_montgomery_reduce.obj \
|
||||
src/libtommath/bn_fast_s_mp_mul_digs.obj \
|
||||
src/libtommath/bn_fast_s_mp_mul_high_digs.obj \
|
||||
src/libtommath/bn_fast_s_mp_sqr.obj \
|
||||
src/libtommath/bn_mp_2expt.obj \
|
||||
src/libtommath/bn_mp_abs.obj \
|
||||
src/libtommath/bn_mp_add.obj \
|
||||
src/libtommath/bn_mp_addmod.obj \
|
||||
src/libtommath/bn_mp_add_d.obj \
|
||||
src/libtommath/bn_mp_and.obj \
|
||||
src/libtommath/bn_mp_clamp.obj \
|
||||
src/libtommath/bn_mp_clear.obj \
|
||||
src/libtommath/bn_mp_clear_multi.obj \
|
||||
src/libtommath/bn_mp_cmp.obj \
|
||||
src/libtommath/bn_mp_cmp_d.obj \
|
||||
src/libtommath/bn_mp_cmp_mag.obj \
|
||||
src/libtommath/bn_mp_cnt_lsb.obj \
|
||||
src/libtommath/bn_mp_copy.obj \
|
||||
src/libtommath/bn_mp_count_bits.obj \
|
||||
src/libtommath/bn_mp_div.obj \
|
||||
src/libtommath/bn_mp_div_2.obj \
|
||||
src/libtommath/bn_mp_div_2d.obj \
|
||||
src/libtommath/bn_mp_div_3.obj \
|
||||
src/libtommath/bn_mp_div_d.obj \
|
||||
src/libtommath/bn_mp_dr_is_modulus.obj \
|
||||
src/libtommath/bn_mp_dr_reduce.obj \
|
||||
src/libtommath/bn_mp_dr_setup.obj \
|
||||
src/libtommath/bn_mp_exch.obj \
|
||||
src/libtommath/bn_mp_exptmod.obj \
|
||||
src/libtommath/bn_mp_exptmod_fast.obj \
|
||||
src/libtommath/bn_mp_expt_d.obj \
|
||||
src/libtommath/bn_mp_exteuclid.obj \
|
||||
src/libtommath/bn_mp_fread.obj \
|
||||
src/libtommath/bn_mp_fwrite.obj \
|
||||
src/libtommath/bn_mp_gcd.obj \
|
||||
src/libtommath/bn_mp_get_int.obj \
|
||||
src/libtommath/bn_mp_grow.obj \
|
||||
src/libtommath/bn_mp_init.obj \
|
||||
src/libtommath/bn_mp_init_copy.obj \
|
||||
src/libtommath/bn_mp_init_multi.obj \
|
||||
src/libtommath/bn_mp_init_set.obj \
|
||||
src/libtommath/bn_mp_init_set_int.obj \
|
||||
src/libtommath/bn_mp_init_size.obj \
|
||||
src/libtommath/bn_mp_invmod.obj \
|
||||
src/libtommath/bn_mp_invmod_slow.obj \
|
||||
src/libtommath/bn_mp_is_square.obj \
|
||||
src/libtommath/bn_mp_jacobi.obj \
|
||||
src/libtommath/bn_mp_karatsuba_mul.obj \
|
||||
src/libtommath/bn_mp_karatsuba_sqr.obj \
|
||||
src/libtommath/bn_mp_lcm.obj \
|
||||
src/libtommath/bn_mp_lshd.obj \
|
||||
src/libtommath/bn_mp_mod.obj \
|
||||
src/libtommath/bn_mp_mod_2d.obj \
|
||||
src/libtommath/bn_mp_mod_d.obj \
|
||||
src/libtommath/bn_mp_montgomery_calc_normalization.obj \
|
||||
src/libtommath/bn_mp_montgomery_reduce.obj \
|
||||
src/libtommath/bn_mp_montgomery_setup.obj \
|
||||
src/libtommath/bn_mp_mul.obj \
|
||||
src/libtommath/bn_mp_mulmod.obj \
|
||||
src/libtommath/bn_mp_mul_2.obj \
|
||||
src/libtommath/bn_mp_mul_2d.obj \
|
||||
src/libtommath/bn_mp_mul_d.obj \
|
||||
src/libtommath/bn_mp_neg.obj \
|
||||
src/libtommath/bn_mp_n_root.obj \
|
||||
src/libtommath/bn_mp_or.obj \
|
||||
src/libtommath/bn_mp_prime_fermat.obj \
|
||||
src/libtommath/bn_mp_prime_is_divisible.obj \
|
||||
src/libtommath/bn_mp_prime_is_prime.obj \
|
||||
src/libtommath/bn_mp_prime_miller_rabin.obj \
|
||||
src/libtommath/bn_mp_prime_next_prime.obj \
|
||||
src/libtommath/bn_mp_prime_rabin_miller_trials.obj \
|
||||
src/libtommath/bn_mp_prime_random_ex.obj \
|
||||
src/libtommath/bn_mp_radix_size.obj \
|
||||
src/libtommath/bn_mp_radix_smap.obj \
|
||||
src/libtommath/bn_mp_rand.obj \
|
||||
src/libtommath/bn_mp_read_radix.obj \
|
||||
src/libtommath/bn_mp_read_signed_bin.obj \
|
||||
src/libtommath/bn_mp_read_unsigned_bin.obj \
|
||||
src/libtommath/bn_mp_reduce.obj \
|
||||
src/libtommath/bn_mp_reduce_2k.obj \
|
||||
src/libtommath/bn_mp_reduce_2k_l.obj \
|
||||
src/libtommath/bn_mp_reduce_2k_setup.obj \
|
||||
src/libtommath/bn_mp_reduce_2k_setup_l.obj \
|
||||
src/libtommath/bn_mp_reduce_is_2k.obj \
|
||||
src/libtommath/bn_mp_reduce_is_2k_l.obj \
|
||||
src/libtommath/bn_mp_reduce_setup.obj \
|
||||
src/libtommath/bn_mp_rshd.obj \
|
||||
src/libtommath/bn_mp_set.obj \
|
||||
src/libtommath/bn_mp_set_int.obj \
|
||||
src/libtommath/bn_mp_shrink.obj \
|
||||
src/libtommath/bn_mp_signed_bin_size.obj \
|
||||
src/libtommath/bn_mp_sqr.obj \
|
||||
src/libtommath/bn_mp_sqrmod.obj \
|
||||
src/libtommath/bn_mp_sqrt.obj \
|
||||
src/libtommath/bn_mp_sub.obj \
|
||||
src/libtommath/bn_mp_submod.obj \
|
||||
src/libtommath/bn_mp_sub_d.obj \
|
||||
src/libtommath/bn_mp_toom_mul.obj \
|
||||
src/libtommath/bn_mp_toom_sqr.obj \
|
||||
src/libtommath/bn_mp_toradix.obj \
|
||||
src/libtommath/bn_mp_toradix_n.obj \
|
||||
src/libtommath/bn_mp_to_signed_bin.obj \
|
||||
src/libtommath/bn_mp_to_signed_bin_n.obj \
|
||||
src/libtommath/bn_mp_to_unsigned_bin.obj \
|
||||
src/libtommath/bn_mp_to_unsigned_bin_n.obj \
|
||||
src/libtommath/bn_mp_unsigned_bin_size.obj \
|
||||
src/libtommath/bn_mp_xor.obj \
|
||||
src/libtommath/bn_mp_zero.obj \
|
||||
src/libtommath/bn_prime_tab.obj \
|
||||
src/libtommath/bn_reverse.obj \
|
||||
src/libtommath/bn_s_mp_add.obj \
|
||||
src/libtommath/bn_s_mp_exptmod.obj \
|
||||
src/libtommath/bn_s_mp_mul_digs.obj \
|
||||
src/libtommath/bn_s_mp_mul_high_digs.obj \
|
||||
src/libtommath/bn_s_mp_sqr.obj \
|
||||
src/libtommath/bn_s_mp_sub.obj \
|
||||
src/lzma/C/LzFind.obj \
|
||||
src/lzma/C/LzmaDec.obj \
|
||||
src/lzma/C/LzmaEnc.obj \
|
||||
src/pklib/explode.obj \
|
||||
src/pklib/implode.obj
|
||||
|
||||
all: $(LIBRARY)
|
||||
|
||||
#clean:
|
||||
# rm -f $(OBJS) $(LIBRARY)
|
||||
|
||||
#install: $(LIBRARY)
|
||||
# install $(LIBRARY) /usr/local/lib
|
||||
# mkdir -p /usr/local/include/StormLib
|
||||
# cp StormLib.h /usr/local/include/StormLib
|
||||
# cp StormPort.h /usr/local/include/StormLib
|
||||
|
||||
$(LIBRARY): $(OBJS_C) $(OBJS_CPP)
|
||||
$(CPP) $(CFLAGS) $(DFLAGS) $(ARCH) $(LFLAGS) -shared -o $(LIBRARY) $(OBJS_C) $(OBJS_CPP)
|
||||
# $(AR) $(ARFLAGS) $(LIBRARY) $(OBJS_C) $(OBJS_CPP)
|
||||
|
||||
$(OBJS_C): %.obj: %.c
|
||||
$(CC) -o $@ $(CFLAGS) $(DFLAGS) -c $<
|
||||
|
||||
$(OBJS_CPP): %.obj: %.cpp
|
||||
$(CC) -o $@ $(CFLAGS) $(DFLAGS) -c $<
|
||||
|
||||
23
src/dep/src/StormLib/Publish.bat
Normal file
23
src/dep/src/StormLib/Publish.bat
Normal file
@ -0,0 +1,23 @@
|
||||
@echo off
|
||||
rem This BAT file updates the ZIP file that is to be uploaded to web
|
||||
rem Only use when both 32-bit and 64-bit are properly compiled
|
||||
|
||||
echo Creating stormlib.zip ...
|
||||
cd \Ladik\Appdir
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\doc\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\src\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\storm_dll\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\StormLib.xcodeproj\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\stormlib_dll\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\test\*
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\makefile*
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.bat
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.sln
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.vcproj
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.plist
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.txt
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.kdev4
|
||||
echo.
|
||||
|
||||
echo Press any key to exit ...
|
||||
pause >nul
|
||||
23
src/dep/src/StormLib/Publish_beta.bat
Normal file
23
src/dep/src/StormLib/Publish_beta.bat
Normal file
@ -0,0 +1,23 @@
|
||||
@echo off
|
||||
rem This BAT file updates the ZIP file that is to be uploaded to web
|
||||
rem Only use when both 32-bit and 64-bit are properly compiled
|
||||
|
||||
echo Creating stormlib_beta.zip ...
|
||||
cd \Ladik\Appdir
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\doc\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\src\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\storm_dll\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\StormLib.xcodeproj\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\stormlib_dll\*
|
||||
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\test\*
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\makefile*
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.bat
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.sln
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.vcproj
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.plist
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.txt
|
||||
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.kdev4
|
||||
echo.
|
||||
|
||||
echo Press any key to exit ...
|
||||
pause >nul
|
||||
@ -1,354 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SAttrFile.cpp Copyright (c) Ladislav Zezula 2007 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 12.06.04 1.00 Lad The first version of SAttrFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc/crc32.h"
|
||||
#include "misc/md5.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
// This function creates the name for the listfile.
|
||||
// the file will be created under unique name in the temporary directory
|
||||
static void GetAttributesFileName(TMPQArchive * /* ha */, char * szAttrFile)
|
||||
{
|
||||
char szTemp[MAX_PATH];
|
||||
|
||||
// Create temporary file name int TEMP directory
|
||||
GetTempPath(sizeof(szTemp)-1, szTemp);
|
||||
GetTempFileName(szTemp, ATTRIBUTES_NAME, 0, szAttrFile);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions (internal use by StormLib)
|
||||
|
||||
int SAttrFileCreate(TMPQArchive * ha)
|
||||
{
|
||||
TMPQAttr * pNewAttr;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// There should NOW be any attributes
|
||||
assert(ha->pAttributes == NULL);
|
||||
|
||||
pNewAttr = ALLOCMEM(TMPQAttr, 1);
|
||||
if(pNewAttr != NULL)
|
||||
{
|
||||
// Pre-set the structure
|
||||
pNewAttr->dwVersion = MPQ_ATTRIBUTES_V1;
|
||||
pNewAttr->dwFlags = 0;
|
||||
|
||||
// Allocate array for CRC32
|
||||
pNewAttr->pCrc32 = ALLOCMEM(TMPQCRC32, ha->pHeader->dwHashTableSize);
|
||||
if(pNewAttr->pCrc32 != NULL)
|
||||
{
|
||||
pNewAttr->dwFlags |= MPQ_ATTRIBUTE_CRC32;
|
||||
memset(pNewAttr->pCrc32, 0, sizeof(TMPQCRC32) * ha->pHeader->dwHashTableSize);
|
||||
}
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Allocate array for FILETIME
|
||||
pNewAttr->pFileTime = ALLOCMEM(TMPQFileTime, ha->pHeader->dwHashTableSize);
|
||||
if(pNewAttr->pFileTime != NULL)
|
||||
{
|
||||
pNewAttr->dwFlags |= MPQ_ATTRIBUTE_FILETIME;
|
||||
memset(pNewAttr->pFileTime, 0, sizeof(TMPQFileTime) * ha->pHeader->dwHashTableSize);
|
||||
}
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Allocate array for MD5
|
||||
pNewAttr->pMd5 = ALLOCMEM(TMPQMD5, ha->pHeader->dwHashTableSize);
|
||||
if(pNewAttr->pMd5 != NULL)
|
||||
{
|
||||
pNewAttr->dwFlags |= MPQ_ATTRIBUTE_MD5;
|
||||
memset(pNewAttr->pMd5, 0, sizeof(TMPQMD5) * ha->pHeader->dwHashTableSize);
|
||||
}
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// If something failed, then free the attributes structure
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
FreeMPQAttributes(pNewAttr);
|
||||
pNewAttr = NULL;
|
||||
}
|
||||
|
||||
ha->pAttributes = pNewAttr;
|
||||
return nError;
|
||||
}
|
||||
|
||||
|
||||
int SAttrFileLoad(TMPQArchive * ha)
|
||||
{
|
||||
TMPQAttr * pAttr = NULL;
|
||||
HANDLE hFile = NULL;
|
||||
DWORD dwBytesRead;
|
||||
DWORD dwToRead;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Initially, set the attrobutes to NULL
|
||||
ha->pAttributes = NULL;
|
||||
|
||||
// Attempt to open the "(attributes)" file.
|
||||
// If it's not there, we don't support attributes
|
||||
if(!SFileOpenFileEx((HANDLE)ha, ATTRIBUTES_NAME, 0, &hFile))
|
||||
nError = GetLastError();
|
||||
|
||||
// Allocate space for the TMPQAttributes
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pAttr = ALLOCMEM(TMPQAttr, 1);
|
||||
if(pAttr == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Load the content of the attributes file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(pAttr, 0, sizeof(TMPQAttr));
|
||||
|
||||
dwToRead = sizeof(DWORD) + sizeof(DWORD);
|
||||
SFileReadFile(hFile, pAttr, dwToRead, &dwBytesRead, NULL);
|
||||
if(dwBytesRead != dwToRead)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Verify format of the attributes
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(pAttr->dwVersion > MPQ_ATTRIBUTES_V1)
|
||||
nError = ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Load the CRC32 (if any)
|
||||
if(nError == ERROR_SUCCESS && (pAttr->dwFlags & MPQ_ATTRIBUTE_CRC32))
|
||||
{
|
||||
pAttr->pCrc32 = ALLOCMEM(TMPQCRC32, ha->pHeader->dwHashTableSize);
|
||||
if(pAttr->pCrc32 != NULL)
|
||||
{
|
||||
memset(pAttr->pCrc32, 0, sizeof(TMPQCRC32) * ha->pHeader->dwHashTableSize);
|
||||
dwToRead = sizeof(TMPQCRC32) * ha->pHeader->dwBlockTableSize;
|
||||
SFileReadFile(hFile, pAttr->pCrc32, dwToRead, &dwBytesRead, NULL);
|
||||
if(dwBytesRead != dwToRead)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
else
|
||||
{
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the FILETIMEs (if any)
|
||||
if(nError == ERROR_SUCCESS && (pAttr->dwFlags & MPQ_ATTRIBUTE_FILETIME))
|
||||
{
|
||||
pAttr->pFileTime = ALLOCMEM(TMPQFileTime, ha->pHeader->dwHashTableSize);
|
||||
if(pAttr->pFileTime != NULL)
|
||||
{
|
||||
memset(pAttr->pFileTime, 0, sizeof(TMPQFileTime) * ha->pHeader->dwHashTableSize);
|
||||
dwToRead = sizeof(TMPQFileTime) * ha->pHeader->dwBlockTableSize;
|
||||
SFileReadFile(hFile, pAttr->pFileTime, dwToRead, &dwBytesRead, NULL);
|
||||
if(dwBytesRead != dwToRead)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
else
|
||||
{
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the MD5 (if any)
|
||||
if(nError == ERROR_SUCCESS && (pAttr->dwFlags & MPQ_ATTRIBUTE_MD5))
|
||||
{
|
||||
pAttr->pMd5 = ALLOCMEM(TMPQMD5, ha->pHeader->dwHashTableSize);
|
||||
if(pAttr->pMd5 != NULL)
|
||||
{
|
||||
memset(pAttr->pMd5, 0, sizeof(TMPQMD5) * ha->pHeader->dwHashTableSize);
|
||||
dwToRead = sizeof(TMPQMD5) * ha->pHeader->dwBlockTableSize;
|
||||
SFileReadFile(hFile, pAttr->pMd5, dwToRead, &dwBytesRead, NULL);
|
||||
if(dwBytesRead != dwToRead)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
else
|
||||
{
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the attributes into the MPQ archive
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
ha->pAttributes = pAttr;
|
||||
pAttr = NULL;
|
||||
}
|
||||
|
||||
// Cleanup & exit
|
||||
FreeMPQAttributes(pAttr);
|
||||
SFileCloseFile(hFile);
|
||||
return nError;
|
||||
}
|
||||
|
||||
int SAttrFileSaveToMpq(TMPQArchive * ha)
|
||||
{
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
DWORD dwToWrite;
|
||||
DWORD dwWritten;
|
||||
LCID lcSave = lcLocale;
|
||||
char szAttrFile[MAX_PATH];
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// If there are no attributes, do nothing
|
||||
if(ha->pAttributes == NULL)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// Create the local attributes file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
GetAttributesFileName(ha, szAttrFile);
|
||||
hFile = CreateFile(szAttrFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Write the content of the attributes to the file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Write the header of the attributes file
|
||||
dwToWrite = sizeof(DWORD) + sizeof(DWORD);
|
||||
WriteFile(hFile, ha->pAttributes, dwToWrite, &dwWritten, NULL);
|
||||
if(dwWritten != dwToWrite)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
|
||||
// Write the array of CRC32
|
||||
if(nError == ERROR_SUCCESS && ha->pAttributes->pCrc32 != NULL)
|
||||
{
|
||||
dwToWrite = sizeof(TMPQCRC32) * ha->pHeader->dwBlockTableSize;
|
||||
WriteFile(hFile, ha->pAttributes->pCrc32, dwToWrite, &dwWritten, NULL);
|
||||
if(dwWritten != dwToWrite)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
|
||||
// Write the array of FILETIMEs
|
||||
if(nError == ERROR_SUCCESS && ha->pAttributes->pFileTime != NULL)
|
||||
{
|
||||
dwToWrite = sizeof(TMPQFileTime) * ha->pHeader->dwBlockTableSize;
|
||||
WriteFile(hFile, ha->pAttributes->pFileTime, dwToWrite, &dwWritten, NULL);
|
||||
if(dwWritten != dwToWrite)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
|
||||
// Write the array of MD5s
|
||||
if(nError == ERROR_SUCCESS && ha->pAttributes->pMd5 != NULL)
|
||||
{
|
||||
dwToWrite = sizeof(TMPQMD5) * ha->pHeader->dwBlockTableSize;
|
||||
WriteFile(hFile, ha->pAttributes->pMd5, dwToWrite, &dwWritten, NULL);
|
||||
if(dwWritten != dwToWrite)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
|
||||
// Add the attributes into MPQ
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
SFileSetLocale(LANG_NEUTRAL);
|
||||
nError = AddFileToArchive(ha, hFile, ATTRIBUTES_NAME, MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING, 0, SFILE_TYPE_DATA, NULL);
|
||||
lcLocale = lcSave;
|
||||
}
|
||||
|
||||
// Close the temporary file and delete it.
|
||||
// There is no FILE_FLAG_DELETE_ON_CLOSE on LINUX.
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hFile);
|
||||
DeleteFile(szAttrFile);
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
void FreeMPQAttributes(TMPQAttr * pAttr)
|
||||
{
|
||||
if(pAttr != NULL)
|
||||
{
|
||||
if(pAttr->pCrc32 != NULL)
|
||||
FREEMEM(pAttr->pCrc32);
|
||||
if(pAttr->pFileTime != NULL)
|
||||
FREEMEM(pAttr->pFileTime);
|
||||
if(pAttr->pMd5 != NULL)
|
||||
FREEMEM(pAttr->pMd5);
|
||||
|
||||
FREEMEM(pAttr);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public (exported) functions
|
||||
|
||||
BOOL WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags)
|
||||
{
|
||||
crc32_context crc32_ctx;
|
||||
md5_context md5_ctx;
|
||||
TMPQFile * hf;
|
||||
TMPQCRC32 Crc32;
|
||||
TMPQMD5 Md5;
|
||||
BYTE Buffer[0x1000];
|
||||
HANDLE hFile = NULL;
|
||||
DWORD dwBytesRead;
|
||||
BOOL bResult = TRUE;
|
||||
|
||||
// Attempt to open the file
|
||||
if(SFileOpenFileEx(hMpq, szFileName, 0, &hFile))
|
||||
{
|
||||
// Initialize the CRC32 and MD5 counters
|
||||
CRC32_Init(&crc32_ctx);
|
||||
MD5_Init(&md5_ctx);
|
||||
hf = (TMPQFile *)hFile;
|
||||
|
||||
// Go through entire file and update both CRC32 and MD5
|
||||
for(;;)
|
||||
{
|
||||
// Read data from file
|
||||
SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
|
||||
if(dwBytesRead == 0)
|
||||
break;
|
||||
|
||||
// Update CRC32 value
|
||||
if(dwFlags & MPQ_ATTRIBUTE_CRC32)
|
||||
CRC32_Update(&crc32_ctx, Buffer, (int)dwBytesRead);
|
||||
|
||||
// Update MD5 value
|
||||
if(dwFlags & MPQ_ATTRIBUTE_MD5)
|
||||
MD5_Update(&md5_ctx, Buffer, (int)dwBytesRead);
|
||||
}
|
||||
|
||||
// Check if the CRC32 matches
|
||||
if((dwFlags & MPQ_ATTRIBUTE_CRC32) && hf->pCrc32 != NULL)
|
||||
{
|
||||
CRC32_Finish(&crc32_ctx, (unsigned long *)&Crc32.dwValue);
|
||||
if(Crc32.dwValue != hf->pCrc32->dwValue)
|
||||
bResult = FALSE;
|
||||
}
|
||||
|
||||
// Check if MD5 matches
|
||||
if((dwFlags & MPQ_ATTRIBUTE_MD5) && hf->pMd5 != NULL)
|
||||
{
|
||||
MD5_Finish(&md5_ctx, Md5.Value);
|
||||
if(memcmp(Md5.Value, hf->pMd5->Value, sizeof(TMPQMD5)))
|
||||
bResult = FALSE;
|
||||
}
|
||||
|
||||
SFileCloseFile(hFile);
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,105 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SCommon.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Common functions for encryption/decryption from Storm.dll. Included by */
|
||||
/* SFile*** functions, do not include and do not use this file directly */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 24.03.03 1.00 Lad The first version of SFileCommon.h */
|
||||
/* 12.06.04 1.00 Lad Renamed to SCommon.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __SCOMMON_H__
|
||||
#define __SCOMMON_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StormLib private defines
|
||||
|
||||
#define SFILE_TYPE_DATA 0 // Process the file as data file
|
||||
#define SFILE_TYPE_WAVE 1 // Process the file as WAVe file
|
||||
|
||||
#define LISTFILE_ENTRY_DELETED (DWORD_PTR)(-2)
|
||||
#define LISTFILE_ENTRY_FREE (DWORD_PTR)(-1)
|
||||
|
||||
// Prevent problems with CRT "min" and "max" functions,
|
||||
// as they are not defined on all platforms
|
||||
#define STORMLIB_MIN(a, b) ((a < b) ? a : b)
|
||||
#define STORMLIB_MAX(a, b) ((a > b) ? a : b)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// External variables
|
||||
|
||||
extern TMPQArchive * pFirstOpen;
|
||||
extern LCID lcLocale;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Encryption and decryption functions
|
||||
|
||||
int PrepareStormBuffer();
|
||||
|
||||
void EncryptHashTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength);
|
||||
void DecryptHashTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength);
|
||||
TMPQHash * FindFreeHashEntry(TMPQArchive * ha, const char * szFileName);
|
||||
|
||||
void EncryptBlockTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength);
|
||||
void DecryptBlockTable(DWORD * pdwTable, BYTE * pbKey, DWORD dwLength);
|
||||
|
||||
DWORD DetectFileSeed(DWORD * block, DWORD decrypted);
|
||||
DWORD DetectFileSeed2(DWORD * block, UINT nDwords, ...);
|
||||
void EncryptMPQBlock(DWORD * pdwBlock, DWORD dwLength, DWORD dwSeed1);
|
||||
void DecryptMPQBlock(DWORD * pdwBlock, DWORD dwLength, DWORD dwSeed1);
|
||||
|
||||
DWORD DecryptHashIndex(TMPQArchive * ha, const char * szFileName);
|
||||
DWORD DecryptName1 (const char * szFileName);
|
||||
DWORD DecryptName2 (const char * szFileName);
|
||||
DWORD DecryptFileSeed (const char * szFileName);
|
||||
|
||||
TMPQHash * GetHashEntry (TMPQArchive * ha, const char * szFileName);
|
||||
TMPQHash * GetHashEntryEx(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compression and decompression functions
|
||||
|
||||
int Compress_pklib (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel);
|
||||
int Decompress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Checking functions
|
||||
|
||||
BOOL IsValidMpqHandle(TMPQArchive * ha);
|
||||
BOOL IsValidFileHandle(TMPQFile * hf);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Other functions
|
||||
|
||||
BOOL SFileOpenArchiveEx(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMPQ, DWORD dwAccessMode = GENERIC_READ);
|
||||
int AddInternalFile(TMPQArchive * ha, const char * szFileName);
|
||||
int AddFileToArchive(TMPQArchive * ha, HANDLE hFile, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality, int nFileType, BOOL * pbReplaced);
|
||||
int SetDataCompression(int nDataCompression);
|
||||
int SaveMPQTables(TMPQArchive * ha);
|
||||
void FreeMPQArchive(TMPQArchive *& ha);
|
||||
void FreeMPQFile(TMPQFile *& hf);
|
||||
|
||||
BOOL CheckWildCard(const char * szString, const char * szWildCard);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Attributes support
|
||||
|
||||
int SAttrFileCreate(TMPQArchive * ha);
|
||||
int SAttrFileLoad(TMPQArchive * ha);
|
||||
int SAttrFileSaveToMpq(TMPQArchive * ha);
|
||||
void FreeMPQAttributes(TMPQAttr * pAttr);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Listfile functions
|
||||
|
||||
int SListFileCreateListFile(TMPQArchive * ha);
|
||||
int SListFileCreateNode(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
|
||||
int SListFileRemoveNode(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
|
||||
void SListFileFreeListFile(TMPQArchive * ha);
|
||||
|
||||
int SListFileSaveToMpq(TMPQArchive * ha);
|
||||
|
||||
#endif // __SCOMMON_H__
|
||||
|
||||
@ -1,724 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SCompression.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* This module serves as a bridge between StormLib code and (de)compression */
|
||||
/* functions. All (de)compression calls go (and should only go) through this */
|
||||
/* module. No system headers should be included in this module to prevent */
|
||||
/* compile-time problems. */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 01.04.03 1.00 Lad The first version of SCompression.cpp */
|
||||
/* 19.11.03 1.01 Dan Big endian handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// Include functions from Pkware Data Compression Library
|
||||
#include "pklib/pklib.h"
|
||||
|
||||
// Include functions from zlib
|
||||
#ifndef __SYS_ZLIB
|
||||
#include "zlib/zlib.h" // Include functions from zlib
|
||||
#else
|
||||
#include <zlib.h> // If zlib is available on system, use this instead
|
||||
#endif
|
||||
|
||||
// Include functions from Huffmann compression
|
||||
#include "huffman/huff.h"
|
||||
|
||||
// Include functions from WAVe compression
|
||||
#include "wave/wave.h"
|
||||
|
||||
// Include functions from BZip2 compression library
|
||||
#ifndef __SYS_BZLIB
|
||||
#include "bzip2/bzlib.h" // Include functions from bzlib
|
||||
#else
|
||||
#include <bzlib.h> // If bzlib is available on system, use this instead
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local structures
|
||||
|
||||
// Information about the input and output buffers for pklib
|
||||
typedef struct
|
||||
{
|
||||
char * pInBuff; // Pointer to input data buffer
|
||||
int nInPos; // Current offset in input data buffer
|
||||
int nInBytes; // Number of bytes in the input buffer
|
||||
char * pOutBuff; // Pointer to output data buffer
|
||||
int nOutPos; // Position in the output buffer
|
||||
int nMaxOut; // Maximum number of bytes in the output buffer
|
||||
} TDataInfo;
|
||||
|
||||
// Table of compression functions
|
||||
typedef int (*COMPRESS)(char *, int *, char *, int, int *, int);
|
||||
typedef struct
|
||||
{
|
||||
unsigned long dwMask; // Compression mask
|
||||
COMPRESS Compress; // Compression function
|
||||
} TCompressTable;
|
||||
|
||||
// Table of decompression functions
|
||||
typedef int (*DECOMPRESS)(char *, int *, char *, int);
|
||||
typedef struct
|
||||
{
|
||||
unsigned long dwMask; // Decompression bit
|
||||
DECOMPRESS Decompress; // Decompression function
|
||||
} TDecompressTable;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* Support functions for Pkware Data Compression Library */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
// Function loads data from the input buffer. Used by Pklib's "implode"
|
||||
// and "explode" function as user-defined callback
|
||||
// Returns number of bytes loaded
|
||||
//
|
||||
// char * buf - Pointer to a buffer where to store loaded data
|
||||
// unsigned int * size - Max. number of bytes to read
|
||||
// void * param - Custom pointer, parameter of implode/explode
|
||||
|
||||
static unsigned int ReadInputData(char * buf, unsigned int * size, void * param)
|
||||
{
|
||||
TDataInfo * pInfo = (TDataInfo *)param;
|
||||
unsigned int nMaxAvail = (pInfo->nInBytes - pInfo->nInPos);
|
||||
unsigned int nToRead = *size;
|
||||
|
||||
// Check the case when not enough data available
|
||||
if(nToRead > nMaxAvail)
|
||||
nToRead = nMaxAvail;
|
||||
|
||||
// Load data and increment offsets
|
||||
memcpy(buf, pInfo->pInBuff + pInfo->nInPos, nToRead);
|
||||
pInfo->nInPos += nToRead;
|
||||
|
||||
return nToRead;
|
||||
}
|
||||
|
||||
// Function for store output data. Used by Pklib's "implode" and "explode"
|
||||
// as user-defined callback
|
||||
//
|
||||
// char * buf - Pointer to data to be written
|
||||
// unsigned int * size - Number of bytes to write
|
||||
// void * param - Custom pointer, parameter of implode/explode
|
||||
|
||||
static void WriteOutputData(char * buf, unsigned int * size, void * param)
|
||||
{
|
||||
TDataInfo * pInfo = (TDataInfo *)param;
|
||||
unsigned int nMaxWrite = (pInfo->nMaxOut - pInfo->nOutPos);
|
||||
unsigned int nToWrite = *size;
|
||||
|
||||
// Check the case when not enough space in the output buffer
|
||||
if(nToWrite > nMaxWrite)
|
||||
nToWrite = nMaxWrite;
|
||||
|
||||
// Write output data and increments offsets
|
||||
memcpy(pInfo->pOutBuff + pInfo->nOutPos, buf, nToWrite);
|
||||
pInfo->nOutPos += nToWrite;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* "80" is IMA ADPCM stereo (de)compression */
|
||||
/* "40" is IMA ADPCM mono (de)compression */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
int Compress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
|
||||
{
|
||||
// Prepare the compression level for the next compression
|
||||
// (After us, the Huffmann compression will be called)
|
||||
if(0 < nCmpLevel && nCmpLevel <= 2)
|
||||
{
|
||||
nCmpLevel = 4;
|
||||
*pCmpType = 6;
|
||||
}
|
||||
else if(nCmpLevel == 3)
|
||||
{
|
||||
nCmpLevel = 6;
|
||||
*pCmpType = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
nCmpLevel = 5;
|
||||
*pCmpType = 7;
|
||||
}
|
||||
*pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 1, nCmpLevel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Decompress_wave_mono(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
|
||||
{
|
||||
*pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Compress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
|
||||
{
|
||||
// Prepare the compression type for the next compression
|
||||
// (After us, the Huffmann compression will be called)
|
||||
if(0 < nCmpLevel && nCmpLevel <= 2)
|
||||
{
|
||||
nCmpLevel = 4;
|
||||
*pCmpType = 6;
|
||||
}
|
||||
else if(nCmpLevel == 3)
|
||||
{
|
||||
nCmpLevel = 6;
|
||||
*pCmpType = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
nCmpLevel = 5;
|
||||
*pCmpType = 7;
|
||||
}
|
||||
*pdwOutLength = CompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (short *)pbInBuffer, dwInLength, 2, nCmpLevel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Decompress_wave_stereo(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
|
||||
{
|
||||
*pdwOutLength = DecompressWave((unsigned char *)pbOutBuffer, *pdwOutLength, (unsigned char *)pbInBuffer, dwInLength, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* The "01" (de)compression is the Huffman (de)compression */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
// 1500F4C0
|
||||
int Compress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */)
|
||||
{
|
||||
THuffmannTree ht; // Huffmann tree for compression
|
||||
TOutputStream os; // Output stream
|
||||
|
||||
// Initialize output stream
|
||||
os.pbOutBuffer = (unsigned char *)pbOutBuffer;
|
||||
os.dwOutSize = *pdwOutLength;
|
||||
os.pbOutPos = (unsigned char *)pbOutBuffer;
|
||||
os.dwBitBuff = 0;
|
||||
os.nBits = 0;
|
||||
|
||||
// Initialize the Huffmann tree for compression
|
||||
ht.InitTree(true);
|
||||
|
||||
*pdwOutLength = ht.DoCompression(&os, (unsigned char *)pbInBuffer, dwInLength, *pCmpType);
|
||||
|
||||
// The following code is not necessary to run, because it has no
|
||||
// effect on the output data. It only clears the huffmann tree, but when
|
||||
// the tree is on the stack, who cares ?
|
||||
// ht.UninitTree();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 1500F5F0
|
||||
int Decompress_huff(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int /* dwInLength */)
|
||||
{
|
||||
THuffmannTree ht;
|
||||
TInputStream is;
|
||||
|
||||
// Initialize input stream
|
||||
is.pbInBuffer = (unsigned char *)pbInBuffer;
|
||||
is.BitBuffer = 0;
|
||||
is.BitCount = 0;
|
||||
|
||||
// Initialize the Huffmann tree for compression
|
||||
ht.InitTree(false);
|
||||
*pdwOutLength = ht.DoDecompression((unsigned char *)pbOutBuffer, *pdwOutLength, &is);
|
||||
|
||||
// The following code is not necessary to run, because it has no
|
||||
// effect on the output data. It only clears the huffmann tree, but when
|
||||
// the tree is on the stack, who cares ?
|
||||
// ht.UninitTree();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* The "02" (de)compression is the ZLIB (de)compression */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
int Compress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * /* pCmpType */, int /* nCmpLevel */)
|
||||
{
|
||||
z_stream z; // Stream information for zlib
|
||||
int nResult;
|
||||
|
||||
// Fill the stream structure for zlib
|
||||
z.next_in = (Bytef *)pbInBuffer;
|
||||
z.avail_in = (uInt)dwInLength;
|
||||
z.total_in = dwInLength;
|
||||
z.next_out = (Bytef *)pbOutBuffer;
|
||||
z.avail_out = *pdwOutLength;
|
||||
z.total_out = 0;
|
||||
z.zalloc = NULL;
|
||||
z.zfree = NULL;
|
||||
|
||||
// Initialize the compression structure. Storm.dll uses zlib version 1.1.3
|
||||
*pdwOutLength = 0;
|
||||
if((nResult = deflateInit(&z, Z_DEFAULT_COMPRESSION)) == 0)
|
||||
{
|
||||
// Call zlib to compress the data
|
||||
nResult = deflate(&z, Z_FINISH);
|
||||
|
||||
if(nResult == Z_OK || nResult == Z_STREAM_END)
|
||||
*pdwOutLength = z.total_out;
|
||||
|
||||
deflateEnd(&z);
|
||||
}
|
||||
return nResult;
|
||||
}
|
||||
|
||||
int Decompress_zlib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
|
||||
{
|
||||
z_stream z; // Stream information for zlib
|
||||
int nResult;
|
||||
|
||||
// Fill the stream structure for zlib
|
||||
z.next_in = (Bytef *)pbInBuffer;
|
||||
z.avail_in = (uInt)dwInLength;
|
||||
z.total_in = dwInLength;
|
||||
z.next_out = (Bytef *)pbOutBuffer;
|
||||
z.avail_out = *pdwOutLength;
|
||||
z.total_out = 0;
|
||||
z.zalloc = NULL;
|
||||
z.zfree = NULL;
|
||||
|
||||
// Initialize the decompression structure. Storm.dll uses zlib version 1.1.3
|
||||
if((nResult = inflateInit(&z)) == 0)
|
||||
{
|
||||
// Call zlib to decompress the data
|
||||
nResult = inflate(&z, Z_FINISH);
|
||||
*pdwOutLength = z.total_out;
|
||||
inflateEnd(&z);
|
||||
}
|
||||
return nResult;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* The "08" (de)compression is the Pkware DCL (de)compression */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
int Compress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int /* nCmpLevel */)
|
||||
{
|
||||
TDataInfo Info; // Data information
|
||||
char * work_buf = ALLOCMEM(char, CMP_BUFFER_SIZE);// Pklib's work buffer
|
||||
unsigned int dict_size; // Dictionary size
|
||||
unsigned int ctype; // Compression type
|
||||
|
||||
// Fill data information structure
|
||||
Info.pInBuff = pbInBuffer;
|
||||
Info.nInPos = 0;
|
||||
Info.nInBytes = dwInLength;
|
||||
Info.pOutBuff = pbOutBuffer;
|
||||
Info.nOutPos = 0;
|
||||
Info.nMaxOut = *pdwOutLength;
|
||||
|
||||
// Set the compression type and dictionary size
|
||||
ctype = (*pCmpType == 2) ? CMP_ASCII : CMP_BINARY;
|
||||
if (dwInLength < 0x600)
|
||||
dict_size = 0x400;
|
||||
else if(0x600 <= dwInLength && dwInLength < 0xC00)
|
||||
dict_size = 0x800;
|
||||
else
|
||||
dict_size = 0x1000;
|
||||
|
||||
// Do the compression
|
||||
implode(ReadInputData, WriteOutputData, work_buf, &Info, &ctype, &dict_size);
|
||||
*pdwOutLength = Info.nOutPos;
|
||||
FREEMEM(work_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Decompress_pklib(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
|
||||
{
|
||||
TDataInfo Info; // Data information
|
||||
char * work_buf = ALLOCMEM(char, EXP_BUFFER_SIZE);// Pklib's work buffer
|
||||
|
||||
// Fill data information structure
|
||||
Info.pInBuff = pbInBuffer;
|
||||
Info.nInPos = 0;
|
||||
Info.nInBytes = dwInLength;
|
||||
Info.pOutBuff = pbOutBuffer;
|
||||
Info.nOutPos = 0;
|
||||
Info.nMaxOut = *pdwOutLength;
|
||||
|
||||
// Do the decompression
|
||||
explode(ReadInputData, WriteOutputData, work_buf, &Info);
|
||||
|
||||
// Fix: If PKLIB is unable to decompress the data, they are uncompressed
|
||||
if(Info.nOutPos == 0)
|
||||
{
|
||||
Info.nOutPos = STORMLIB_MIN(*pdwOutLength, dwInLength);
|
||||
memcpy(pbOutBuffer, pbInBuffer, Info.nOutPos);
|
||||
}
|
||||
|
||||
*pdwOutLength = Info.nOutPos;
|
||||
FREEMEM(work_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* The "10" (de)compression is the Bzip2 (de)compression */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
int Compress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
|
||||
{
|
||||
bz_stream strm;
|
||||
int blockSize100k;
|
||||
int workFactor = 30;
|
||||
|
||||
// Keep compiler happy
|
||||
nCmpLevel = nCmpLevel;
|
||||
|
||||
// Initialize the BZLIB compression
|
||||
strm.bzalloc = NULL;
|
||||
strm.bzfree = NULL;
|
||||
|
||||
// Adjust the block size
|
||||
blockSize100k = *pCmpType;
|
||||
if(blockSize100k < 1 || blockSize100k > 9)
|
||||
blockSize100k = 9;
|
||||
|
||||
// Blizzard uses 9 as blockSize100k, (0 as workFactor)
|
||||
if(BZ2_bzCompressInit(&strm, blockSize100k, 0, workFactor) == 0)
|
||||
{
|
||||
strm.next_in = pbInBuffer;
|
||||
strm.avail_in = dwInLength;
|
||||
strm.next_out = pbOutBuffer;
|
||||
strm.avail_out = *pdwOutLength;
|
||||
|
||||
// Perform the compression
|
||||
while(BZ2_bzCompress(&strm, (strm.avail_in != 0) ? BZ_RUN : BZ_FINISH) != BZ_STREAM_END);
|
||||
|
||||
// Put the stream into idle state
|
||||
BZ2_bzCompressEnd(&strm);
|
||||
*pdwOutLength = strm.total_out_lo32;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdwOutLength = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Decompress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
|
||||
{
|
||||
bz_stream strm;
|
||||
int nResult = BZ_OK;
|
||||
|
||||
// Initialize the BZLIB decompression
|
||||
strm.bzalloc = NULL;
|
||||
strm.bzfree = NULL;
|
||||
if(BZ2_bzDecompressInit(&strm, 0, 0) == BZ_OK)
|
||||
{
|
||||
strm.next_in = pbInBuffer;
|
||||
strm.avail_in = dwInLength;
|
||||
strm.next_out = pbOutBuffer;
|
||||
strm.avail_out = *pdwOutLength;
|
||||
|
||||
// Perform the decompression
|
||||
while(nResult != BZ_STREAM_END)
|
||||
{
|
||||
nResult = BZ2_bzDecompress(&strm);
|
||||
|
||||
// If any error there, break the loop
|
||||
if(nResult < BZ_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
// Put the stream into idle state
|
||||
BZ2_bzDecompressEnd(&strm);
|
||||
|
||||
// If all succeeded, set the number of output bytes
|
||||
if(nResult >= BZ_OK)
|
||||
{
|
||||
*pdwOutLength = strm.total_out_lo32;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Something failed, so set number of output bytes to zero
|
||||
*pdwOutLength = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* SCompCompress */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
// This table contains compress functions which can be applied to
|
||||
// uncompressed blocks. Each bit set means the corresponding
|
||||
// compression method/function must be applied.
|
||||
//
|
||||
// WAVes compression Data compression
|
||||
// ------------------ -------------------
|
||||
// 1st block - 0x08 0x08 (D, HF, W2, SC, D2)
|
||||
// Rest blocks - 0x81 0x02 (W3)
|
||||
|
||||
static TCompressTable cmp_table[] =
|
||||
{
|
||||
{MPQ_COMPRESSION_WAVE_MONO, Compress_wave_mono}, // IMA ADPCM mono compression
|
||||
{MPQ_COMPRESSION_WAVE_STEREO, Compress_wave_stereo}, // IMA ADPCM stereo compression
|
||||
{MPQ_COMPRESSION_HUFFMANN, Compress_huff}, // Huffmann compression
|
||||
{MPQ_COMPRESSION_ZLIB, Compress_zlib}, // Compression with the "zlib" library
|
||||
{MPQ_COMPRESSION_PKWARE, Compress_pklib}, // Compression with Pkware DCL
|
||||
{MPQ_COMPRESSION_BZIP2, Compress_bzip2} // Compression Bzip2 library
|
||||
};
|
||||
|
||||
int WINAPI SCompCompress(char * pbCompressed, int * pdwOutLength, char * pbUncompressed, int dwInLength,
|
||||
int uCompressions, int nCmpType, int nCmpLevel)
|
||||
{
|
||||
char * pbTempBuff = NULL; // Temporary storage for decompressed data
|
||||
char * pbOutput = pbCompressed; // Current output buffer
|
||||
char * pbInput; // Current input buffer
|
||||
int uCompressions2;
|
||||
int dwCompressCount = 0;
|
||||
int dwDoneCount = 0;
|
||||
int dwOutSize = 0;
|
||||
int dwInSize = dwInLength;
|
||||
int dwEntries = (sizeof(cmp_table) / sizeof(TCompressTable));
|
||||
int nResult = 1;
|
||||
int i;
|
||||
|
||||
// Check for valid parameters
|
||||
if(!pdwOutLength || *pdwOutLength < dwInLength || !pbCompressed || !pbUncompressed)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Count the compressions
|
||||
for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++)
|
||||
{
|
||||
if(uCompressions & cmp_table[i].dwMask)
|
||||
dwCompressCount++;
|
||||
|
||||
uCompressions2 &= ~cmp_table[i].dwMask;
|
||||
}
|
||||
|
||||
// If a compression remains, do nothing
|
||||
if(uCompressions2 != 0)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If more that one compression, allocate intermediate buffer
|
||||
if(dwCompressCount >= 2)
|
||||
pbTempBuff = ALLOCMEM(char, *pdwOutLength + 1);
|
||||
|
||||
// Perform the compressions
|
||||
pbInput = pbUncompressed;
|
||||
dwInSize = dwInLength;
|
||||
for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++)
|
||||
{
|
||||
if(uCompressions2 & cmp_table[i].dwMask)
|
||||
{
|
||||
// Set the right output buffer
|
||||
dwCompressCount--;
|
||||
pbOutput = (dwCompressCount & 1) ? pbTempBuff : pbCompressed;
|
||||
|
||||
// Perform the partial compression
|
||||
dwOutSize = *pdwOutLength - 1;
|
||||
|
||||
cmp_table[i].Compress(pbOutput + 1, &dwOutSize, pbInput, dwInSize, &nCmpType, nCmpLevel);
|
||||
if(dwOutSize == 0)
|
||||
{
|
||||
SetLastError(ERROR_GEN_FAILURE);
|
||||
*pdwOutLength = 0;
|
||||
nResult = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the compression failed, copy the block instead
|
||||
if(dwOutSize >= dwInSize - 1)
|
||||
{
|
||||
if(dwDoneCount > 0)
|
||||
pbOutput++;
|
||||
|
||||
memcpy(pbOutput, pbInput, dwInSize);
|
||||
pbInput = pbOutput;
|
||||
uCompressions &= ~cmp_table[i].dwMask;
|
||||
dwOutSize = dwInSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
pbInput = pbOutput + 1;
|
||||
dwInSize = dwOutSize;
|
||||
dwDoneCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the compressed data to the correct output buffer
|
||||
if(nResult != 0)
|
||||
{
|
||||
if(uCompressions && (dwInSize + 1) < *pdwOutLength)
|
||||
{
|
||||
if(pbOutput != pbCompressed && pbOutput != pbCompressed + 1)
|
||||
memcpy(pbCompressed, pbOutput, dwInSize);
|
||||
*pbCompressed = (char)uCompressions;
|
||||
*pdwOutLength = dwInSize + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(pbCompressed, pbUncompressed, dwInSize);
|
||||
*pdwOutLength = dwInSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup and return
|
||||
if(pbTempBuff != NULL)
|
||||
FREEMEM(pbTempBuff);
|
||||
return nResult;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* SCompDecompress */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
// This table contains decompress functions which can be applied to
|
||||
// uncompressed blocks. The compression mask is stored in the first byte
|
||||
// of compressed block
|
||||
static TDecompressTable dcmp_table[] =
|
||||
{
|
||||
{MPQ_COMPRESSION_BZIP2, Decompress_bzip2}, // Decompression with Bzip2 library
|
||||
{MPQ_COMPRESSION_PKWARE, Decompress_pklib}, // Decompression with Pkware Data Compression Library
|
||||
{MPQ_COMPRESSION_ZLIB, Decompress_zlib}, // Decompression with the "zlib" library
|
||||
{MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression
|
||||
{MPQ_COMPRESSION_WAVE_STEREO, Decompress_wave_stereo}, // IMA ADPCM stereo decompression
|
||||
{MPQ_COMPRESSION_WAVE_MONO, Decompress_wave_mono} // IMA ADPCM mono decompression
|
||||
};
|
||||
|
||||
int WINAPI SCompDecompress(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
|
||||
{
|
||||
char * pbTempBuff = NULL; // Temporary storage for decompressed data
|
||||
char * pbWorkBuff = NULL; // Where to store decompressed data
|
||||
int dwOutLength = *pdwOutLength; // For storage number of output bytes
|
||||
unsigned fDecompressions1; // Decompressions applied to the block
|
||||
unsigned fDecompressions2; // Just another copy of decompressions applied to the block
|
||||
int dwCount = 0; // Counter for every use
|
||||
int dwEntries = (sizeof(dcmp_table) / sizeof(TDecompressTable));
|
||||
int nResult = 1;
|
||||
int i;
|
||||
|
||||
// If the input length is the same as output, do nothing.
|
||||
if(dwInLength == dwOutLength)
|
||||
{
|
||||
if(pbInBuffer == pbOutBuffer)
|
||||
return 1;
|
||||
|
||||
memcpy(pbOutBuffer, pbInBuffer, dwInLength);
|
||||
*pdwOutLength = dwInLength;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get applied compression types and decrement data length
|
||||
fDecompressions1 = fDecompressions2 = (unsigned char)*pbInBuffer++;
|
||||
dwInLength--;
|
||||
|
||||
// Search decompression table type and get all types of compression
|
||||
for(i = 0; i < dwEntries; i++)
|
||||
{
|
||||
// We have to apply this decompression ?
|
||||
if(fDecompressions1 & dcmp_table[i].dwMask)
|
||||
dwCount++;
|
||||
|
||||
// Clear this flag from temporary variable.
|
||||
fDecompressions2 &= ~dcmp_table[i].dwMask;
|
||||
}
|
||||
|
||||
// Check if there is some method unhandled
|
||||
// (E.g. compressed by future versions)
|
||||
if(fDecompressions2 != 0)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If there is more than only one compression, we have to allocate extra buffer
|
||||
if(dwCount >= 2)
|
||||
pbTempBuff = ALLOCMEM(char, dwOutLength);
|
||||
|
||||
// Apply all decompressions
|
||||
for(i = 0, dwCount = 0; i < dwEntries; i++)
|
||||
{
|
||||
// If not used this kind of compression, skip the loop
|
||||
if(fDecompressions1 & dcmp_table[i].dwMask)
|
||||
{
|
||||
// If odd case, use target buffer for output, otherwise use allocated tempbuffer
|
||||
pbWorkBuff = (dwCount++ & 1) ? pbTempBuff : pbOutBuffer;
|
||||
dwOutLength = *pdwOutLength;
|
||||
|
||||
// Decompress buffer using corresponding function
|
||||
dcmp_table[i].Decompress(pbWorkBuff, &dwOutLength, pbInBuffer, dwInLength);
|
||||
if(dwOutLength == 0)
|
||||
{
|
||||
SetLastError(ERROR_GEN_FAILURE);
|
||||
nResult = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Move output length to src length for next compression
|
||||
dwInLength = dwOutLength;
|
||||
pbInBuffer = pbWorkBuff;
|
||||
}
|
||||
}
|
||||
|
||||
// If output buffer is not the same like target buffer, we have to copy data
|
||||
if(nResult != 0)
|
||||
{
|
||||
if(pbWorkBuff != pbOutBuffer)
|
||||
memcpy(pbOutBuffer, pbInBuffer, dwOutLength);
|
||||
|
||||
}
|
||||
|
||||
// Delete temporary buffer, if necessary
|
||||
if(pbTempBuff != NULL)
|
||||
FREEMEM(pbTempBuff);
|
||||
|
||||
*pdwOutLength = dwOutLength;
|
||||
return nResult;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* SCompSetDataCompression */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
int WINAPI SCompSetDataCompression(int nDataCompression)
|
||||
{
|
||||
int nValidMask = (MPQ_COMPRESSION_ZLIB | MPQ_COMPRESSION_PKWARE | MPQ_COMPRESSION_BZIP2);
|
||||
|
||||
if((nDataCompression & nValidMask) != nDataCompression)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetDataCompression(nDataCompression);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -1,686 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileCompactArchive.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Archive compacting function */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 14.04.03 1.00 Lad Splitted from SFileCreateArchiveEx.cpp */
|
||||
/* 19.11.03 1.01 Dan Big endian handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local structures */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local variables */
|
||||
/*****************************************************************************/
|
||||
|
||||
static COMPACTCB CompactCB = NULL;
|
||||
static void * lpUserData = NULL;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
// Creates a copy of hash table
|
||||
static TMPQHash * CopyHashTable(TMPQArchive * ha)
|
||||
{
|
||||
TMPQHash * pHashTableCopy = ALLOCMEM(TMPQHash, ha->pHeader->dwHashTableSize);
|
||||
|
||||
if(pHashTableCopy != NULL)
|
||||
memcpy(pHashTableCopy, ha->pHashTable, sizeof(TMPQHash) * ha->pHeader->dwHashTableSize);
|
||||
|
||||
return pHashTableCopy;
|
||||
}
|
||||
|
||||
static int CheckIfAllFilesKnown(TMPQArchive * ha, const char * szListFile, DWORD * pFileSeeds)
|
||||
{
|
||||
TMPQHash * pHashTableCopy = NULL; // Copy of the hash table
|
||||
TMPQHash * pHash;
|
||||
TMPQHash * pHashEnd = NULL; // End of the hash table
|
||||
DWORD dwFileCount = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// First of all, create a copy of hash table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((pHashTableCopy = CopyHashTable(ha)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
pHashEnd = pHashTableCopy + ha->pHeader->dwHashTableSize;
|
||||
|
||||
// Notify the user
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(lpUserData, CCB_CHECKING_FILES, 0, ha->pHeader->dwBlockTableSize);
|
||||
}
|
||||
|
||||
// Now check all the files from the filelist
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
SFILE_FIND_DATA wf;
|
||||
HANDLE hFind = SFileFindFirstFile((HANDLE)ha, "*", &wf, szListFile);
|
||||
BOOL bResult = TRUE;
|
||||
|
||||
// Do while some files have been found
|
||||
while(hFind != NULL && bResult)
|
||||
{
|
||||
TMPQHash * pHash = GetHashEntry(ha, wf.cFileName);
|
||||
|
||||
// If the hash table entry has been found, find it's position
|
||||
// in the hash table copy
|
||||
if(pHash != NULL)
|
||||
{
|
||||
pHash = pHashTableCopy + (pHash - ha->pHashTable);
|
||||
if(pHash->dwName1 != (DWORD)-1 && pHash->dwName2 != (DWORD)-1)
|
||||
{
|
||||
TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex;
|
||||
DWORD dwSeed = 0;
|
||||
|
||||
// Resolve the file seed. Use plain file name for it
|
||||
if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
char * szFileName = strrchr(wf.cFileName, '\\');
|
||||
|
||||
if(szFileName == NULL)
|
||||
szFileName = wf.cFileName;
|
||||
else
|
||||
szFileName++;
|
||||
|
||||
dwSeed = DecryptFileSeed(szFileName);
|
||||
if(pBlock->dwFlags & MPQ_FILE_FIXSEED)
|
||||
dwSeed = (dwSeed + pBlock->dwFilePos) ^ pBlock->dwFSize;
|
||||
}
|
||||
pFileSeeds[pHash->dwBlockIndex] = dwSeed;
|
||||
|
||||
pHash->dwName1 = 0xFFFFFFFF;
|
||||
pHash->dwName2 = 0xFFFFFFFF;
|
||||
pHash->lcLocale = 0xFFFF;
|
||||
pHash->wPlatform = 0xFFFF;
|
||||
pHash->dwBlockIndex = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
// Notify the user
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(lpUserData, CCB_CHECKING_FILES, ++dwFileCount, ha->pHeader->dwBlockTableSize);
|
||||
|
||||
// Find the next file in the archive
|
||||
bResult = SFileFindNextFile(hFind, &wf);
|
||||
}
|
||||
|
||||
if(hFind != NULL)
|
||||
SFileFindClose(hFind);
|
||||
}
|
||||
|
||||
// When the filelist checking is complete, parse the hash table copy and find the
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Notify the user about checking hash table
|
||||
dwFileCount = 0;
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(lpUserData, CCB_CHECKING_HASH_TABLE, dwFileCount, ha->pHeader->dwBlockTableSize);
|
||||
|
||||
for(pHash = pHashTableCopy; pHash < pHashEnd; pHash++)
|
||||
{
|
||||
// If there is an unresolved entry, try to detect its seed. If it fails,
|
||||
// we cannot complete the work
|
||||
if(pHash->dwBlockIndex < ha->pHeader->dwBlockTableSize)
|
||||
{
|
||||
HANDLE hFile = NULL;
|
||||
DWORD dwFlags = 0;
|
||||
DWORD dwSeed = 0;
|
||||
|
||||
if(SFileOpenFileEx((HANDLE)ha, (char *)(DWORD_PTR)pHash->dwBlockIndex, SFILE_OPEN_BY_INDEX, &hFile))
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
dwFlags = hf->pBlock->dwFlags;
|
||||
dwSeed = hf->dwSeed1;
|
||||
SFileCloseFile(hFile);
|
||||
}
|
||||
|
||||
// If the file is encrypted, we have to check
|
||||
// If we can apply the file decryption seed
|
||||
if(dwFlags & MPQ_FILE_ENCRYPTED && dwSeed == 0)
|
||||
{
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Remember the seed
|
||||
pFileSeeds[pHash->dwBlockIndex] = dwSeed;
|
||||
|
||||
// Notify the user
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(lpUserData, CCB_CHECKING_HASH_TABLE, ++dwFileCount, ha->pHeader->dwBlockTableSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the copy of hash table
|
||||
if(pHashTableCopy != NULL)
|
||||
FREEMEM(pHashTableCopy);
|
||||
return nError;
|
||||
}
|
||||
|
||||
// Copies all file blocks into another archive.
|
||||
static int CopyMpqFileBlocks(
|
||||
HANDLE hFile,
|
||||
TMPQArchive * ha,
|
||||
TMPQBlockEx * pBlockEx,
|
||||
TMPQBlock * pBlock,
|
||||
DWORD dwSeed)
|
||||
{
|
||||
LARGE_INTEGER FilePos = {0};
|
||||
DWORD * pdwBlockPos2 = NULL; // File block positions to be written to target file
|
||||
DWORD * pdwBlockPos = NULL; // File block positions (unencrypted)
|
||||
BYTE * pbBlock = NULL; // Buffer for the file block
|
||||
DWORD dwTransferred; // Number of bytes transferred
|
||||
DWORD dwCSize = 0; // Compressed file size
|
||||
DWORD dwBytes = 0; // Number of bytes
|
||||
DWORD dwSeed1 = 0; // File seed used for decryption
|
||||
DWORD dwSeed2 = 0; // File seed used for encryption
|
||||
DWORD nBlocks = 0; // Number of file blocks
|
||||
DWORD nBlock = 0; // Currently processed file block
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// When file length is zero, do nothing
|
||||
if(pBlock->dwFSize == 0)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// Calculate number of blocks in the file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nBlocks = pBlock->dwFSize / ha->dwBlockSize;
|
||||
if(pBlock->dwFSize % ha->dwBlockSize)
|
||||
nBlocks++;
|
||||
pbBlock = ALLOCMEM(BYTE, ha->dwBlockSize);
|
||||
if(pbBlock == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Set the position to the begin of the file within archive
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
FilePos.HighPart = pBlockEx->wFilePosHigh;
|
||||
FilePos.LowPart = pBlock->dwFilePos;
|
||||
FilePos.QuadPart += ha->MpqPos.QuadPart;
|
||||
if(SetFilePointer(ha->hFile, FilePos.LowPart, &FilePos.HighPart, FILE_BEGIN) != FilePos.LowPart)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Remember the position in the destination file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
FilePos.HighPart = 0;
|
||||
FilePos.LowPart = SetFilePointer(hFile, 0, &FilePos.HighPart, FILE_CURRENT);
|
||||
}
|
||||
|
||||
// Resolve decryption seeds. The 'dwSeed' parameter is the decryption
|
||||
// seed for the file.
|
||||
if(nError == ERROR_SUCCESS && (pBlock->dwFlags & MPQ_FILE_ENCRYPTED))
|
||||
{
|
||||
dwSeed1 = dwSeed;
|
||||
if(pBlock->dwFlags & MPQ_FILE_FIXSEED)
|
||||
dwSeed = (dwSeed1 ^ pBlock->dwFSize) - pBlock->dwFilePos;
|
||||
|
||||
dwSeed2 = dwSeed;
|
||||
if(pBlock->dwFlags & MPQ_FILE_FIXSEED)
|
||||
dwSeed2 = (dwSeed + (DWORD)(FilePos.QuadPart - ha->MpqPos.QuadPart)) ^ pBlock->dwFSize;
|
||||
}
|
||||
|
||||
// Load the file positions from the archive and save it to the target file
|
||||
// (only if the file is compressed)
|
||||
if(pBlock->dwFlags & MPQ_FILE_COMPRESSED)
|
||||
{
|
||||
// Allocate buffers
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pdwBlockPos = ALLOCMEM(DWORD, nBlocks + 2);
|
||||
pdwBlockPos2 = ALLOCMEM(DWORD, nBlocks + 2);
|
||||
|
||||
if(pdwBlockPos == NULL || pdwBlockPos2 == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Load the block positions
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
dwBytes = (nBlocks + 1) * sizeof(DWORD);
|
||||
if(pBlock->dwFlags & MPQ_FILE_HAS_EXTRA)
|
||||
dwBytes += sizeof(DWORD);
|
||||
|
||||
ReadFile(ha->hFile, pdwBlockPos, dwBytes, &dwTransferred, NULL);
|
||||
if(dwTransferred != dwBytes)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Re-encrypt the block table positions
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED(pdwBlockPos, dwBytes / sizeof(DWORD));
|
||||
if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
DecryptMPQBlock(pdwBlockPos, dwBytes, dwSeed1 - 1);
|
||||
if(pdwBlockPos[0] != dwBytes)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
memcpy(pdwBlockPos2, pdwBlockPos, dwBytes);
|
||||
EncryptMPQBlock(pdwBlockPos2, dwBytes, dwSeed2 - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pdwBlockPos2, pdwBlockPos, dwBytes);
|
||||
}
|
||||
BSWAP_ARRAY32_UNSIGNED(pdwBlockPos2, dwBytes / sizeof(DWORD));
|
||||
}
|
||||
|
||||
// Write to the target file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
WriteFile(hFile, pdwBlockPos2, dwBytes, &dwTransferred, NULL);
|
||||
dwCSize += dwTransferred;
|
||||
if(dwTransferred != dwBytes)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we have to copy all file blocks. We will do it without
|
||||
// recompression, because re-compression is not necessary in this case
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
for(nBlock = 0; nBlock < nBlocks; nBlock++)
|
||||
{
|
||||
// Fix: The last block must not be exactly the size of one block.
|
||||
dwBytes = ha->dwBlockSize;
|
||||
if(nBlock == nBlocks - 1)
|
||||
{
|
||||
dwBytes = pBlock->dwFSize - (ha->dwBlockSize * (nBlocks - 1));
|
||||
}
|
||||
|
||||
if(pBlock->dwFlags & MPQ_FILE_COMPRESSED)
|
||||
dwBytes = pdwBlockPos[nBlock+1] - pdwBlockPos[nBlock];
|
||||
|
||||
// Read the file block
|
||||
ReadFile(ha->hFile, pbBlock, dwBytes, &dwTransferred, NULL);
|
||||
if(dwTransferred != dwBytes)
|
||||
{
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
break;
|
||||
}
|
||||
|
||||
// If necessary, re-encrypt the block
|
||||
// Note: Recompression is not necessary here. Unlike encryption,
|
||||
// the compression does not depend on the position of the file in MPQ.
|
||||
if((pBlock->dwFlags & MPQ_FILE_ENCRYPTED) && dwSeed1 != dwSeed2)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED((DWORD *)pbBlock, dwBytes/sizeof(DWORD));
|
||||
DecryptMPQBlock((DWORD *)pbBlock, dwBytes, dwSeed1 + nBlock);
|
||||
EncryptMPQBlock((DWORD *)pbBlock, dwBytes, dwSeed2 + nBlock);
|
||||
BSWAP_ARRAY32_UNSIGNED((DWORD *)pbBlock, dwBytes/sizeof(DWORD));
|
||||
}
|
||||
|
||||
// Now write the block back to the file
|
||||
WriteFile(hFile, pbBlock, dwBytes, &dwTransferred, NULL);
|
||||
dwCSize += dwTransferred;
|
||||
if(dwTransferred != dwBytes)
|
||||
{
|
||||
nError = ERROR_DISK_FULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the file extras, if any
|
||||
// These extras does not seem to be encrypted, and their purpose is unknown
|
||||
if(nError == ERROR_SUCCESS && (pBlock->dwFlags & MPQ_FILE_HAS_EXTRA))
|
||||
{
|
||||
dwBytes = pdwBlockPos[nBlocks + 1] - pdwBlockPos[nBlocks];
|
||||
if(dwBytes != 0)
|
||||
{
|
||||
ReadFile(ha->hFile, pbBlock, dwBytes, &dwTransferred, NULL);
|
||||
if(dwTransferred == dwBytes)
|
||||
{
|
||||
WriteFile(hFile, pbBlock, dwBytes, &dwTransferred, NULL);
|
||||
dwCSize += dwTransferred;
|
||||
if(dwTransferred != dwBytes)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update file position in the block table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// At this point, number of bytes written should be exactly
|
||||
// the same like the compressed file size. If it isn't, there's something wrong
|
||||
// (maybe new archive version ?)
|
||||
assert(dwCSize == pBlock->dwCSize);
|
||||
|
||||
// Update file pos in the block table
|
||||
FilePos.QuadPart -= ha->MpqPos.QuadPart;
|
||||
pBlockEx->wFilePosHigh = (USHORT)FilePos.HighPart;
|
||||
pBlock->dwFilePos = FilePos.LowPart;
|
||||
}
|
||||
|
||||
// Cleanup and return
|
||||
if(pdwBlockPos2 != NULL)
|
||||
FREEMEM(pdwBlockPos2);
|
||||
if(pdwBlockPos != NULL)
|
||||
FREEMEM(pdwBlockPos);
|
||||
if(pbBlock != NULL)
|
||||
FREEMEM(pbBlock);
|
||||
return nError;
|
||||
}
|
||||
|
||||
|
||||
static int CopyNonMpqData(
|
||||
HANDLE hSrcFile,
|
||||
HANDLE hTrgFile,
|
||||
LARGE_INTEGER & DataSizeToCopy)
|
||||
{
|
||||
LARGE_INTEGER DataSize = DataSizeToCopy;
|
||||
DWORD dwTransferred;
|
||||
DWORD dwToRead;
|
||||
char DataBuffer[0x1000];
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
while(DataSize.QuadPart > 0)
|
||||
{
|
||||
// Get the proper size of data
|
||||
dwToRead = sizeof(DataBuffer);
|
||||
if(DataSize.HighPart == 0 && DataSize.LowPart < dwToRead)
|
||||
dwToRead = DataSize.LowPart;
|
||||
|
||||
// Read the source file
|
||||
ReadFile(hSrcFile, DataBuffer, dwToRead, &dwTransferred, NULL);
|
||||
if(dwTransferred != dwToRead)
|
||||
{
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Write to the target file
|
||||
WriteFile(hTrgFile, DataBuffer, dwToRead, &dwTransferred, NULL);
|
||||
if(dwTransferred != dwToRead)
|
||||
{
|
||||
nError = ERROR_DISK_FULL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Decrement the number of data to be copied
|
||||
DataSize.QuadPart -= dwTransferred;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static int CopyMpqFiles(HANDLE hFile, TMPQArchive * ha, DWORD * pFileSeeds)
|
||||
{
|
||||
TMPQBlockEx * pBlockEx;
|
||||
TMPQBlock * pBlock;
|
||||
DWORD dwSeed1;
|
||||
DWORD dwIndex;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Walk through all files and write them to the destination MPQ archive
|
||||
for(dwIndex = 0; dwIndex < ha->pHeader->dwBlockTableSize; dwIndex++)
|
||||
{
|
||||
pBlockEx = ha->pExtBlockTable + dwIndex;
|
||||
pBlock = ha->pBlockTable + dwIndex;
|
||||
dwSeed1 = pFileSeeds[dwIndex];
|
||||
|
||||
// Notify the caller about work
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(lpUserData, CCB_COMPACTING_FILES, dwIndex, ha->pHeader->dwBlockTableSize);
|
||||
|
||||
// Copy all the file blocks
|
||||
// Debug: Break at (dwIndex == 5973)
|
||||
if(pBlock->dwFlags & MPQ_FILE_EXISTS)
|
||||
{
|
||||
nError = CopyMpqFileBlocks(hFile, ha, pBlockEx, pBlock, dwSeed1);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup and exit
|
||||
return nError;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
BOOL WINAPI SFileSetCompactCallback(HANDLE /* hMPQ */, COMPACTCB aCompactCB, void * lpData)
|
||||
{
|
||||
CompactCB = aCompactCB;
|
||||
lpUserData = lpData;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Archive compacting (incomplete)
|
||||
|
||||
BOOL WINAPI SFileCompactArchive(HANDLE hMPQ, const char * szListFile, BOOL /* bReserved */)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
DWORD * pFileSeeds = NULL;
|
||||
char szTempFile[MAX_PATH] = "";
|
||||
char * szTemp = NULL;
|
||||
DWORD dwTransferred;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Test the valid parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Create the table with file seeds
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((pFileSeeds = ALLOCMEM(DWORD, ha->pHeader->dwBlockTableSize)) != NULL)
|
||||
memset(pFileSeeds, 0, sizeof(DWORD) * ha->pHeader->dwBlockTableSize);
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// First of all, we have to check of we are able to decrypt all files.
|
||||
// If not, sorry, but the archive cannot be compacted.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = CheckIfAllFilesKnown(ha, szListFile, pFileSeeds);
|
||||
|
||||
// Get the temporary file name and create it
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(lpUserData, CCB_COPYING_NON_MPQ_DATA, 0, 0);
|
||||
|
||||
strcpy(szTempFile, ha->szFileName);
|
||||
if((szTemp = strrchr(szTempFile, '.')) != NULL)
|
||||
strcpy(szTemp + 1, "mp_");
|
||||
else
|
||||
strcat(szTempFile, "_");
|
||||
|
||||
hFile = CreateFile(szTempFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Write the data before MPQ header (if any)
|
||||
if(nError == ERROR_SUCCESS && ha->MpqPos.QuadPart > 0)
|
||||
{
|
||||
SetFilePointer(ha->hFile, 0, NULL, FILE_BEGIN);
|
||||
if(ha->pShunt != NULL)
|
||||
nError = CopyNonMpqData(ha->hFile, hFile, ha->ShuntPos);
|
||||
else
|
||||
nError = CopyNonMpqData(ha->hFile, hFile, ha->MpqPos);
|
||||
}
|
||||
|
||||
// Write the MPQ shunt (if any)
|
||||
if(nError == ERROR_SUCCESS && ha->pShunt != NULL)
|
||||
{
|
||||
BSWAP_TMPQSHUNT(ha->pShunt);
|
||||
WriteFile(hFile, ha->pShunt, sizeof(TMPQShunt), &dwTransferred, NULL);
|
||||
BSWAP_TMPQSHUNT(ha->pShunt);
|
||||
|
||||
if(dwTransferred != sizeof(TMPQShunt))
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
|
||||
// Write the data between MPQ shunt and the MPQ header (if any)
|
||||
if(nError == ERROR_SUCCESS && ha->pShunt != NULL)
|
||||
{
|
||||
LARGE_INTEGER BytesToCopy;
|
||||
|
||||
BytesToCopy.QuadPart = ha->MpqPos.QuadPart - (ha->ShuntPos.QuadPart + sizeof(TMPQShunt));
|
||||
nError = CopyNonMpqData(ha->hFile, hFile, BytesToCopy);
|
||||
}
|
||||
|
||||
// Write the MPQ header
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
BSWAP_TMPQHEADER(ha->pHeader);
|
||||
WriteFile(hFile, ha->pHeader, ha->pHeader->dwHeaderSize, &dwTransferred, NULL);
|
||||
BSWAP_TMPQHEADER(ha->pHeader);
|
||||
if(dwTransferred != ha->pHeader->dwHeaderSize)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
|
||||
// Write the data between the header and between the first file
|
||||
// For this, we have to determine where the first file begins
|
||||
// Ladik: While this seems to be useful at first sight,
|
||||
// it makes SFileCompactArchive useless, when there's just one file
|
||||
// in a MPQ that has been rewritten.
|
||||
/*
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
LARGE_INTEGER FirstFilePos;
|
||||
LARGE_INTEGER TempPos;
|
||||
TMPQBlockEx * pBlockEx = ha->pExtBlockTable;
|
||||
TMPQBlock * pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize;
|
||||
TMPQBlock * pBlock = ha->pBlockTable;
|
||||
|
||||
// Maximum file position
|
||||
FirstFilePos.HighPart = 0x7FFFFFFF;
|
||||
FirstFilePos.LowPart = 0xFFFFFFFF;
|
||||
|
||||
// Find the block with the least position in the MPQ
|
||||
while(pBlock < pBlockEnd)
|
||||
{
|
||||
TempPos.HighPart = pBlockEx->wFilePosHigh;
|
||||
TempPos.LowPart = pBlock->dwFilePos;
|
||||
if(TempPos.QuadPart < FirstFilePos.QuadPart)
|
||||
FirstFilePos = TempPos;
|
||||
|
||||
pBlockEx++;
|
||||
pBlock++;
|
||||
}
|
||||
|
||||
// Set the position in the source file right after the file header
|
||||
TempPos.QuadPart = ha->MpqPos.QuadPart + ha->pHeader->dwHeaderSize;
|
||||
SetFilePointer(ha->hFile, TempPos.LowPart, &TempPos.HighPart, FILE_BEGIN);
|
||||
|
||||
// Get the number of bytes to copy
|
||||
FirstFilePos.QuadPart -= ha->pHeader->dwHeaderSize;
|
||||
nError = CopyNonMpqData(ha->hFile, hFile, FirstFilePos);
|
||||
}
|
||||
*/
|
||||
// Now write all file blocks.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = CopyMpqFiles(hFile, ha, pFileSeeds);
|
||||
|
||||
// Now we need to update the tables positions
|
||||
// (but only if the tables are at the end of the file)
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
LARGE_INTEGER RelativePos;
|
||||
LARGE_INTEGER FilePos = {0};
|
||||
|
||||
// Set the hash table position
|
||||
FilePos.LowPart = SetFilePointer(hFile, 0, &FilePos.HighPart, FILE_CURRENT);
|
||||
RelativePos.QuadPart = FilePos.QuadPart - ha->MpqPos.QuadPart;
|
||||
ha->pHeader->wHashTablePosHigh = (USHORT)RelativePos.HighPart;
|
||||
ha->pHeader->dwHashTablePos = RelativePos.LowPart;
|
||||
ha->HashTablePos = FilePos;
|
||||
|
||||
// Set the block table position
|
||||
RelativePos.QuadPart += ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
|
||||
FilePos.QuadPart += ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
|
||||
ha->pHeader->wBlockTablePosHigh = (USHORT)RelativePos.HighPart;
|
||||
ha->pHeader->dwBlockTablePos = RelativePos.LowPart;
|
||||
ha->BlockTablePos = FilePos;
|
||||
|
||||
// Set the extended block table position
|
||||
RelativePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
|
||||
FilePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
|
||||
if(ha->ExtBlockTablePos.QuadPart != 0)
|
||||
{
|
||||
ha->pHeader->ExtBlockTablePos = RelativePos;
|
||||
ha->ExtBlockTablePos = FilePos;
|
||||
|
||||
RelativePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx);
|
||||
FilePos.QuadPart += ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx);
|
||||
}
|
||||
|
||||
// Set the archive size
|
||||
ha->pHeader->dwArchiveSize = RelativePos.LowPart;
|
||||
ha->MpqSize = RelativePos;
|
||||
}
|
||||
|
||||
// If succeeded, update the tables in the file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
CloseHandle(ha->hFile);
|
||||
ha->hFile = hFile;
|
||||
hFile = INVALID_HANDLE_VALUE;
|
||||
nError = SaveMPQTables(ha);
|
||||
}
|
||||
|
||||
// If all succeeded, switch the archives
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(lpUserData, CCB_CLOSING_ARCHIVE, 0, 0);
|
||||
|
||||
if(!DeleteFile(ha->szFileName) || // Delete the old archive
|
||||
!CloseHandle(ha->hFile) || // Close the new archive
|
||||
!MoveFile(szTempFile, ha->szFileName)) // Rename the temporary archive
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Now open the freshly renamed archive file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
ha->hFile = CreateFile(ha->szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if(ha->hFile == INVALID_HANDLE_VALUE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Invalidate the positions of the archive
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
ha->pLastFile = NULL;
|
||||
ha->dwBlockPos = 0;
|
||||
ha->dwBuffPos = 0;
|
||||
}
|
||||
|
||||
// Cleanup and return
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hFile);
|
||||
if(pFileSeeds != NULL)
|
||||
FREEMEM(pFileSeeds);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
DeleteFile(szTempFile);
|
||||
CompactCB = NULL;
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
@ -1,746 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileCreateArchiveEx.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* MPQ Editing functions */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 24.03.03 1.00 Lad Splitted from SFileOpenArchive.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define DEFAULT_BLOCK_SIZE 3 // Default size of the block
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local tables
|
||||
|
||||
static DWORD PowersOfTwo[] =
|
||||
{
|
||||
0x0000002, 0x0000004, 0x0000008,
|
||||
0x0000010, 0x0000020, 0x0000040, 0x0000080,
|
||||
0x0000100, 0x0000200, 0x0000400, 0x0000800,
|
||||
0x0001000, 0x0002000, 0x0004000, 0x0008000,
|
||||
0x0010000, 0x0020000, 0x0040000, 0x0080000,
|
||||
0x0000000
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static int RecryptFileData(
|
||||
TMPQArchive * ha,
|
||||
DWORD dwSaveBlockIndex,
|
||||
const char * szFileName,
|
||||
const char * szNewFileName)
|
||||
{
|
||||
LARGE_INTEGER BlockFilePos;
|
||||
LARGE_INTEGER MpqFilePos;
|
||||
TMPQBlockEx * pBlockEx = ha->pExtBlockTable + dwSaveBlockIndex;
|
||||
TMPQBlock * pBlock = ha->pBlockTable + dwSaveBlockIndex;
|
||||
const char * szPlainName;
|
||||
LPDWORD pdwBlockPos1 = NULL;
|
||||
LPDWORD pdwBlockPos2 = NULL;
|
||||
LPBYTE pbFileBlock = NULL;
|
||||
DWORD dwTransferred;
|
||||
DWORD dwOldSeed;
|
||||
DWORD dwNewSeed;
|
||||
DWORD dwToRead;
|
||||
int nBlocks;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// The file must be encrypted
|
||||
assert(pBlock->dwFlags & MPQ_FILE_ENCRYPTED);
|
||||
|
||||
// File decryption seed is calculated from the plain name
|
||||
szPlainName = strrchr(szFileName, '\\');
|
||||
if(szPlainName != NULL)
|
||||
szFileName = szPlainName + 1;
|
||||
szPlainName = strrchr(szNewFileName, '\\');
|
||||
if(szPlainName != NULL)
|
||||
szNewFileName = szPlainName + 1;
|
||||
|
||||
// Calculate both file seeds
|
||||
dwOldSeed = DecryptFileSeed(szFileName);
|
||||
dwNewSeed = DecryptFileSeed(szNewFileName);
|
||||
if(pBlock->dwFlags & MPQ_FILE_FIXSEED)
|
||||
{
|
||||
dwOldSeed = (dwOldSeed + pBlock->dwFilePos) ^ pBlock->dwFSize;
|
||||
dwNewSeed = (dwNewSeed + pBlock->dwFilePos) ^ pBlock->dwFSize;
|
||||
}
|
||||
|
||||
// Incase the seeds are equal, don't recrypt the file
|
||||
if(dwNewSeed == dwOldSeed)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// Calculate the file position of the archived file
|
||||
MpqFilePos.LowPart = pBlock->dwFilePos;
|
||||
MpqFilePos.HighPart = pBlockEx->wFilePosHigh;
|
||||
MpqFilePos.QuadPart += ha->MpqPos.QuadPart;
|
||||
|
||||
// Calculate the number of file blocks
|
||||
nBlocks = pBlock->dwFSize / ha->dwBlockSize;
|
||||
if(pBlock->dwFSize % ha->dwBlockSize)
|
||||
nBlocks++;
|
||||
|
||||
// If the file is stored as single unit, we recrypt one block only
|
||||
if(pBlock->dwFlags & MPQ_FILE_SINGLE_UNIT)
|
||||
{
|
||||
// Allocate the block
|
||||
pbFileBlock = ALLOCMEM(BYTE, pBlock->dwCSize);
|
||||
if(pbFileBlock == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
SetFilePointer(ha->hFile, MpqFilePos.LowPart, &MpqFilePos.HighPart, FILE_BEGIN);
|
||||
ReadFile(ha->hFile, pbFileBlock, pBlock->dwCSize, &dwTransferred, NULL);
|
||||
if(dwTransferred == pBlock->dwCSize)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Recrypt the block
|
||||
DecryptMPQBlock((DWORD *)pbFileBlock, pBlock->dwCSize, dwOldSeed);
|
||||
EncryptMPQBlock((DWORD *)pbFileBlock, pBlock->dwCSize, dwNewSeed);
|
||||
|
||||
// Write it back
|
||||
SetFilePointer(ha->hFile, MpqFilePos.LowPart, &MpqFilePos.HighPart, FILE_BEGIN);
|
||||
WriteFile(ha->hFile, pbFileBlock, pBlock->dwCSize, &dwTransferred, NULL);
|
||||
if(dwTransferred != pBlock->dwCSize)
|
||||
nError = ERROR_WRITE_FAULT;
|
||||
}
|
||||
FREEMEM(pbFileBlock);
|
||||
return nError;
|
||||
}
|
||||
|
||||
// If the file is compressed, we have to re-crypt block table first,
|
||||
// then all file blocks
|
||||
if(pBlock->dwFlags & MPQ_FILE_COMPRESSED)
|
||||
{
|
||||
// Allocate buffer for both blocks
|
||||
pdwBlockPos1 = ALLOCMEM(DWORD, nBlocks + 2);
|
||||
pdwBlockPos2 = ALLOCMEM(DWORD, nBlocks + 2);
|
||||
if(pdwBlockPos1 == NULL || pdwBlockPos2 == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Calculate number of bytes to be read
|
||||
dwToRead = (nBlocks + 1) * sizeof(DWORD);
|
||||
if(pBlock->dwFlags & MPQ_FILE_HAS_EXTRA)
|
||||
dwToRead += sizeof(DWORD);
|
||||
|
||||
// Read the block positions
|
||||
SetFilePointer(ha->hFile, MpqFilePos.LowPart, &MpqFilePos.HighPart, FILE_BEGIN);
|
||||
ReadFile(ha->hFile, pdwBlockPos1, dwToRead, &dwTransferred, NULL);
|
||||
if(dwTransferred != dwToRead)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
// Recrypt the block table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED(pdwBlockPos1, dwToRead / sizeof(DWORD));
|
||||
DecryptMPQBlock(pdwBlockPos1, dwToRead, dwOldSeed - 1);
|
||||
if(pdwBlockPos1[0] != dwToRead)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
memcpy(pdwBlockPos2, pdwBlockPos1, dwToRead);
|
||||
EncryptMPQBlock(pdwBlockPos2, dwToRead, dwNewSeed - 1);
|
||||
BSWAP_ARRAY32_UNSIGNED(pdwBlockPos2, dwToRead / sizeof(DWORD));
|
||||
}
|
||||
|
||||
// Write the recrypted block table back
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
SetFilePointer(ha->hFile, MpqFilePos.LowPart, &MpqFilePos.HighPart, FILE_BEGIN);
|
||||
WriteFile(ha->hFile, pdwBlockPos2, dwToRead, &dwTransferred, NULL);
|
||||
if(dwTransferred != dwToRead)
|
||||
nError = ERROR_WRITE_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the transfer buffer
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pbFileBlock = ALLOCMEM(BYTE, ha->dwBlockSize);
|
||||
if(pbFileBlock == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Now we have to recrypt all file blocks
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
for(int nBlock = 0; nBlock < nBlocks; nBlock++)
|
||||
{
|
||||
// Calc position and length for uncompressed file
|
||||
BlockFilePos.QuadPart = MpqFilePos.QuadPart + (ha->dwBlockSize * nBlock);
|
||||
dwToRead = ha->dwBlockSize;
|
||||
if(nBlock == nBlocks - 1)
|
||||
dwToRead = pBlock->dwFSize - (ha->dwBlockSize * (nBlocks - 1));
|
||||
|
||||
// Fix position and length for compressed file
|
||||
if(pBlock->dwFlags & MPQ_FILE_COMPRESS)
|
||||
{
|
||||
BlockFilePos.QuadPart = MpqFilePos.QuadPart + pdwBlockPos1[nBlock];
|
||||
dwToRead = pdwBlockPos1[nBlock+1] - pdwBlockPos1[nBlock];
|
||||
}
|
||||
|
||||
// Read the file block
|
||||
SetFilePointer(ha->hFile, BlockFilePos.LowPart, &BlockFilePos.HighPart, FILE_BEGIN);
|
||||
ReadFile(ha->hFile, pbFileBlock, dwToRead, &dwTransferred, NULL);
|
||||
if(dwTransferred != dwToRead)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
// Recrypt the file block
|
||||
BSWAP_ARRAY32_UNSIGNED((DWORD *)pbFileBlock, dwToRead/sizeof(DWORD));
|
||||
DecryptMPQBlock((DWORD *)pbFileBlock, dwToRead, dwOldSeed + nBlock);
|
||||
EncryptMPQBlock((DWORD *)pbFileBlock, dwToRead, dwNewSeed + nBlock);
|
||||
BSWAP_ARRAY32_UNSIGNED((DWORD *)pbFileBlock, dwToRead/sizeof(DWORD));
|
||||
|
||||
// Write the block back
|
||||
SetFilePointer(ha->hFile, BlockFilePos.LowPart, &BlockFilePos.HighPart, FILE_BEGIN);
|
||||
WriteFile(ha->hFile, pbFileBlock, dwToRead, &dwTransferred, NULL);
|
||||
if(dwTransferred != dwToRead)
|
||||
nError = ERROR_WRITE_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
// Free buffers and exit
|
||||
if(pbFileBlock != NULL)
|
||||
FREEMEM(pbFileBlock);
|
||||
if(pdwBlockPos2 != NULL)
|
||||
FREEMEM(pdwBlockPos2);
|
||||
if(pdwBlockPos1 != NULL)
|
||||
FREEMEM(pdwBlockPos1);
|
||||
return nError;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Opens or creates a (new) MPQ archive.
|
||||
//
|
||||
// szMpqName - Name of the archive to be created.
|
||||
//
|
||||
// dwCreationDisposition:
|
||||
//
|
||||
// Value Archive exists Archive doesn't exist
|
||||
// ---------- --------------------- ---------------------
|
||||
// CREATE_NEW Fails Creates new archive
|
||||
// CREATE_ALWAYS Overwrites existing Creates new archive
|
||||
// OPEN_EXISTING Opens the archive Fails
|
||||
// OPEN_ALWAYS Opens the archive Creates new archive
|
||||
//
|
||||
// The above mentioned values can be combined with the following flags:
|
||||
//
|
||||
// MPQ_CREATE_ARCHIVE_V1 - Creates MPQ archive version 1
|
||||
// MPQ_CREATE_ARCHIVE_V2 - Creates MPQ archive version 2
|
||||
// MPQ_CREATE_ATTRIBUTES - Will also add (attributes) file with the CRCs
|
||||
//
|
||||
// dwHashTableSize - Size of the hash table (only if creating a new archive).
|
||||
// Must be between 2^4 (= 16) and 2^18 (= 262 144)
|
||||
//
|
||||
// phMpq - Receives handle to the archive
|
||||
//
|
||||
|
||||
BOOL WINAPI SFileCreateArchiveEx(const char * szMpqName, DWORD dwCreationDisposition, DWORD dwHashTableSize, HANDLE * phMPQ)
|
||||
{
|
||||
LARGE_INTEGER MpqPos = {0}; // Position of MPQ header in the file
|
||||
TMPQArchive * ha = NULL; // MPQ archive handle
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE; // File handle
|
||||
DWORD dwTransferred = 0; // Number of bytes written into the archive
|
||||
USHORT wFormatVersion;
|
||||
BOOL bCreateAttributes = FALSE;
|
||||
BOOL bFileExists = FALSE;
|
||||
int nIndex = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Pre-initialize the result value
|
||||
if(phMPQ != NULL)
|
||||
*phMPQ = NULL;
|
||||
|
||||
// Check the parameters, if they are valid
|
||||
if(szMpqName == NULL || *szMpqName == 0 || phMPQ == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Check the value of dwCreationDisposition against file existence
|
||||
bFileExists = (GetFileAttributes(szMpqName) != 0xFFFFFFFF);
|
||||
|
||||
// Extract format version from the "dwCreationDisposition"
|
||||
bCreateAttributes = (dwCreationDisposition & MPQ_CREATE_ATTRIBUTES);
|
||||
wFormatVersion = (USHORT)((dwCreationDisposition >> 0x10) & 0x0000000F);
|
||||
dwCreationDisposition &= 0x0000FFFF;
|
||||
|
||||
// If the file exists and open required, do it.
|
||||
if(bFileExists && (dwCreationDisposition == OPEN_EXISTING || dwCreationDisposition == OPEN_ALWAYS))
|
||||
{
|
||||
// Try to open the archive normal way. If it fails, it means that
|
||||
// the file exist, but it is not a MPQ archive.
|
||||
if(SFileOpenArchiveEx(szMpqName, 0, 0, phMPQ, GENERIC_READ | GENERIC_WRITE))
|
||||
return TRUE;
|
||||
|
||||
// If the caller required to open the existing archive,
|
||||
// and the file is not MPQ archive, return error
|
||||
if(dwCreationDisposition == OPEN_EXISTING)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Two error cases
|
||||
if(dwCreationDisposition == CREATE_NEW && bFileExists)
|
||||
{
|
||||
SetLastError(ERROR_ALREADY_EXISTS);
|
||||
return FALSE;
|
||||
}
|
||||
if(dwCreationDisposition == OPEN_EXISTING && bFileExists == FALSE)
|
||||
{
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// At this point, we have to create the archive. If the file exists,
|
||||
// we will convert it to MPQ archive.
|
||||
// Check the value of hash table size. It has to be a power of two
|
||||
// and must be between HASH_TABLE_SIZE_MIN and HASH_TABLE_SIZE_MAX
|
||||
if(dwHashTableSize < HASH_TABLE_SIZE_MIN)
|
||||
dwHashTableSize = HASH_TABLE_SIZE_MIN;
|
||||
if(dwHashTableSize > HASH_TABLE_SIZE_MAX)
|
||||
dwHashTableSize = HASH_TABLE_SIZE_MAX;
|
||||
|
||||
// Round the hash table size up to the nearest power of two
|
||||
for(nIndex = 0; PowersOfTwo[nIndex] != 0; nIndex++)
|
||||
{
|
||||
if(dwHashTableSize <= PowersOfTwo[nIndex])
|
||||
{
|
||||
dwHashTableSize = PowersOfTwo[nIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the buffer for decryption engine
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = PrepareStormBuffer();
|
||||
|
||||
// Get the position where the MPQ header will begin.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
hFile = CreateFile(szMpqName,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
dwCreationDisposition,
|
||||
0,
|
||||
NULL);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Retrieve the file size and round it up to 0x200 bytes
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
MpqPos.LowPart = GetFileSize(hFile, (LPDWORD)&MpqPos.HighPart);
|
||||
MpqPos.QuadPart += 0x1FF;
|
||||
MpqPos.LowPart &= 0xFFFFFE00;
|
||||
|
||||
if(wFormatVersion == MPQ_FORMAT_VERSION_1 && MpqPos.HighPart != 0)
|
||||
nError = ERROR_DISK_FULL;
|
||||
if(wFormatVersion == MPQ_FORMAT_VERSION_2 && MpqPos.HighPart > 0x0000FFFF)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
|
||||
// Move to the end of the file (i.e. begin of the MPQ)
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(SetFilePointer(hFile, MpqPos.LowPart, &MpqPos.HighPart, FILE_BEGIN) == 0xFFFFFFFF)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Set the new end of the file to the MPQ header position
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!SetEndOfFile(hFile))
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Create the archive handle
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Fill the MPQ archive handle structure and create the header,
|
||||
// block buffer, hash table and block table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(ha, 0, sizeof(TMPQArchive));
|
||||
strcpy(ha->szFileName, szMpqName);
|
||||
ha->hFile = hFile;
|
||||
ha->dwBlockSize = 0x200 << DEFAULT_BLOCK_SIZE;
|
||||
ha->MpqPos = MpqPos;
|
||||
ha->pHeader = &ha->Header;
|
||||
ha->pHashTable = ALLOCMEM(TMPQHash, dwHashTableSize);
|
||||
ha->pBlockTable = ALLOCMEM(TMPQBlock, dwHashTableSize);
|
||||
ha->pExtBlockTable = ALLOCMEM(TMPQBlockEx, dwHashTableSize);
|
||||
ha->pbBlockBuffer = ALLOCMEM(BYTE, ha->dwBlockSize);
|
||||
ha->pListFile = NULL;
|
||||
ha->dwFlags |= MPQ_FLAG_CHANGED;
|
||||
|
||||
if(!ha->pHashTable || !ha->pBlockTable || !ha->pExtBlockTable || !ha->pbBlockBuffer)
|
||||
nError = GetLastError();
|
||||
hFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// Fill the MPQ header and all buffers
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
LARGE_INTEGER TempPos;
|
||||
TMPQHeader2 * pHeader = ha->pHeader;
|
||||
DWORD dwHeaderSize = (wFormatVersion == MPQ_FORMAT_VERSION_2) ? sizeof(TMPQHeader2) : sizeof(TMPQHeader);
|
||||
|
||||
memset(pHeader, 0, sizeof(TMPQHeader2));
|
||||
pHeader->dwID = ID_MPQ;
|
||||
pHeader->dwHeaderSize = dwHeaderSize;
|
||||
pHeader->dwArchiveSize = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash);
|
||||
pHeader->wFormatVersion = wFormatVersion;
|
||||
pHeader->wBlockSize = 3; // 0x1000 bytes per block
|
||||
pHeader->dwHashTableSize = dwHashTableSize;
|
||||
|
||||
// Set proper hash table positions
|
||||
ha->HashTablePos.QuadPart = ha->MpqPos.QuadPart + pHeader->dwHeaderSize;
|
||||
ha->pHeader->dwHashTablePos = pHeader->dwHeaderSize;
|
||||
ha->pHeader->wHashTablePosHigh = 0;
|
||||
|
||||
// Set proper block table positions
|
||||
ha->BlockTablePos.QuadPart = ha->HashTablePos.QuadPart +
|
||||
(ha->pHeader->dwHashTableSize * sizeof(TMPQHash));
|
||||
TempPos.QuadPart = ha->BlockTablePos.QuadPart - ha->MpqPos.QuadPart;
|
||||
ha->pHeader->dwBlockTablePos = TempPos.LowPart;
|
||||
ha->pHeader->wBlockTablePosHigh = (USHORT)TempPos.HighPart;
|
||||
|
||||
// For now, we set extended block table positioon top zero unless we add enough
|
||||
// files to cause the archive size exceed 4 GB
|
||||
ha->ExtBlockTablePos.QuadPart = 0;
|
||||
|
||||
// Clear all tables
|
||||
memset(ha->pBlockTable, 0, sizeof(TMPQBlock) * dwHashTableSize);
|
||||
memset(ha->pExtBlockTable, 0, sizeof(TMPQBlockEx) * dwHashTableSize);
|
||||
memset(ha->pHashTable, 0xFF, sizeof(TMPQHash) * dwHashTableSize);
|
||||
}
|
||||
|
||||
// Write the MPQ header to the file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD dwHeaderSize = ha->pHeader->dwHeaderSize;
|
||||
|
||||
BSWAP_TMPQHEADER(ha->pHeader);
|
||||
WriteFile(ha->hFile, ha->pHeader, dwHeaderSize, &dwTransferred, NULL);
|
||||
BSWAP_TMPQHEADER(ha->pHeader);
|
||||
|
||||
if(dwTransferred != ha->pHeader->dwHeaderSize)
|
||||
nError = ERROR_DISK_FULL;
|
||||
|
||||
ha->MpqSize.QuadPart += dwTransferred;
|
||||
}
|
||||
|
||||
// Create the internal listfile
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = SListFileCreateListFile(ha);
|
||||
|
||||
// Try to add the internal listfile, attributes.
|
||||
// Also add internal listfile to the search lists
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(SFileAddListFile((HANDLE)ha, NULL) != ERROR_SUCCESS)
|
||||
AddInternalFile(ha, LISTFILE_NAME);
|
||||
}
|
||||
|
||||
// Create the file attributes
|
||||
if(nError == ERROR_SUCCESS && bCreateAttributes)
|
||||
{
|
||||
if(SAttrFileCreate(ha) == ERROR_SUCCESS)
|
||||
AddInternalFile(ha, ATTRIBUTES_NAME);
|
||||
}
|
||||
|
||||
// Cleanup : If an error, delete all buffers and return
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
FreeMPQArchive(ha);
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hFile);
|
||||
SetLastError(nError);
|
||||
ha = NULL;
|
||||
}
|
||||
|
||||
// Return the values
|
||||
*phMPQ = (HANDLE)ha;
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Changes locale ID of a file
|
||||
|
||||
BOOL WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
|
||||
// Invalid handle => do nothing
|
||||
if(IsValidFileHandle(hf) == FALSE || IsValidMpqHandle(hf->ha) == FALSE)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// If the file has not been open for writing, do nothing.
|
||||
if(hf->ha->pListFile == NULL)
|
||||
return ERROR_ACCESS_DENIED;
|
||||
|
||||
hf->pHash->lcLocale = (USHORT)lcNewLocale;
|
||||
hf->ha->dwFlags |= MPQ_FLAG_CHANGED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Adds a file into the archive
|
||||
|
||||
BOOL WINAPI SFileAddFileEx(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality, int nFileType)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
BOOL bReplaced = FALSE; // TRUE if replacing file in the archive
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Check valid parameters
|
||||
if(IsValidMpqHandle(ha) == FALSE || szFileName == NULL || *szFileName == 0 || szArchivedName == NULL || *szArchivedName == 0)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Check the values of dwFlags
|
||||
if((dwFlags & MPQ_FILE_IMPLODE) && (dwFlags & MPQ_FILE_COMPRESS))
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// If anyone is trying to add listfile, and the archive already has a listfile,
|
||||
// deny the operation, but return success.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(ha->pListFile != NULL && !_stricmp(szFileName, LISTFILE_NAME))
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// Open added file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, NULL);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = AddFileToArchive(ha, hFile, szArchivedName, dwFlags, dwQuality, nFileType, &bReplaced);
|
||||
|
||||
// Add the file into listfile also
|
||||
if(nError == ERROR_SUCCESS && bReplaced == FALSE)
|
||||
nError = SListFileCreateNode(ha, szArchivedName, lcLocale);
|
||||
|
||||
// Cleanup and exit
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hFile);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
// Adds a data file into the archive
|
||||
BOOL WINAPI SFileAddFile(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags)
|
||||
{
|
||||
return SFileAddFileEx(hMPQ, szFileName, szArchivedName, dwFlags, 0, SFILE_TYPE_DATA);
|
||||
}
|
||||
|
||||
// Adds a WAVE file into the archive
|
||||
BOOL WINAPI SFileAddWave(HANDLE hMPQ, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality)
|
||||
{
|
||||
return SFileAddFileEx(hMPQ, szFileName, szArchivedName, dwFlags, dwQuality, SFILE_TYPE_WAVE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// BOOL SFileRemoveFile(HANDLE hMPQ, char * szFileName)
|
||||
//
|
||||
// This function removes a file from the archive. The file content
|
||||
// remains there, only the entries in the hash table and in the block
|
||||
// table are updated.
|
||||
|
||||
BOOL WINAPI SFileRemoveFile(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
TMPQBlockEx * pBlockEx = NULL; // Block entry of deleted file
|
||||
TMPQBlock * pBlock = NULL; // Block entry of deleted file
|
||||
TMPQHash * pHash = NULL; // Hash entry of deleted file
|
||||
DWORD dwBlockIndex = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Check the parameters
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(IsValidMpqHandle(ha) == FALSE)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
if(dwSearchScope != SFILE_OPEN_BY_INDEX && *szFileName == 0)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Do not allow to remove listfile
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(dwSearchScope != SFILE_OPEN_BY_INDEX && !_stricmp(szFileName, LISTFILE_NAME))
|
||||
nError = ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
// Remove the file from the list file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = SListFileRemoveNode(ha, szFileName, lcLocale);
|
||||
|
||||
// Get hash entry belonging to this file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((pHash = GetHashEntryEx(ha, (char *)szFileName, lcLocale)) == NULL)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
// If index was not found, or is greater than number of files, exit.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((dwBlockIndex = pHash->dwBlockIndex) > ha->pHeader->dwBlockTableSize)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Get block and test if the file is not already deleted
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pBlockEx = ha->pExtBlockTable + dwBlockIndex;
|
||||
pBlock = ha->pBlockTable + dwBlockIndex;
|
||||
if((pBlock->dwFlags & MPQ_FILE_EXISTS) == 0)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Now invalidate the block entry and the hash entry. Do not make any
|
||||
// relocations and file copying, use SFileCompactArchive for it.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pBlockEx->wFilePosHigh = 0;
|
||||
pBlock->dwFilePos = 0;
|
||||
pBlock->dwFSize = 0;
|
||||
pBlock->dwCSize = 0;
|
||||
pBlock->dwFlags = 0;
|
||||
pHash->dwName1 = 0xFFFFFFFF;
|
||||
pHash->dwName2 = 0xFFFFFFFF;
|
||||
pHash->lcLocale = 0xFFFF;
|
||||
pHash->wPlatform = 0xFFFF;
|
||||
pHash->dwBlockIndex = HASH_ENTRY_DELETED;
|
||||
|
||||
// Update MPQ archive
|
||||
ha->dwFlags |= MPQ_FLAG_CHANGED;
|
||||
}
|
||||
|
||||
// Resolve error and exit
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
// Renames the file within the archive.
|
||||
BOOL WINAPI SFileRenameFile(HANDLE hMPQ, const char * szFileName, const char * szNewFileName)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
TMPQBlock * pBlock;
|
||||
TMPQHash * pOldHash = NULL; // Hash entry for the original file
|
||||
TMPQHash * pNewHash = NULL; // Hash entry for the renamed file
|
||||
DWORD dwSaveBlockIndex = 0;
|
||||
LCID lcSaveLocale = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Test the valid parameters
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(hMPQ == NULL || szNewFileName == NULL || *szNewFileName == 0)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
if(szFileName == NULL || *szFileName == 0)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Do not allow to rename listfile
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!_stricmp(szFileName, LISTFILE_NAME))
|
||||
nError = ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
// Get the hash table entry for the original file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((pOldHash = GetHashEntryEx(ha, szFileName, lcLocale)) == NULL)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Test if the file already exists in the archive
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((pNewHash = GetHashEntryEx(ha, szNewFileName, pOldHash->lcLocale)) != NULL)
|
||||
nError = ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
// We have to know the decryption seed, otherwise we cannot re-crypt
|
||||
// the file after renaming
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Save block table index and remove the hash table entry
|
||||
dwSaveBlockIndex = pOldHash->dwBlockIndex;
|
||||
lcSaveLocale = pOldHash->lcLocale;
|
||||
pBlock = ha->pBlockTable + dwSaveBlockIndex;
|
||||
|
||||
// If the file is encrypted, we have to re-crypt the file content
|
||||
// with the new decryption seed
|
||||
if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
nError = RecryptFileData(ha, dwSaveBlockIndex, szFileName, szNewFileName);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the hash table entry for the renamed file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
SListFileRemoveNode(ha, szFileName, lcSaveLocale);
|
||||
pOldHash->dwName1 = 0xFFFFFFFF;
|
||||
pOldHash->dwName2 = 0xFFFFFFFF;
|
||||
pOldHash->lcLocale = 0xFFFF;
|
||||
pOldHash->wPlatform = 0xFFFF;
|
||||
pOldHash->dwBlockIndex = HASH_ENTRY_DELETED;
|
||||
|
||||
if((pNewHash = FindFreeHashEntry(ha, szNewFileName)) == NULL)
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
// Save the block index and clear the hash entry
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Copy the block table index
|
||||
pNewHash->dwBlockIndex = dwSaveBlockIndex;
|
||||
pNewHash->lcLocale = (USHORT)lcSaveLocale;
|
||||
ha->dwFlags |= MPQ_FLAG_CHANGED;
|
||||
|
||||
// Create new name node for the listfile
|
||||
nError = SListFileCreateNode(ha, szNewFileName, lcSaveLocale);
|
||||
}
|
||||
|
||||
// Resolve error and return
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
@ -1,316 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* A module for file searching within MPQs */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define LISTFILE_CACHE_SIZE 0x1000
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static BOOL IsValidSearchHandle(TMPQSearch * hs)
|
||||
{
|
||||
if(hs == NULL || IsBadReadPtr(hs, sizeof(TMPQSearch)))
|
||||
return FALSE;
|
||||
|
||||
if(!IsValidMpqHandle(hs->ha))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// This function compares a string with a wildcard search string.
|
||||
// returns TRUE, when the string matches with the wildcard.
|
||||
BOOL CheckWildCard(const char * szString, const char * szWildCard)
|
||||
{
|
||||
char * szTemp; // Temporary helper pointer
|
||||
int nResult = 0; // For memcmp return values
|
||||
int nMustNotMatch = 0; // Number of following chars int szString,
|
||||
// which must not match with szWildCard
|
||||
int nMustMatch = 0; // Number of the following characters,
|
||||
// which must match
|
||||
|
||||
// When the string is empty, it does not match with every wildcard
|
||||
if(*szString == 0)
|
||||
return FALSE;
|
||||
|
||||
// When the mask is empty, it matches to every wildcard
|
||||
if(szWildCard == NULL || *szWildCard == 0)
|
||||
return FALSE;
|
||||
|
||||
// Do normal test
|
||||
for(;;)
|
||||
{
|
||||
switch(*szWildCard)
|
||||
{
|
||||
case '*': // Means "every number of characters"
|
||||
// Skip all asterisks
|
||||
while(*szWildCard == '*')
|
||||
szWildCard++;
|
||||
|
||||
// When no more characters in wildcard, it means that the strings match
|
||||
if(*szWildCard == 0)
|
||||
return TRUE;
|
||||
|
||||
// The next N characters must not agree
|
||||
nMustNotMatch |= 0x70000000;
|
||||
break;
|
||||
|
||||
case '?': // Means "One or no character"
|
||||
while(*szWildCard == '?')
|
||||
{
|
||||
nMustNotMatch++;
|
||||
szWildCard++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// If the two characters match
|
||||
if(toupper(*szString) == toupper(*szWildCard))
|
||||
{
|
||||
// When end of string, they agree
|
||||
if(*szString == 0)
|
||||
return TRUE;
|
||||
|
||||
nMustNotMatch = 0;
|
||||
szWildCard++;
|
||||
szString++;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the next character must match, the string does not match
|
||||
if(nMustNotMatch == 0)
|
||||
return FALSE;
|
||||
|
||||
// Count the characters which must match after characters
|
||||
// that must not match
|
||||
szTemp = (char *)szWildCard;
|
||||
nMustMatch = 0;
|
||||
while(*szTemp != 0 && *szTemp != '*' && *szTemp != '?')
|
||||
{
|
||||
nMustMatch++;
|
||||
szTemp++;
|
||||
}
|
||||
|
||||
// Now skip characters from szString up to number of chars
|
||||
// that must not match
|
||||
nResult = -1;
|
||||
while(nMustNotMatch > 0 && *szString != 0)
|
||||
{
|
||||
if((nResult = _strnicmp(szString, szWildCard, nMustMatch)) == 0)
|
||||
break;
|
||||
|
||||
szString++;
|
||||
nMustNotMatch--;
|
||||
}
|
||||
|
||||
// Make one more comparison
|
||||
if(nMustNotMatch == 0)
|
||||
nResult = _strnicmp(szString, szWildCard, nMustMatch);
|
||||
|
||||
// If a match has been found, continue the search
|
||||
if(nResult == 0)
|
||||
{
|
||||
nMustNotMatch = 0;
|
||||
szWildCard += nMustMatch;
|
||||
szString += nMustMatch;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Performs one MPQ search
|
||||
static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TMPQArchive * ha = hs->ha;
|
||||
TFileNode * pNode = NULL;
|
||||
TMPQBlock * pBlock;
|
||||
TMPQHash * pFoundHash = NULL;
|
||||
TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
TMPQHash * pHash = ha->pHashTable + hs->dwNextIndex;
|
||||
DWORD dwIndex = hs->dwNextIndex;
|
||||
|
||||
// Do until a file is found or no more files
|
||||
while(pHash < pHashEnd)
|
||||
{
|
||||
pNode = ha->pListFile[dwIndex++];
|
||||
|
||||
// Is this entry occupied ?
|
||||
if(pHash->dwBlockIndex < HASH_ENTRY_DELETED && (DWORD_PTR)pNode < LISTFILE_ENTRY_DELETED)
|
||||
{
|
||||
// Check the file name.
|
||||
if(CheckWildCard(pNode->szFileName, hs->szSearchMask))
|
||||
{
|
||||
pFoundHash = pHash;
|
||||
pHash++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next hash
|
||||
pHash++;
|
||||
}
|
||||
|
||||
// In case there will be more equal entries in the hash table
|
||||
if(pFoundHash != NULL)
|
||||
{
|
||||
while(pHash < pHashEnd)
|
||||
{
|
||||
if(pHash->dwName1 != pFoundHash->dwName1 ||
|
||||
pHash->dwName2 != pFoundHash->dwName2 ||
|
||||
pHash->lcLocale != pFoundHash->lcLocale ||
|
||||
pHash->wPlatform != pFoundHash->wPlatform)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Move to the next hash
|
||||
pFoundHash = pHash;
|
||||
pHash++;
|
||||
}
|
||||
|
||||
// Fill the found entry
|
||||
pBlock = ha->pBlockTable + pFoundHash->dwBlockIndex;
|
||||
lpFindFileData->lcLocale = pFoundHash->lcLocale;
|
||||
lpFindFileData->dwFileSize = pBlock->dwFSize;
|
||||
lpFindFileData->dwFileFlags = pBlock->dwFlags;
|
||||
lpFindFileData->dwBlockIndex = pFoundHash->dwBlockIndex;
|
||||
lpFindFileData->dwCompSize = pBlock->dwCSize;
|
||||
|
||||
// Fill the file name and plain file name
|
||||
strcpy(lpFindFileData->cFileName, pNode->szFileName);
|
||||
lpFindFileData->szPlainName = strrchr(lpFindFileData->cFileName, '\\');
|
||||
if(lpFindFileData->szPlainName == NULL)
|
||||
lpFindFileData->szPlainName = lpFindFileData->cFileName;
|
||||
else
|
||||
lpFindFileData->szPlainName++;
|
||||
|
||||
// Adjust the next hash index to search
|
||||
hs->dwNextIndex = (DWORD)(pFoundHash - ha->pHashTable) + 1;
|
||||
|
||||
// Fill the next entry
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// No more files found, return error
|
||||
return ERROR_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
static void FreeMPQSearch(TMPQSearch *& hs)
|
||||
{
|
||||
if(hs != NULL)
|
||||
{
|
||||
FREEMEM(hs);
|
||||
hs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
HANDLE WINAPI SFileFindFirstFile(HANDLE hMPQ, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
TMPQSearch * hs = NULL; // Search object handle
|
||||
size_t nSize = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Check for the valid parameters
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!IsValidMpqHandle(ha))
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
if(szMask == NULL || lpFindFileData == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
if(szListFile == NULL && !IsValidMpqHandle(ha))
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Include the listfile into the MPQ's internal listfile
|
||||
// Note that if the listfile name is NULL, do nothing because the
|
||||
// internal listfile is always included.
|
||||
if(nError == ERROR_SUCCESS && szListFile != NULL && *szListFile != 0)
|
||||
nError = SFileAddListFile((HANDLE)ha, szListFile);
|
||||
|
||||
// Allocate the structure for MPQ search
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nSize = sizeof(TMPQSearch) + strlen(szMask) + 1;
|
||||
if((hs = (TMPQSearch *)ALLOCMEM(char, nSize)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Perform the first search
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(hs, 0, sizeof(TMPQSearch));
|
||||
hs->ha = ha;
|
||||
hs->dwNextIndex = 0;
|
||||
strcpy(hs->szSearchMask, szMask);
|
||||
nError = DoMPQSearch(hs, lpFindFileData);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
FreeMPQSearch(hs);
|
||||
SetLastError(nError);
|
||||
}
|
||||
|
||||
// Return the result value
|
||||
return (HANDLE)hs;
|
||||
}
|
||||
|
||||
BOOL WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TMPQSearch * hs = (TMPQSearch *)hFind;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Check the parameters
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!IsValidSearchHandle(hs) || lpFindFileData == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = DoMPQSearch(hs, lpFindFileData);
|
||||
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError(nError);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI SFileFindClose(HANDLE hFind)
|
||||
{
|
||||
TMPQSearch * hs = (TMPQSearch *)hFind;
|
||||
|
||||
// Check the parameters
|
||||
if(!IsValidSearchHandle(hs))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FreeMPQSearch(hs);
|
||||
return TRUE;
|
||||
}
|
||||
@ -1,543 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */
|
||||
/* */
|
||||
/* Author : Ladislav Zezula */
|
||||
/* E-mail : ladik@zezula.net */
|
||||
/* WWW : www.zezula.net */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Archive functions of Storm.dll */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */
|
||||
/* 19.11.03 1.01 Dan Big endian handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
static BOOL IsAviFile(TMPQHeader * pHeader)
|
||||
{
|
||||
DWORD * AviHdr = (DWORD *)pHeader;
|
||||
|
||||
// Test for 'RIFF', 'AVI ' or 'LIST'
|
||||
return (AviHdr[0] == 'FFIR' && AviHdr[2] == ' IVA' && AviHdr[3] == 'TSIL');
|
||||
}
|
||||
|
||||
// This function gets the right positions of the hash table and the block table.
|
||||
static int RelocateMpqTablePositions(TMPQArchive * ha)
|
||||
{
|
||||
TMPQHeader2 * pHeader = ha->pHeader;
|
||||
LARGE_INTEGER FileSize;
|
||||
LARGE_INTEGER TempSize;
|
||||
|
||||
// Get the size of the file
|
||||
FileSize.LowPart = GetFileSize(ha->hFile, (LPDWORD)&FileSize.HighPart);
|
||||
|
||||
// Set the proper hash table position
|
||||
ha->HashTablePos.HighPart = pHeader->wHashTablePosHigh;
|
||||
ha->HashTablePos.LowPart = pHeader->dwHashTablePos;
|
||||
ha->HashTablePos.QuadPart += ha->MpqPos.QuadPart;
|
||||
if(ha->HashTablePos.QuadPart > FileSize.QuadPart)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
// Set the proper block table position
|
||||
ha->BlockTablePos.HighPart = pHeader->wBlockTablePosHigh;
|
||||
ha->BlockTablePos.LowPart = pHeader->dwBlockTablePos;
|
||||
ha->BlockTablePos.QuadPart += ha->MpqPos.QuadPart;
|
||||
if(ha->BlockTablePos.QuadPart > FileSize.QuadPart)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
// Set the proper position of the extended block table
|
||||
if(pHeader->ExtBlockTablePos.QuadPart != 0)
|
||||
{
|
||||
ha->ExtBlockTablePos = pHeader->ExtBlockTablePos;
|
||||
ha->ExtBlockTablePos.QuadPart += ha->MpqPos.QuadPart;
|
||||
if(ha->ExtBlockTablePos.QuadPart > FileSize.QuadPart)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Size of MPQ archive is computed as the biggest of
|
||||
// (EndOfBlockTable, EndOfHashTable, EndOfExtBlockTable)
|
||||
TempSize.QuadPart = ha->HashTablePos.QuadPart + (pHeader->dwHashTableSize * sizeof(TMPQHash));
|
||||
if(TempSize.QuadPart > ha->MpqSize.QuadPart)
|
||||
ha->MpqSize = TempSize;
|
||||
TempSize.QuadPart = ha->BlockTablePos.QuadPart + (pHeader->dwBlockTableSize * sizeof(TMPQBlock));
|
||||
if(TempSize.QuadPart > ha->MpqSize.QuadPart)
|
||||
ha->MpqSize = TempSize;
|
||||
TempSize.QuadPart = ha->ExtBlockTablePos.QuadPart + (pHeader->dwBlockTableSize * sizeof(TMPQBlockEx));
|
||||
if(TempSize.QuadPart > ha->MpqSize.QuadPart)
|
||||
ha->MpqSize = TempSize;
|
||||
|
||||
// MPQ size does not include the bytes before MPQ header
|
||||
ha->MpqSize.QuadPart -= ha->MpqPos.QuadPart;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileGetLocale and SFileSetLocale
|
||||
// Set the locale for all neewly opened archives and files
|
||||
|
||||
LCID WINAPI SFileGetLocale()
|
||||
{
|
||||
return lcLocale;
|
||||
}
|
||||
|
||||
LCID WINAPI SFileSetLocale(LCID lcNewLocale)
|
||||
{
|
||||
lcLocale = lcNewLocale;
|
||||
return lcLocale;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileOpenArchiveEx (not a public function !!!)
|
||||
//
|
||||
// szFileName - MPQ archive file name to open
|
||||
// dwPriority - When SFileOpenFileEx called, this contains the search priority for searched archives
|
||||
// dwFlags - If contains MPQ_OPEN_NO_LISTFILE, then the internal list file will not be used.
|
||||
// phMPQ - Pointer to store open archive handle
|
||||
|
||||
BOOL SFileOpenArchiveEx(
|
||||
const char * szMpqName,
|
||||
DWORD dwPriority,
|
||||
DWORD dwFlags,
|
||||
HANDLE * phMPQ,
|
||||
DWORD dwAccessMode)
|
||||
{
|
||||
LARGE_INTEGER TempPos;
|
||||
TMPQArchive * ha = NULL; // Archive handle
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;// Opened archive file handle
|
||||
DWORD dwMaxBlockIndex = 0; // Maximum value of block entry
|
||||
DWORD dwBlockTableSize = 0; // Block table size.
|
||||
DWORD dwTransferred; // Number of bytes read
|
||||
DWORD dwBytes = 0; // Number of bytes to read
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Check the right parameters
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(szMpqName == NULL || *szMpqName == 0 || phMPQ == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Ensure that StormBuffer is allocated
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = PrepareStormBuffer();
|
||||
|
||||
// Open the MPQ archive file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
hFile = CreateFile(szMpqName, dwAccessMode, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Allocate the MPQhandle
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Initialize handle structure and allocate structure for MPQ header
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(ha, 0, sizeof(TMPQArchive));
|
||||
strncpy(ha->szFileName, szMpqName, strlen(szMpqName));
|
||||
ha->hFile = hFile;
|
||||
ha->dwPriority = dwPriority;
|
||||
ha->pHeader = &ha->Header;
|
||||
ha->pListFile = NULL;
|
||||
hFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// Find the offset of MPQ header within the file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
LARGE_INTEGER SearchPos = {0};
|
||||
LARGE_INTEGER MpqPos = {0};
|
||||
DWORD dwHeaderID;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// Invalidate the MPQ ID and read the eventual header
|
||||
SetFilePointer(ha->hFile, MpqPos.LowPart, &MpqPos.HighPart, FILE_BEGIN);
|
||||
ReadFile(ha->hFile, ha->pHeader, sizeof(TMPQHeader2), &dwTransferred, NULL);
|
||||
dwHeaderID = BSWAP_INT32_UNSIGNED(ha->pHeader->dwID);
|
||||
|
||||
// Special check : Some MPQs are actually AVI files, only with
|
||||
// changed extension.
|
||||
if(MpqPos.QuadPart == 0 && IsAviFile(ha->pHeader))
|
||||
{
|
||||
nError = ERROR_AVI_FILE;
|
||||
break;
|
||||
}
|
||||
|
||||
// If different number of bytes read, break the loop
|
||||
if(dwTransferred != sizeof(TMPQHeader2))
|
||||
{
|
||||
nError = ERROR_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
// If there is the MPQ shunt signature, process it
|
||||
if(dwHeaderID == ID_MPQ_SHUNT && ha->pShunt == NULL)
|
||||
{
|
||||
// Ignore the MPQ shunt completely if the caller wants to open the MPQ as V1.0
|
||||
if((dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0)
|
||||
{
|
||||
// Fill the shunt header
|
||||
ha->ShuntPos = MpqPos;
|
||||
ha->pShunt = &ha->Shunt;
|
||||
memcpy(ha->pShunt, ha->pHeader, sizeof(TMPQShunt));
|
||||
BSWAP_TMPQSHUNT(ha->pShunt);
|
||||
|
||||
// Set the MPQ pos and repeat the search
|
||||
MpqPos.QuadPart = SearchPos.QuadPart + ha->pShunt->dwHeaderPos;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// There must be MPQ header signature
|
||||
if(dwHeaderID == ID_MPQ)
|
||||
{
|
||||
BSWAP_TMPQHEADER(ha->pHeader);
|
||||
|
||||
// Save the position where the MPQ header has been found
|
||||
ha->MpqPos = MpqPos;
|
||||
|
||||
// If valid signature has been found, break the loop
|
||||
if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1)
|
||||
{
|
||||
// W3M Map Protectors set some garbage value into the "dwHeaderSize"
|
||||
// field of MPQ header. This value is apparently ignored by Storm.dll
|
||||
if(ha->pHeader->dwHeaderSize != sizeof(TMPQHeader))
|
||||
{
|
||||
ha->dwFlags |= MPQ_FLAG_PROTECTED;
|
||||
ha->pHeader->dwHeaderSize = sizeof(TMPQHeader);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_2)
|
||||
{
|
||||
// W3M Map Protectors set some garbage value into the "dwHeaderSize"
|
||||
// field of MPQ header. This value is apparently ignored by Storm.dll
|
||||
if(ha->pHeader->dwHeaderSize != sizeof(TMPQHeader2))
|
||||
{
|
||||
ha->dwFlags |= MPQ_FLAG_PROTECTED;
|
||||
ha->pHeader->dwHeaderSize = sizeof(TMPQHeader2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Note: the "dwArchiveSize" member in the MPQ header is ignored by Storm.dll
|
||||
// and can contain garbage value ("w3xmaster" protector)
|
||||
//
|
||||
|
||||
nError = ERROR_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
// Move to the next possible offset
|
||||
SearchPos.QuadPart += 0x200;
|
||||
MpqPos = SearchPos;
|
||||
}
|
||||
}
|
||||
|
||||
// Relocate tables position
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// W3x Map Protectors use the fact that War3's StormLib ignores the file shunt,
|
||||
// and probably ignores the MPQ format version as well. The trick is to
|
||||
// fake MPQ format 2, with an improper hi-word position of hash table and block table
|
||||
// We can overcome such protectors by forcing opening the archive as MPQ v 1.0
|
||||
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
|
||||
{
|
||||
ha->pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
|
||||
ha->pHeader->dwHeaderSize = sizeof(TMPQHeader);
|
||||
ha->pShunt = NULL;
|
||||
}
|
||||
|
||||
// Clear the fields not supported in older formats
|
||||
if(ha->pHeader->wFormatVersion < MPQ_FORMAT_VERSION_2)
|
||||
{
|
||||
ha->pHeader->ExtBlockTablePos.QuadPart = 0;
|
||||
ha->pHeader->wBlockTablePosHigh = 0;
|
||||
ha->pHeader->wHashTablePosHigh = 0;
|
||||
}
|
||||
|
||||
ha->dwBlockSize = (0x200 << ha->pHeader->wBlockSize);
|
||||
nError = RelocateMpqTablePositions(ha);
|
||||
}
|
||||
|
||||
// Allocate buffers
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
//
|
||||
// Note that the block table should be as large as the hash table
|
||||
// (For later file additions).
|
||||
//
|
||||
// I have found a MPQ which has the block table larger than
|
||||
// the hash table. We should avoid buffer overruns caused by that.
|
||||
//
|
||||
|
||||
if(ha->pHeader->dwBlockTableSize > ha->pHeader->dwHashTableSize)
|
||||
ha->pHeader->dwBlockTableSize = ha->pHeader->dwHashTableSize;
|
||||
dwBlockTableSize = ha->pHeader->dwHashTableSize;
|
||||
|
||||
ha->pHashTable = ALLOCMEM(TMPQHash, ha->pHeader->dwHashTableSize);
|
||||
ha->pBlockTable = ALLOCMEM(TMPQBlock, dwBlockTableSize);
|
||||
ha->pExtBlockTable = ALLOCMEM(TMPQBlockEx, dwBlockTableSize);
|
||||
ha->pbBlockBuffer = ALLOCMEM(BYTE, ha->dwBlockSize);
|
||||
|
||||
if(!ha->pHashTable || !ha->pBlockTable || !ha->pExtBlockTable || !ha->pbBlockBuffer)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Read the hash table into memory
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
dwBytes = ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
|
||||
SetFilePointer(ha->hFile, ha->HashTablePos.LowPart, &ha->HashTablePos.HighPart, FILE_BEGIN);
|
||||
ReadFile(ha->hFile, ha->pHashTable, dwBytes, &dwTransferred, NULL);
|
||||
|
||||
if(dwTransferred != dwBytes)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Decrypt hash table and check if it is correctly decrypted
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
// TMPQHash * pHash;
|
||||
|
||||
// We have to convert the hash table from LittleEndian
|
||||
BSWAP_ARRAY32_UNSIGNED((DWORD *)ha->pHashTable, (dwBytes / sizeof(DWORD)));
|
||||
DecryptHashTable((DWORD *)ha->pHashTable, (BYTE *)"(hash table)", (ha->pHeader->dwHashTableSize * 4));
|
||||
|
||||
//
|
||||
// Check hash table if is correctly decrypted
|
||||
//
|
||||
// Ladik: Some MPQ protectors corrupt the hash table by rewriting part of it.
|
||||
// To be able to open these, we will not check the entire hash table,
|
||||
// but will check it at the moment of file opening.
|
||||
//
|
||||
}
|
||||
|
||||
// Now, read the block table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(ha->pBlockTable, 0, dwBlockTableSize * sizeof(TMPQBlock));
|
||||
|
||||
// Carefully check the block table size
|
||||
dwBytes = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
|
||||
SetFilePointer(ha->hFile, ha->BlockTablePos.LowPart, &ha->BlockTablePos.HighPart, FILE_BEGIN);
|
||||
ReadFile(ha->hFile, ha->pBlockTable, dwBytes, &dwTransferred, NULL);
|
||||
|
||||
// I have found a MPQ which claimed 0x200 entries in the block table,
|
||||
// but the file was cut and there was only 0x1A0 entries.
|
||||
// We will handle this case properly, even if that means
|
||||
// omiting another integrity check of the MPQ
|
||||
if(dwTransferred < dwBytes)
|
||||
dwBytes = dwTransferred;
|
||||
BSWAP_ARRAY32_UNSIGNED((DWORD *)ha->pBlockTable, dwBytes / sizeof(DWORD));
|
||||
|
||||
// If nothing was read, we assume the file is corrupt.
|
||||
if(dwTransferred == 0)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Decrypt block table.
|
||||
// Some MPQs don't have the block table decrypted, e.g. cracked Diablo version
|
||||
// We have to check if block table is really encrypted
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
TMPQBlock * pBlockEnd = ha->pBlockTable + (dwBytes / sizeof(TMPQBlock));
|
||||
TMPQBlock * pBlock = ha->pBlockTable;
|
||||
BOOL bBlockTableEncrypted = FALSE;
|
||||
|
||||
// Verify all blocks entries in the table
|
||||
// The loop usually stops at the first entry
|
||||
while(pBlock < pBlockEnd)
|
||||
{
|
||||
// The lower 8 bits of the MPQ flags are always zero.
|
||||
// Note that this may change in next MPQ versions
|
||||
if(pBlock->dwFlags & 0x000000FF)
|
||||
{
|
||||
bBlockTableEncrypted = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Move to the next block table entry
|
||||
pBlock++;
|
||||
}
|
||||
|
||||
if(bBlockTableEncrypted)
|
||||
{
|
||||
DecryptBlockTable((DWORD *)ha->pBlockTable,
|
||||
(BYTE *)"(block table)",
|
||||
(dwBytes / sizeof(DWORD)));
|
||||
}
|
||||
}
|
||||
|
||||
// Now, read the extended block table.
|
||||
// For V1 archives, we still will maintain the extended block table
|
||||
// (it will be filled with zeros)
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(ha->pExtBlockTable, 0, dwBlockTableSize * sizeof(TMPQBlockEx));
|
||||
|
||||
if(ha->pHeader->ExtBlockTablePos.QuadPart != 0)
|
||||
{
|
||||
dwBytes = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlockEx);
|
||||
SetFilePointer(ha->hFile,
|
||||
ha->ExtBlockTablePos.LowPart,
|
||||
&ha->ExtBlockTablePos.HighPart,
|
||||
FILE_BEGIN);
|
||||
ReadFile(ha->hFile, ha->pExtBlockTable, dwBytes, &dwTransferred, NULL);
|
||||
|
||||
// We have to convert every DWORD in ha->block from LittleEndian
|
||||
BSWAP_ARRAY16_UNSIGNED((USHORT *)ha->pExtBlockTable, dwBytes / sizeof(USHORT));
|
||||
|
||||
// The extended block table is not encrypted (so far)
|
||||
if(dwTransferred != dwBytes)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify both block tables (If the MPQ file is not protected)
|
||||
if(nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_PROTECTED) == 0)
|
||||
{
|
||||
TMPQBlockEx * pBlockEx = ha->pExtBlockTable;
|
||||
TMPQBlock * pBlockEnd = ha->pBlockTable + dwMaxBlockIndex + 1;
|
||||
TMPQBlock * pBlock = ha->pBlockTable;
|
||||
|
||||
// If the MPQ file is not protected,
|
||||
// we will check if all sizes in the block table is correct.
|
||||
// Note that we will not relocate the block table (change from previous versions)
|
||||
for(; pBlock < pBlockEnd; pBlock++, pBlockEx++)
|
||||
{
|
||||
if(pBlock->dwFlags & MPQ_FILE_EXISTS)
|
||||
{
|
||||
// Get the 64-bit file position
|
||||
TempPos.HighPart = pBlockEx->wFilePosHigh;
|
||||
TempPos.LowPart = pBlock->dwFilePos;
|
||||
|
||||
if(TempPos.QuadPart > ha->MpqSize.QuadPart || pBlock->dwCSize > ha->MpqSize.QuadPart)
|
||||
{
|
||||
nError = ERROR_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the caller didn't specified otherwise,
|
||||
// include the internal listfile to the TMPQArchive structure
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((dwFlags & MPQ_OPEN_NO_LISTFILE) == 0)
|
||||
{
|
||||
if(nError == ERROR_SUCCESS)
|
||||
SListFileCreateListFile(ha);
|
||||
|
||||
// Add the internal listfile
|
||||
if(nError == ERROR_SUCCESS)
|
||||
SFileAddListFile((HANDLE)ha, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// If the caller didn't specified otherwise,
|
||||
// load the "(attributes)" file
|
||||
if(nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_ATTRIBUTES) == 0)
|
||||
{
|
||||
// Ignore the result here. Attrobutes are not necessary,
|
||||
// if they are not there, we will just ignore them
|
||||
SAttrFileLoad(ha);
|
||||
}
|
||||
|
||||
// Cleanup and exit
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
FreeMPQArchive(ha);
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hFile);
|
||||
SetLastError(nError);
|
||||
ha = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pFirstOpen == NULL)
|
||||
pFirstOpen = ha;
|
||||
}
|
||||
*phMPQ = ha;
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
BOOL WINAPI SFileOpenArchive(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMPQ)
|
||||
{
|
||||
return SFileOpenArchiveEx(szMpqName, dwPriority, dwFlags, phMPQ, GENERIC_READ);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// BOOL SFileFlushArchive(HANDLE hMpq)
|
||||
//
|
||||
// Saves all dirty data into MPQ archive.
|
||||
// Has similar effect like SFileCLoseArchive, but the archive is not closed.
|
||||
// Use on clients who keep MPQ archive open even for write operations,
|
||||
// and terminating without calling SFileCloseArchive might corrupt the archive.
|
||||
//
|
||||
|
||||
BOOL WINAPI SFileFlushArchive(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
// Do nothing if 'hMpq' is bad parameter
|
||||
if(!IsValidMpqHandle(ha))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// If the archive has been changed, update the changes
|
||||
// on the disk drive.
|
||||
if(ha->dwFlags & MPQ_FLAG_CHANGED)
|
||||
{
|
||||
SListFileSaveToMpq(ha);
|
||||
SAttrFileSaveToMpq(ha);
|
||||
SaveMPQTables(ha);
|
||||
ha->dwFlags &= ~MPQ_FLAG_CHANGED;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// BOOL SFileCloseArchive(HANDLE hMPQ);
|
||||
//
|
||||
|
||||
BOOL WINAPI SFileCloseArchive(HANDLE hMPQ)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
|
||||
// Flush all unsaved data to the storage
|
||||
if(!SFileFlushArchive(hMPQ))
|
||||
return FALSE;
|
||||
|
||||
// Free all memory used by MPQ archive
|
||||
FreeMPQArchive(ha);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1,453 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileOpenFileEx.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.99 1.00 Lad The first version of SFileOpenFileEx.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
static BOOL OpenLocalFile(const char * szFileName, HANDLE * phFile)
|
||||
{
|
||||
TMPQFile * hf = NULL;
|
||||
HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// Allocate and initialize file handle
|
||||
size_t nHandleSize = sizeof(TMPQFile) + strlen(szFileName);
|
||||
if((hf = (TMPQFile *)ALLOCMEM(char, nHandleSize)) != NULL)
|
||||
{
|
||||
memset(hf, 0, nHandleSize);
|
||||
strcpy(hf->szFileName, szFileName);
|
||||
hf->hFile = hFile;
|
||||
*phFile = hf;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
*phFile = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void FreeMPQFile(TMPQFile *& hf)
|
||||
{
|
||||
if(hf != NULL)
|
||||
{
|
||||
if(hf->hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hf->hFile);
|
||||
if(hf->pdwBlockPos != NULL)
|
||||
FREEMEM(hf->pdwBlockPos);
|
||||
if(hf->pbFileBuffer != NULL)
|
||||
FREEMEM(hf->pbFileBuffer);
|
||||
FREEMEM(hf);
|
||||
hf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileEnumLocales enums all locale versions within MPQ.
|
||||
// Functions fills all available language identifiers on a file into the buffer
|
||||
// pointed by plcLocales. There must be enough entries to copy the localed,
|
||||
// otherwise the function returns ERROR_INSUFFICIENT_BUFFER.
|
||||
|
||||
int WINAPI SFileEnumLocales(
|
||||
HANDLE hMPQ,
|
||||
const char * szFileName,
|
||||
LCID * plcLocales,
|
||||
DWORD * pdwMaxLocales,
|
||||
DWORD dwSearchScope)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
TMPQHash * pHash = NULL;
|
||||
TMPQHash * pHashEnd = NULL;
|
||||
DWORD dwLocales = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Test the parameters
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!IsValidMpqHandle(ha) || pdwMaxLocales == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
if(dwSearchScope == SFILE_OPEN_BY_INDEX && (DWORD_PTR)szFileName > ha->pHeader->dwBlockTableSize)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
if(dwSearchScope != SFILE_OPEN_BY_INDEX && *szFileName == 0)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Retrieve the hash entry for the required file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
|
||||
if(dwSearchScope == SFILE_OPEN_BY_INDEX)
|
||||
{
|
||||
for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
|
||||
{
|
||||
if(pHash->dwBlockIndex == (DWORD_PTR)szFileName)
|
||||
break;
|
||||
}
|
||||
if(pHash == pHashEnd)
|
||||
pHash = NULL;
|
||||
}
|
||||
else
|
||||
pHash = GetHashEntry(ha, szFileName);
|
||||
|
||||
// If the file was not found, sorry
|
||||
if(pHash == NULL)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Count the entries which correspond to the same file name
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
TMPQHash * pStartHash = pHash;
|
||||
TMPQHash * pSaveHash = pHash;
|
||||
DWORD dwName1 = pHash->dwName1;
|
||||
DWORD dwName2 = pHash->dwName2;
|
||||
LCID PrevLocale = 0xFFFFFFFF;
|
||||
|
||||
if(dwSearchScope != SFILE_OPEN_BY_INDEX)
|
||||
{
|
||||
while(pHash->dwBlockIndex != HASH_ENTRY_FREE)
|
||||
{
|
||||
if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex != HASH_ENTRY_DELETED)
|
||||
{
|
||||
// If the locale is different from previous one, count it.
|
||||
if(pHash->lcLocale != PrevLocale)
|
||||
{
|
||||
PrevLocale = pHash->lcLocale;
|
||||
dwLocales++;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next hash
|
||||
if(++pHash >= pHashEnd)
|
||||
pHash = ha->pHashTable;
|
||||
if(pHash == pStartHash)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For nameless access, return 1 locale always
|
||||
dwLocales++;
|
||||
}
|
||||
|
||||
// Restore the has pointer
|
||||
pHash = pSaveHash;
|
||||
}
|
||||
|
||||
// Test if there is enough space to copy the locales
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD dwMaxLocales = *pdwMaxLocales;
|
||||
|
||||
*pdwMaxLocales = dwLocales;
|
||||
if(dwMaxLocales < dwLocales)
|
||||
nError = ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
// Fill all present locales
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
TMPQHash * pStartHash = pHash;
|
||||
DWORD dwName1 = pHash->dwName1;
|
||||
DWORD dwName2 = pHash->dwName2;
|
||||
LCID PrevLocale = 0xFFFFFFFF;
|
||||
|
||||
if(dwSearchScope != SFILE_OPEN_BY_INDEX)
|
||||
{
|
||||
while(pHash->dwBlockIndex != HASH_ENTRY_FREE)
|
||||
{
|
||||
if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex != HASH_ENTRY_DELETED)
|
||||
{
|
||||
// If the locale is different from previous one, count it.
|
||||
if(pHash->lcLocale != PrevLocale)
|
||||
{
|
||||
*plcLocales++ = (LCID)pHash->lcLocale;
|
||||
PrevLocale = pHash->lcLocale;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next hash
|
||||
if(++pHash >= pHashEnd)
|
||||
pHash = ha->pHashTable;
|
||||
if(pHash == pStartHash)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For nameless access, return 1 locale always
|
||||
*plcLocales++ = (LCID)pHash->lcLocale;
|
||||
}
|
||||
}
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileHasFile
|
||||
//
|
||||
// hMPQ - Handle of opened MPQ archive
|
||||
// szFileName - Name of file to look for
|
||||
|
||||
BOOL WINAPI SFileHasFile(HANDLE hMPQ, const char * szFileName)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(ha == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
if(*szFileName == 0)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Prepare the file opening
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(GetHashEntryEx(ha, szFileName, lcLocale) == NULL)
|
||||
{
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError(nError);
|
||||
}
|
||||
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileOpenFileEx
|
||||
//
|
||||
// hMPQ - Handle of opened MPQ archive
|
||||
// szFileName - Name of file to open
|
||||
// dwSearchScope - Where to search
|
||||
// phFile - Pointer to store opened file handle
|
||||
|
||||
BOOL WINAPI SFileOpenFileEx(HANDLE hMPQ, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile)
|
||||
{
|
||||
LARGE_INTEGER FilePos;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMPQ;
|
||||
TMPQFile * hf = NULL;
|
||||
TMPQHash * pHash = NULL; // Hash table index
|
||||
TMPQBlock * pBlock = NULL; // File block
|
||||
TMPQBlockEx * pBlockEx = NULL;
|
||||
DWORD dwHashIndex = 0; // Hash table index
|
||||
DWORD dwBlockIndex = (DWORD)-1; // Found table index
|
||||
size_t nHandleSize = 0; // Memory space necessary to allocate TMPQHandle
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Due to increasing numbers of files in MPQs, I had to change the behavior
|
||||
// of opening by file index. Now, the SFILE_OPEN_BY_INDEX value of dwSearchScope
|
||||
// must be entered. This check will allow to find code places that are incompatible
|
||||
// with the new behavior.
|
||||
if(dwSearchScope != SFILE_OPEN_BY_INDEX && szFileName != NULL)
|
||||
{
|
||||
assert((DWORD_PTR)szFileName > 0x10000);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(ha == NULL && dwSearchScope == SFILE_OPEN_FROM_MPQ)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
if(phFile == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
if(dwSearchScope == SFILE_OPEN_BY_INDEX && (DWORD_PTR)szFileName > ha->pHeader->dwBlockTableSize)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
if(dwSearchScope != SFILE_OPEN_BY_INDEX && (szFileName == NULL || *szFileName == 0))
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Prepare the file opening
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// When the file is given by number, ...
|
||||
if(dwSearchScope == SFILE_OPEN_BY_INDEX)
|
||||
{
|
||||
TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
|
||||
// Set handle size to be sizeof(TMPQFile) + length of FileXXXXXXXX.xxx
|
||||
nHandleSize = sizeof(TMPQFile) + 20;
|
||||
for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
|
||||
{
|
||||
if((DWORD_PTR)szFileName == pHash->dwBlockIndex)
|
||||
{
|
||||
dwHashIndex = (DWORD)(pHash - ha->pHashTable);
|
||||
dwBlockIndex = pHash->dwBlockIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we have to open a disk file
|
||||
if(dwSearchScope == SFILE_OPEN_LOCAL_FILE)
|
||||
return OpenLocalFile(szFileName, phFile);
|
||||
|
||||
nHandleSize = sizeof(TMPQFile) + strlen(szFileName);
|
||||
if((pHash = GetHashEntryEx(ha, szFileName, lcLocale)) != NULL)
|
||||
{
|
||||
dwHashIndex = (DWORD)(pHash - ha->pHashTable);
|
||||
dwBlockIndex = pHash->dwBlockIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get block index from file name and test it
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// If index was not found, or is greater than number of files, exit.
|
||||
// This also covers the deleted files and free entries
|
||||
if(dwBlockIndex > ha->pHeader->dwBlockTableSize)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Get block and test if the file was not already deleted.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Get both block tables and file position
|
||||
pBlockEx = ha->pExtBlockTable + dwBlockIndex;
|
||||
pBlock = ha->pBlockTable + dwBlockIndex;
|
||||
FilePos.HighPart = pBlockEx->wFilePosHigh;
|
||||
FilePos.LowPart = pBlock->dwFilePos;
|
||||
|
||||
if(FilePos.QuadPart > ha->MpqSize.QuadPart ||
|
||||
pBlock->dwCSize > ha->MpqSize.QuadPart)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
if((pBlock->dwFlags & MPQ_FILE_EXISTS) == 0)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
if(pBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS)
|
||||
nError = ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Allocate file handle
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((hf = (TMPQFile *)ALLOCMEM(char, nHandleSize)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Initialize file handle
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(hf, 0, nHandleSize);
|
||||
hf->hFile = INVALID_HANDLE_VALUE;
|
||||
hf->ha = ha;
|
||||
hf->pBlockEx = pBlockEx;
|
||||
hf->pBlock = pBlock;
|
||||
hf->nBlocks = (hf->pBlock->dwFSize + ha->dwBlockSize - 1) / ha->dwBlockSize;
|
||||
hf->pHash = pHash;
|
||||
|
||||
hf->MpqFilePos.HighPart = pBlockEx->wFilePosHigh;
|
||||
hf->MpqFilePos.LowPart = pBlock->dwFilePos;
|
||||
hf->RawFilePos.QuadPart = hf->MpqFilePos.QuadPart + ha->MpqPos.QuadPart;
|
||||
|
||||
hf->dwHashIndex = dwHashIndex;
|
||||
hf->dwBlockIndex = dwBlockIndex;
|
||||
|
||||
// Allocate buffers for decompression.
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED)
|
||||
{
|
||||
// Allocate buffer for block positions. At the begin of file are stored
|
||||
// DWORDs holding positions of each block relative from begin of file in the archive
|
||||
// As for newer MPQs, there may be one additional entry in the block table
|
||||
// (if the MPQ_FILE_HAS_EXTRA flag is set).
|
||||
// Allocate the buffer to include this DWORD as well
|
||||
|
||||
if((hf->pdwBlockPos = ALLOCMEM(DWORD, hf->nBlocks + 2)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Decrypt file seed. Cannot be used if the file is given by index
|
||||
if(dwSearchScope != SFILE_OPEN_BY_INDEX)
|
||||
{
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
const char * szTemp = strrchr(szFileName, '\\');
|
||||
|
||||
strcpy(hf->szFileName, szFileName);
|
||||
if(szTemp != NULL)
|
||||
szFileName = szTemp + 1;
|
||||
|
||||
hf->dwSeed1 = DecryptFileSeed((char *)szFileName);
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_FIXSEED)
|
||||
{
|
||||
hf->dwSeed1 = (hf->dwSeed1 + hf->pBlock->dwFilePos) ^ hf->pBlock->dwFSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the file is encrypted and not compressed, we cannot detect the file seed
|
||||
if(SFileGetFileName(hf, hf->szFileName) == FALSE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve pointers to file's attributes
|
||||
if(nError == ERROR_SUCCESS && ha->pAttributes != NULL)
|
||||
{
|
||||
if(ha->pAttributes->pCrc32 != NULL)
|
||||
hf->pCrc32 = ha->pAttributes->pCrc32 + dwBlockIndex;
|
||||
if(ha->pAttributes->pFileTime != NULL)
|
||||
hf->pFileTime = ha->pAttributes->pFileTime + dwBlockIndex;
|
||||
if(ha->pAttributes->pMd5 != NULL)
|
||||
hf->pMd5 = ha->pAttributes->pMd5 + dwBlockIndex;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
FreeMPQFile(hf);
|
||||
SetLastError(nError);
|
||||
}
|
||||
|
||||
*phFile = hf;
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// BOOL WINAPI SFileCloseFile(HANDLE hFile);
|
||||
|
||||
BOOL WINAPI SFileCloseFile(HANDLE hFile)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
|
||||
if(!IsValidFileHandle(hf))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Set the last accessed file in the archive
|
||||
if(hf->ha != NULL)
|
||||
hf->ha->pLastFile = NULL;
|
||||
|
||||
// Free the structure
|
||||
FreeMPQFile(hf);
|
||||
return TRUE;
|
||||
}
|
||||
@ -1,843 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileReadFile.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.99 1.00 Lad The first version of SFileReadFile.cpp */
|
||||
/* 24.03.99 1.00 Lad Added the SFileGetFileInfo function */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define ID_WAVE 0x46464952 // Signature of WAVes for name breaking
|
||||
#define ID_EXE 0x00005A4D // Signature of executable files
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local structures
|
||||
|
||||
struct TID2Ext
|
||||
{
|
||||
DWORD dwID;
|
||||
char * szExt;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ReadMPQBlock
|
||||
//
|
||||
// hf - MPQ File handle.
|
||||
// dwBlockPos - Position of block in the file (relative to file begin)
|
||||
// buffer - Pointer to target buffer to store blocks.
|
||||
// dwBlockSize - Number of bytes to read. Must be multiplier of block size.
|
||||
//
|
||||
// Returns number of bytes read.
|
||||
|
||||
static DWORD WINAPI ReadMPQBlocks(TMPQFile * hf, DWORD dwBlockPos, BYTE * buffer, DWORD blockBytes)
|
||||
{
|
||||
LARGE_INTEGER FilePos;
|
||||
TMPQArchive * ha = hf->ha; // Archive handle
|
||||
BYTE * tempBuffer = NULL; // Buffer for reading compressed data from the file
|
||||
DWORD dwFilePos = dwBlockPos; // Reading position from the file
|
||||
DWORD dwToRead; // Number of bytes to read
|
||||
DWORD blockNum; // Block number (needed for decrypt)
|
||||
DWORD dwBytesRead = 0; // Total number of bytes read
|
||||
DWORD bytesRemain = 0; // Number of data bytes remaining up to the end of the file
|
||||
DWORD nBlocks; // Number of blocks to load
|
||||
DWORD i;
|
||||
|
||||
// Test parameters. Block position and block size must be block-aligned, block size nonzero
|
||||
if((dwBlockPos & (ha->dwBlockSize - 1)) || blockBytes == 0)
|
||||
return 0;
|
||||
|
||||
// Check the end of file
|
||||
if((dwBlockPos + blockBytes) > hf->pBlock->dwFSize)
|
||||
blockBytes = hf->pBlock->dwFSize - dwBlockPos;
|
||||
|
||||
bytesRemain = hf->pBlock->dwFSize - dwBlockPos;
|
||||
blockNum = dwBlockPos / ha->dwBlockSize;
|
||||
nBlocks = blockBytes / ha->dwBlockSize;
|
||||
if(blockBytes % ha->dwBlockSize)
|
||||
nBlocks++;
|
||||
|
||||
// If file has variable block positions, we have to load them
|
||||
if((hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED) && hf->bBlockPosLoaded == FALSE)
|
||||
{
|
||||
// Move file pointer to the begin of the file in the MPQ
|
||||
SetFilePointer(ha->hFile, hf->RawFilePos.LowPart, &hf->RawFilePos.HighPart, FILE_BEGIN);
|
||||
|
||||
// Read block positions from begin of file.
|
||||
dwToRead = (hf->nBlocks+1) * sizeof(DWORD);
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_HAS_EXTRA)
|
||||
dwToRead += sizeof(DWORD);
|
||||
|
||||
// Read the block pos table and convert the buffer to little endian
|
||||
ReadFile(ha->hFile, hf->pdwBlockPos, dwToRead, &dwBytesRead, NULL);
|
||||
BSWAP_ARRAY32_UNSIGNED(hf->pdwBlockPos, (hf->nBlocks+1));
|
||||
|
||||
//
|
||||
// If the archive if protected some way, perform additional check
|
||||
// Sometimes, the file appears not to be encrypted, but it is.
|
||||
//
|
||||
// Note: In WoW 1.10+, there's a new flag. With this flag present,
|
||||
// there's one additional entry in the block table.
|
||||
//
|
||||
|
||||
if(hf->pdwBlockPos[0] != dwBytesRead)
|
||||
hf->pBlock->dwFlags |= MPQ_FILE_ENCRYPTED;
|
||||
|
||||
// Decrypt loaded block positions if necessary
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
// If we don't know the file seed, try to find it.
|
||||
if(hf->dwSeed1 == 0)
|
||||
hf->dwSeed1 = DetectFileSeed(hf->pdwBlockPos, dwBytesRead);
|
||||
|
||||
// If we don't know the file seed, sorry but we cannot extract the file.
|
||||
if(hf->dwSeed1 == 0)
|
||||
return 0;
|
||||
|
||||
// Decrypt block positions
|
||||
DecryptMPQBlock(hf->pdwBlockPos, dwBytesRead, hf->dwSeed1 - 1);
|
||||
|
||||
//
|
||||
// Check if the block positions are correctly decrypted
|
||||
// Previous versions of StormLib (up to 6.20) had bug in SFileRenameFile.
|
||||
// Incase the file name changed, Stormlib didn't re-crypt the file with changed seed,
|
||||
// so the file remained corrupt after the name change.
|
||||
//
|
||||
// I saw a protector who puts negative offset into the block table.
|
||||
// Because there are always at least 2 block positions, we can check their difference
|
||||
//
|
||||
|
||||
if((hf->pdwBlockPos[1] - hf->pdwBlockPos[0]) > ha->dwBlockSize)
|
||||
{
|
||||
// Try once again to detect file seed and decrypt the blocks
|
||||
SetFilePointer(ha->hFile, hf->RawFilePos.LowPart, &hf->RawFilePos.HighPart, FILE_BEGIN);
|
||||
ReadFile(ha->hFile, hf->pdwBlockPos, dwToRead, &dwBytesRead, NULL);
|
||||
|
||||
BSWAP_ARRAY32_UNSIGNED(hf->pdwBlockPos, (hf->nBlocks+1));
|
||||
hf->dwSeed1 = DetectFileSeed(hf->pdwBlockPos, dwBytesRead);
|
||||
DecryptMPQBlock(hf->pdwBlockPos, dwBytesRead, hf->dwSeed1 - 1);
|
||||
|
||||
// Check if the block positions are correctly decrypted
|
||||
if(hf->pdwBlockPos[0] != dwBytesRead)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Update hf's variables
|
||||
hf->bBlockPosLoaded = TRUE;
|
||||
}
|
||||
|
||||
// Get file position and number of bytes to read
|
||||
dwFilePos = dwBlockPos;
|
||||
dwToRead = blockBytes;
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED)
|
||||
{
|
||||
dwFilePos = hf->pdwBlockPos[blockNum];
|
||||
dwToRead = hf->pdwBlockPos[blockNum + nBlocks] - dwFilePos;
|
||||
}
|
||||
|
||||
// Warning: dwFilePos, obtained from the block table, might be negative.
|
||||
// Incase of format V1, we have to ignore the overflow.
|
||||
FilePos.QuadPart = hf->RawFilePos.QuadPart + dwFilePos;
|
||||
if((dwFilePos & 0x80000000) && ha->Header.wFormatVersion == MPQ_FORMAT_VERSION_1)
|
||||
FilePos.HighPart = 0;
|
||||
|
||||
// Get work buffer for store read data
|
||||
tempBuffer = buffer;
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED)
|
||||
{
|
||||
if((tempBuffer = ALLOCMEM(BYTE, dwToRead)) == NULL)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Set file pointer, if necessary and read all required blocks
|
||||
SetFilePointer(ha->hFile, FilePos.LowPart, &FilePos.HighPart, FILE_BEGIN);
|
||||
ReadFile(ha->hFile, tempBuffer, dwToRead, &dwBytesRead, NULL);
|
||||
|
||||
// Block processing part.
|
||||
DWORD blockStart = 0; // Index of block start in work buffer
|
||||
DWORD blockSize = STORMLIB_MIN(blockBytes, ha->dwBlockSize);
|
||||
DWORD index = blockNum; // Current block index
|
||||
|
||||
dwBytesRead = 0; // Clear read byte counter
|
||||
|
||||
// Walk through all blocks
|
||||
for(i = 0; i < nBlocks; i++, index++)
|
||||
{
|
||||
BYTE * inputBuffer = tempBuffer + blockStart;
|
||||
int outLength = ha->dwBlockSize;
|
||||
|
||||
if(bytesRemain < (DWORD)outLength)
|
||||
outLength = bytesRemain;
|
||||
|
||||
// Get current block length
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED)
|
||||
blockSize = hf->pdwBlockPos[index+1] - hf->pdwBlockPos[index];
|
||||
|
||||
// If block is encrypted, we have to decrypt it.
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED((DWORD *)inputBuffer, blockSize / sizeof(DWORD));
|
||||
|
||||
// If we don't know the seed, try to decode it as WAVE file
|
||||
if(hf->dwSeed1 == 0)
|
||||
hf->dwSeed1 = DetectFileSeed2((DWORD *)inputBuffer, 3, ID_WAVE, hf->pBlock->dwFSize - 8, 0x45564157);
|
||||
|
||||
// Let's try MSVC's standard EXE or header
|
||||
if(hf->dwSeed1 == 0)
|
||||
hf->dwSeed1 = DetectFileSeed2((DWORD *)inputBuffer, 2, 0x00905A4D, 0x00000003);
|
||||
|
||||
if(hf->dwSeed1 == 0)
|
||||
{
|
||||
dwBytesRead = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
DecryptMPQBlock((DWORD *)inputBuffer, blockSize, hf->dwSeed1 + index);
|
||||
BSWAP_ARRAY32_UNSIGNED((DWORD *)inputBuffer, blockSize / sizeof(DWORD));
|
||||
}
|
||||
|
||||
// If the block is really compressed, decompress it.
|
||||
// WARNING : Some block may not be compressed, it can be determined only
|
||||
// by comparing uncompressed and compressed size !!!
|
||||
if(blockSize < (DWORD)outLength)
|
||||
{
|
||||
// Is the file compressed with PKWARE Data Compression Library ?
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_IMPLODE)
|
||||
Decompress_pklib((char *)buffer, &outLength, (char *)inputBuffer, (int)blockSize);
|
||||
|
||||
// Is it a file compressed by Blizzard's multiple compression ?
|
||||
// Note that Storm.dll v 1.0.9 distributed with Warcraft III
|
||||
// passes the full path name of the opened archive as the new last parameter
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESS)
|
||||
{
|
||||
if(!SCompDecompress((char *)buffer, &outLength, (char *)inputBuffer, (int)blockSize))
|
||||
{
|
||||
dwBytesRead = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dwBytesRead += outLength;
|
||||
buffer += outLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(buffer != inputBuffer)
|
||||
memcpy(buffer, inputBuffer, blockSize);
|
||||
|
||||
dwBytesRead += blockSize;
|
||||
buffer += blockSize;
|
||||
}
|
||||
blockStart += blockSize;
|
||||
bytesRemain -= outLength;
|
||||
}
|
||||
|
||||
// Delete input buffer, if necessary
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESSED)
|
||||
FREEMEM(tempBuffer);
|
||||
|
||||
return dwBytesRead;
|
||||
}
|
||||
|
||||
// When this function is called, it is already ensured that the parameters are valid
|
||||
// (e.g. the "dwToRead + dwFilePos" is not greater than the file size)
|
||||
static DWORD WINAPI ReadMPQFileSingleUnit(TMPQFile * hf, DWORD dwFilePos, BYTE * pbBuffer, DWORD dwToRead)
|
||||
{
|
||||
TMPQArchive * ha = hf->ha;
|
||||
DWORD dwBytesRead = 0;
|
||||
|
||||
// If the file is really compressed, decompress it.
|
||||
// Otherwise, read the data as-is to the caller.
|
||||
if(hf->pBlock->dwCSize < hf->pBlock->dwFSize)
|
||||
{
|
||||
if(hf->pbFileBuffer == NULL)
|
||||
{
|
||||
BYTE * inputBuffer = NULL;
|
||||
int outputBufferSize = (int)hf->pBlock->dwFSize;
|
||||
int inputBufferSize = (int)hf->pBlock->dwCSize;
|
||||
|
||||
// Allocate buffer in the hf
|
||||
hf->pbFileBuffer = ALLOCMEM(BYTE, outputBufferSize);
|
||||
if(hf->pbFileBuffer == NULL)
|
||||
return (DWORD)-1;
|
||||
|
||||
// Allocate temporary buffer for reading the file
|
||||
inputBuffer = ALLOCMEM(BYTE, inputBufferSize);
|
||||
if(inputBuffer != NULL)
|
||||
{
|
||||
// Move file pointer to the begin of the file, move to inner, modified by PeakGao,2008.10.28
|
||||
SetFilePointer(ha->hFile, hf->RawFilePos.LowPart, &hf->RawFilePos.HighPart, FILE_BEGIN);
|
||||
|
||||
// Read the compressed file data
|
||||
ReadFile(ha->hFile, inputBuffer, inputBufferSize, &dwBytesRead, NULL);
|
||||
|
||||
// Is the file compressed with PKWARE Data Compression Library ?
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_IMPLODE)
|
||||
Decompress_pklib((char *)hf->pbFileBuffer, &outputBufferSize, (char *)inputBuffer, (int)inputBufferSize);
|
||||
|
||||
// Is it a file compressed by Blizzard's multiple compression ?
|
||||
// Note that Storm.dll v 1.0.9 distributed with Warcraft III
|
||||
// passes the full path name of the opened archive as the new last parameter
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_COMPRESS)
|
||||
SCompDecompress((char *)hf->pbFileBuffer, &outputBufferSize, (char *)inputBuffer, (int)inputBufferSize);
|
||||
|
||||
// Free the temporary input buffer
|
||||
FREEMEM(inputBuffer);
|
||||
|
||||
// If the decompression failed, don't continue
|
||||
if(outputBufferSize == 0)
|
||||
{
|
||||
FREEMEM(hf->pbFileBuffer);
|
||||
hf->pbFileBuffer = NULL;
|
||||
return (DWORD)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the file data, if any there
|
||||
if(hf->pbFileBuffer != NULL)
|
||||
{
|
||||
memcpy(pbBuffer, hf->pbFileBuffer + dwFilePos, dwToRead);
|
||||
dwBytesRead = dwToRead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LARGE_INTEGER RawFilePos = hf->RawFilePos;
|
||||
|
||||
// Move file pointer to the dwFilePos of the file, added by PeakGao, 2008.10.28
|
||||
RawFilePos.QuadPart += dwFilePos;
|
||||
SetFilePointer(ha->hFile, RawFilePos.LowPart, &RawFilePos.HighPart, FILE_BEGIN);
|
||||
|
||||
// Read the uncompressed file data
|
||||
ReadFile(ha->hFile, pbBuffer, dwToRead, &dwBytesRead, NULL);
|
||||
}
|
||||
|
||||
return dwBytesRead;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ReadMPQFile
|
||||
|
||||
static DWORD WINAPI ReadMPQFile(TMPQFile * hf, DWORD dwFilePos, BYTE * pbBuffer, DWORD dwToRead)
|
||||
{
|
||||
TMPQArchive * ha = hf->ha;
|
||||
TMPQBlock * pBlock = hf->pBlock; // Pointer to file block
|
||||
DWORD dwBytesRead = 0; // Number of bytes read from the file
|
||||
DWORD dwBlockPos; // Position in the file aligned to the whole blocks
|
||||
DWORD dwLoaded;
|
||||
|
||||
// File position is greater or equal to file size ?
|
||||
if(dwFilePos >= pBlock->dwFSize)
|
||||
return dwBytesRead;
|
||||
|
||||
// If too few bytes in the file remaining, cut them
|
||||
if((pBlock->dwFSize - dwFilePos) < dwToRead)
|
||||
dwToRead = (pBlock->dwFSize - dwFilePos);
|
||||
|
||||
// If the file is stored as single unit, handle it separately
|
||||
if(pBlock->dwFlags & MPQ_FILE_SINGLE_UNIT)
|
||||
return ReadMPQFileSingleUnit(hf, dwFilePos, pbBuffer, dwToRead);
|
||||
|
||||
// Block position in the file
|
||||
dwBlockPos = dwFilePos & ~(ha->dwBlockSize - 1); // Position in the block
|
||||
|
||||
// Load the first block, if incomplete. It may be loaded in the cache buffer.
|
||||
// We have to check if this block is loaded. If not, load it.
|
||||
if((dwFilePos % ha->dwBlockSize) != 0)
|
||||
{
|
||||
// Number of bytes remaining in the buffer
|
||||
DWORD dwToCopy;
|
||||
DWORD dwLoaded = ha->dwBlockSize;
|
||||
|
||||
// Check if data are loaded in the cache
|
||||
if(hf != ha->pLastFile || dwBlockPos != ha->dwBlockPos)
|
||||
{
|
||||
// Load one MPQ block into archive buffer
|
||||
dwLoaded = ReadMPQBlocks(hf, dwBlockPos, ha->pbBlockBuffer, ha->dwBlockSize);
|
||||
if(dwLoaded == 0)
|
||||
return (DWORD)-1;
|
||||
|
||||
// Save lastly accessed file and block position for later use
|
||||
ha->pLastFile = hf;
|
||||
ha->dwBlockPos = dwBlockPos;
|
||||
ha->dwBuffPos = dwFilePos % ha->dwBlockSize;
|
||||
}
|
||||
dwToCopy = dwLoaded - ha->dwBuffPos;
|
||||
if(dwToCopy > dwToRead)
|
||||
dwToCopy = dwToRead;
|
||||
|
||||
// Copy data from block buffer into target buffer
|
||||
memcpy(pbBuffer, ha->pbBlockBuffer + ha->dwBuffPos, dwToCopy);
|
||||
|
||||
// Update pointers
|
||||
dwToRead -= dwToCopy;
|
||||
dwBytesRead += dwToCopy;
|
||||
pbBuffer += dwToCopy;
|
||||
dwBlockPos += ha->dwBlockSize;
|
||||
ha->dwBuffPos += dwToCopy;
|
||||
|
||||
// If all, return.
|
||||
if(dwToRead == 0)
|
||||
return dwBytesRead;
|
||||
}
|
||||
|
||||
// Load the whole ("middle") blocks only if there are more or equal one block
|
||||
if(dwToRead > ha->dwBlockSize)
|
||||
{
|
||||
DWORD dwBlockBytes = dwToRead & ~(ha->dwBlockSize - 1);
|
||||
|
||||
dwLoaded = ReadMPQBlocks(hf, dwBlockPos, pbBuffer, dwBlockBytes);
|
||||
if(dwLoaded == 0)
|
||||
return (DWORD)-1;
|
||||
|
||||
// Update pointers
|
||||
dwToRead -= dwLoaded;
|
||||
dwBytesRead += dwLoaded;
|
||||
pbBuffer += dwLoaded;
|
||||
dwBlockPos += dwLoaded;
|
||||
|
||||
// If all, return.
|
||||
if(dwToRead == 0)
|
||||
return dwBytesRead;
|
||||
}
|
||||
|
||||
// Load the terminating block
|
||||
if(dwToRead > 0)
|
||||
{
|
||||
DWORD dwToCopy = ha->dwBlockSize;
|
||||
|
||||
// Check if data are loaded in the cache
|
||||
if(hf != ha->pLastFile || dwBlockPos != ha->dwBlockPos)
|
||||
{
|
||||
// Load one MPQ block into archive buffer
|
||||
dwToCopy = ReadMPQBlocks(hf, dwBlockPos, ha->pbBlockBuffer, ha->dwBlockSize);
|
||||
if(dwToCopy == 0)
|
||||
return (DWORD)-1;
|
||||
|
||||
// Save lastly accessed file and block position for later use
|
||||
ha->pLastFile = hf;
|
||||
ha->dwBlockPos = dwBlockPos;
|
||||
}
|
||||
ha->dwBuffPos = 0;
|
||||
|
||||
// Check number of bytes read
|
||||
if(dwToCopy > dwToRead)
|
||||
dwToCopy = dwToRead;
|
||||
|
||||
memcpy(pbBuffer, ha->pbBlockBuffer, dwToCopy);
|
||||
dwBytesRead += dwToCopy;
|
||||
ha->dwBuffPos = dwToCopy;
|
||||
}
|
||||
|
||||
// Return what we've read
|
||||
return dwBytesRead;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileReadFile
|
||||
|
||||
BOOL WINAPI SFileReadFile(HANDLE hFile, VOID * lpBuffer, DWORD dwToRead, DWORD * pdwRead, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
DWORD dwBytes = 0; // Number of bytes (for everything)
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Zero the number of bytes read
|
||||
if(pdwRead != NULL)
|
||||
*pdwRead = 0;
|
||||
|
||||
// Check valid parameters
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(hf == NULL || lpBuffer == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// If direct access to the file, use Win32 for reading
|
||||
if(nError == ERROR_SUCCESS && hf->hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD dwTransferred;
|
||||
|
||||
ReadFile(hf->hFile, lpBuffer, dwToRead, &dwTransferred, lpOverlapped);
|
||||
if(dwTransferred < dwToRead)
|
||||
{
|
||||
SetLastError(ERROR_HANDLE_EOF);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(pdwRead != NULL)
|
||||
*pdwRead = dwTransferred;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Read all the bytes available in the buffer (If any)
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(dwToRead > 0)
|
||||
{
|
||||
dwBytes = ReadMPQFile(hf, hf->dwFilePos, (BYTE *)lpBuffer, dwToRead);
|
||||
if(dwBytes == (DWORD)-1)
|
||||
{
|
||||
SetLastError(ERROR_CAN_NOT_COMPLETE);
|
||||
return FALSE;
|
||||
}
|
||||
hf->ha->pLastFile = hf;
|
||||
hf->dwFilePos += dwBytes;
|
||||
}
|
||||
if(pdwRead != NULL)
|
||||
*pdwRead = dwBytes;
|
||||
}
|
||||
|
||||
// Check number of bytes read. If not OK, return FALSE.
|
||||
if(dwBytes < dwToRead)
|
||||
{
|
||||
SetLastError(ERROR_HANDLE_EOF);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileGetFilePos
|
||||
//
|
||||
// Returns position of archive file in the archive (relative to begin of file)
|
||||
|
||||
DWORD WINAPI SFileGetFilePos(HANDLE hFile, DWORD * pdwFilePosHigh)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
|
||||
if(pdwFilePosHigh != NULL)
|
||||
*pdwFilePosHigh = 0;
|
||||
|
||||
if(hf == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return (DWORD)-1;
|
||||
}
|
||||
|
||||
// If opened as plain file, ...
|
||||
if(hf->hFile != INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
// If opened from archive, return file size
|
||||
if(pdwFilePosHigh != NULL)
|
||||
*pdwFilePosHigh = hf->RawFilePos.HighPart;
|
||||
return hf->RawFilePos.LowPart;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileGetFileSize
|
||||
|
||||
DWORD WINAPI SFileGetFileSize(HANDLE hFile, DWORD * pdwFileSizeHigh)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
|
||||
if(pdwFileSizeHigh != NULL)
|
||||
*pdwFileSizeHigh = 0;
|
||||
|
||||
if(hf == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return (DWORD)-1;
|
||||
}
|
||||
|
||||
// If opened as plain file, ...
|
||||
if(hf->hFile != INVALID_HANDLE_VALUE)
|
||||
return GetFileSize(hf->hFile, pdwFileSizeHigh);
|
||||
|
||||
// If opened from archive, return file size
|
||||
return hf->pBlock->dwFSize;
|
||||
}
|
||||
|
||||
DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * pdwFilePosHigh, DWORD dwMethod)
|
||||
{
|
||||
TMPQArchive * ha;
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
|
||||
if(hf == NULL || (pdwFilePosHigh != NULL && *pdwFilePosHigh != 0))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return (DWORD)-1;
|
||||
}
|
||||
|
||||
// If opened as plain file, call Win32 API
|
||||
if(hf->hFile != INVALID_HANDLE_VALUE)
|
||||
return SetFilePointer(hf->hFile, lFilePos, pdwFilePosHigh, dwMethod);
|
||||
ha = hf->ha;
|
||||
|
||||
switch(dwMethod)
|
||||
{
|
||||
case FILE_BEGIN:
|
||||
// Cannot set pointer before begin of file
|
||||
if(-lFilePos > (LONG)hf->dwFilePos)
|
||||
hf->dwFilePos = 0;
|
||||
else
|
||||
hf->dwFilePos = lFilePos;
|
||||
break;
|
||||
|
||||
case FILE_CURRENT:
|
||||
// Cannot set pointer before begin of file
|
||||
if(-lFilePos > (LONG)hf->dwFilePos)
|
||||
hf->dwFilePos = 0;
|
||||
else
|
||||
hf->dwFilePos += lFilePos;
|
||||
break;
|
||||
|
||||
case FILE_END:
|
||||
// Cannot set file position before begin of file
|
||||
if(-lFilePos >= (LONG)hf->pBlock->dwFSize)
|
||||
hf->dwFilePos = 0;
|
||||
else
|
||||
hf->dwFilePos = hf->pBlock->dwFSize + lFilePos;
|
||||
break;
|
||||
|
||||
default:
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if(hf == ha->pLastFile && (hf->dwFilePos & ~(ha->dwBlockSize - 1)) == ha->dwBlockPos)
|
||||
ha->dwBuffPos = hf->dwFilePos & (ha->dwBlockSize - 1);
|
||||
else
|
||||
{
|
||||
ha->pLastFile = NULL;
|
||||
ha->dwBuffPos = 0;
|
||||
}
|
||||
|
||||
return hf->dwFilePos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tries to retrieve the file name
|
||||
|
||||
static TID2Ext id2ext[] =
|
||||
{
|
||||
{0x1A51504D, "mpq"}, // MPQ archive header ID ('MPQ\x1A')
|
||||
{0x46464952, "wav"}, // WAVE header 'RIFF'
|
||||
{0x324B4D53, "smk"}, // Old "Smacker Video" files 'SMK2'
|
||||
{0x694B4942, "bik"}, // Bink video files (new)
|
||||
{0x0801050A, "pcx"}, // PCX images used in Diablo I
|
||||
{0x544E4F46, "fnt"}, // Font files used in Diablo II
|
||||
{0x6D74683C, "html"}, // HTML '<htm'
|
||||
{0x4D54483C, "html"}, // HTML '<HTM
|
||||
{0x216F6F57, "tbl"}, // Table files
|
||||
{0x31504C42, "blp"}, // BLP textures
|
||||
{0x32504C42, "blp"}, // BLP textures (v2)
|
||||
{0x584C444D, "mdx"}, // MDX files
|
||||
{0x45505954, "pud"}, // Warcraft II maps
|
||||
{0x38464947, "gif"}, // GIF images 'GIF8'
|
||||
{0x3032444D, "m2"}, // WoW ??? .m2
|
||||
{0x43424457, "dbc"}, // ??? .dbc
|
||||
{0x47585053, "bls"}, // WoW pixel shaders
|
||||
{0xE0FFD8FF, "jpg"}, // JPEG image
|
||||
{0, NULL} // Terminator
|
||||
};
|
||||
|
||||
BOOL WINAPI SFileGetFileName(HANDLE hFile, char * szFileName)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle
|
||||
char * szExt = "xxx"; // Default extension
|
||||
DWORD dwFirstBytes[2]; // The first 4 bytes of the file
|
||||
DWORD dwFilePos; // Saved file position
|
||||
int nError = ERROR_SUCCESS;
|
||||
int i;
|
||||
|
||||
// Pre-zero the output buffer
|
||||
if(szFileName != NULL)
|
||||
*szFileName = 0;
|
||||
|
||||
// Check valid parameters
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(hf == NULL || szFileName == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// If the file name is already filled, return it.
|
||||
if(nError == ERROR_SUCCESS && *hf->szFileName != 0)
|
||||
{
|
||||
if(szFileName != hf->szFileName)
|
||||
strcpy(szFileName, hf->szFileName);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(hf->dwBlockIndex == (DWORD)-1)
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
// Read the first 8 bytes from the file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
dwFirstBytes[0] = dwFirstBytes[1] = 0;
|
||||
dwFilePos = SFileSetFilePointer(hf, 0, NULL, FILE_CURRENT);
|
||||
SFileReadFile(hFile, &dwFirstBytes, sizeof(dwFirstBytes), NULL);
|
||||
BSWAP_ARRAY32_UNSIGNED(dwFirstBytes, sizeof(dwFirstBytes) / sizeof(DWORD));
|
||||
SFileSetFilePointer(hf, dwFilePos, NULL, FILE_BEGIN);
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((dwFirstBytes[0] & 0x0000FFFF) == ID_EXE)
|
||||
szExt = "exe";
|
||||
else if(dwFirstBytes[0] == 0x00000006 && dwFirstBytes[1] == 0x00000001)
|
||||
szExt = "dc6";
|
||||
else
|
||||
{
|
||||
for(i = 0; id2ext[i].szExt != NULL; i++)
|
||||
{
|
||||
if(id2ext[i].dwID == dwFirstBytes[0])
|
||||
{
|
||||
szExt = id2ext[i].szExt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the file name
|
||||
sprintf(hf->szFileName, "File%08lu.%s", hf->dwBlockIndex, szExt);
|
||||
if(szFileName != hf->szFileName)
|
||||
strcpy(szFileName, hf->szFileName);
|
||||
}
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Retrieves an information about an archive or about a file within the archive
|
||||
//
|
||||
// hMpqOrFile - Handle to an MPQ archive or to a file
|
||||
// dwInfoType - Information to obtain
|
||||
|
||||
DWORD_PTR WINAPI SFileGetFileInfo(HANDLE hMpqOrFile, DWORD dwInfoType)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpqOrFile;
|
||||
TMPQFile * hf = (TMPQFile *)hMpqOrFile;
|
||||
TMPQBlock * pBlockEnd;
|
||||
TMPQBlock * pBlock;
|
||||
DWORD dwFileCount = 0;
|
||||
DWORD dwSeed;
|
||||
|
||||
switch(dwInfoType)
|
||||
{
|
||||
case SFILE_INFO_ARCHIVE_SIZE:
|
||||
if(IsValidMpqHandle(ha))
|
||||
return ha->pHeader->dwArchiveSize;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_HASH_TABLE_SIZE: // Size of the hash table
|
||||
if(IsValidMpqHandle(ha))
|
||||
return ha->pHeader->dwHashTableSize;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_BLOCK_TABLE_SIZE: // Size of the hash table
|
||||
if(IsValidMpqHandle(ha))
|
||||
return ha->pHeader->dwBlockTableSize;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_BLOCK_SIZE:
|
||||
if(IsValidMpqHandle(ha))
|
||||
return ha->dwBlockSize;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_HASH_TABLE:
|
||||
if(IsValidMpqHandle(ha))
|
||||
return (DWORD_PTR)ha->pHashTable;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_BLOCK_TABLE:
|
||||
if(IsValidMpqHandle(ha))
|
||||
return (DWORD_PTR)ha->pBlockTable;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_NUM_FILES:
|
||||
if(IsValidMpqHandle(ha))
|
||||
{
|
||||
pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize;
|
||||
for(pBlock = ha->pBlockTable; pBlock < pBlockEnd; pBlock++)
|
||||
{
|
||||
if(pBlock->dwFlags & MPQ_FILE_EXISTS)
|
||||
dwFileCount++;
|
||||
}
|
||||
return dwFileCount;
|
||||
}
|
||||
break;
|
||||
|
||||
case SFILE_INFO_HASH_INDEX:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->dwHashIndex;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_CODENAME1:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->pHash->dwName1;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_CODENAME2:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->pHash->dwName2;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_LOCALEID:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->pHash->lcLocale;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_BLOCKINDEX:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->dwBlockIndex;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_FILE_SIZE:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->pBlock->dwFSize;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_COMPRESSED_SIZE:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->pBlock->dwCSize;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_FLAGS:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->pBlock->dwFlags;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_POSITION:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->pBlock->dwFilePos;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_SEED:
|
||||
if(IsValidFileHandle(hf))
|
||||
return hf->dwSeed1;
|
||||
break;
|
||||
|
||||
case SFILE_INFO_SEED_UNFIXED:
|
||||
if(IsValidFileHandle(hf))
|
||||
{
|
||||
dwSeed = hf->dwSeed1;
|
||||
if(hf->pBlock->dwFlags & MPQ_FILE_FIXSEED)
|
||||
dwSeed = (dwSeed ^ hf->pBlock->dwFSize) - hf->MpqFilePos.LowPart;
|
||||
return dwSeed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Unknown parameter or invalid handle
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
@ -1,612 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* SListFile.cpp Copyright (c) Ladislav Zezula 2004 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 12.06.04 1.00 Lad The first version of SListFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
#include <assert.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Listfile entry structure
|
||||
|
||||
#define LISTFILE_CACHE_SIZE 0x1000 // Size of one cache element
|
||||
#define NO_MORE_CHARACTERS 256
|
||||
#define HASH_TABLE_SIZE 31 // Initial hash table size (should be a prime number)
|
||||
|
||||
struct TListFileCache
|
||||
{
|
||||
HANDLE hFile; // Stormlib file handle
|
||||
char * szMask; // File mask
|
||||
DWORD dwFileSize; // Total size of the cached file
|
||||
DWORD dwBuffSize; // File of the cache
|
||||
DWORD dwFilePos; // Position of the cache in the file
|
||||
BYTE * pBegin; // The begin of the listfile cache
|
||||
BYTE * pPos;
|
||||
BYTE * pEnd; // The last character in the file cache
|
||||
|
||||
BYTE Buffer[1]; // Listfile cache itself
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions (cache)
|
||||
|
||||
// Reloads the cache. Returns number of characters
|
||||
// that has been loaded into the cache.
|
||||
static int ReloadCache(TListFileCache * pCache)
|
||||
{
|
||||
// Check if there is enough characters in the cache
|
||||
// If not, we have to reload the next block
|
||||
if(pCache->pPos >= pCache->pEnd)
|
||||
{
|
||||
// If the cache is already at the end, do nothing more
|
||||
if((pCache->dwFilePos + pCache->dwBuffSize) >= pCache->dwFileSize)
|
||||
return 0;
|
||||
|
||||
pCache->dwFilePos += pCache->dwBuffSize;
|
||||
SFileReadFile(pCache->hFile, pCache->Buffer, pCache->dwBuffSize, &pCache->dwBuffSize, NULL);
|
||||
if(pCache->dwBuffSize == 0)
|
||||
return 0;
|
||||
|
||||
// Set the buffer pointers
|
||||
pCache->pBegin =
|
||||
pCache->pPos = &pCache->Buffer[0];
|
||||
pCache->pEnd = pCache->pBegin + pCache->dwBuffSize;
|
||||
}
|
||||
|
||||
return pCache->dwBuffSize;
|
||||
}
|
||||
|
||||
static size_t ReadLine(TListFileCache * pCache, char * szLine, int nMaxChars)
|
||||
{
|
||||
char * szLineBegin = szLine;
|
||||
char * szLineEnd = szLine + nMaxChars - 1;
|
||||
|
||||
__BeginLoading:
|
||||
|
||||
// Skip newlines, spaces, tabs and another non-printable stuff
|
||||
while(pCache->pPos < pCache->pEnd && *pCache->pPos <= 0x20)
|
||||
pCache->pPos++;
|
||||
|
||||
// Copy the remaining characters
|
||||
while(pCache->pPos < pCache->pEnd && szLine < szLineEnd)
|
||||
{
|
||||
// If we have found a newline, stop loading
|
||||
if(*pCache->pPos == 0x0D || *pCache->pPos == 0x0A)
|
||||
break;
|
||||
|
||||
*szLine++ = *pCache->pPos++;
|
||||
}
|
||||
|
||||
// If we now need to reload the cache, do it
|
||||
if(pCache->pPos == pCache->pEnd)
|
||||
{
|
||||
if(ReloadCache(pCache) > 0)
|
||||
goto __BeginLoading;
|
||||
}
|
||||
|
||||
*szLine = 0;
|
||||
return (szLine - szLineBegin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions (listfile nodes)
|
||||
|
||||
// This function creates the name for the listfile.
|
||||
// the file will be created under unique name in the temporary directory
|
||||
static void GetListFileName(TMPQArchive * /* ha */, char * szListFile)
|
||||
{
|
||||
char szTemp[MAX_PATH];
|
||||
|
||||
// Create temporary file name int TEMP directory
|
||||
GetTempPath(sizeof(szTemp)-1, szTemp);
|
||||
GetTempFileName(szTemp, LISTFILE_NAME, 0, szListFile);
|
||||
}
|
||||
|
||||
// Creates new listfile. The listfile is an array of TListFileNode
|
||||
// structures. The size of the array is the same like the hash table size,
|
||||
// the ordering is the same too (listfile item index is the same like
|
||||
// the index in the MPQ hash table)
|
||||
|
||||
int SListFileCreateListFile(TMPQArchive * ha)
|
||||
{
|
||||
DWORD dwItems = ha->pHeader->dwHashTableSize;
|
||||
|
||||
// The listfile should be NULL now
|
||||
assert(ha->pListFile == NULL);
|
||||
|
||||
ha->pListFile = ALLOCMEM(TFileNode *, dwItems);
|
||||
if(ha->pListFile == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
memset(ha->pListFile, 0xFF, dwItems * sizeof(TFileNode *));
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// Adds a name into the list of all names. For each locale in the MPQ,
|
||||
// one entry will be created
|
||||
// If the file name is already there, does nothing.
|
||||
int SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szFileName)
|
||||
{
|
||||
TFileNode * pNode = NULL;
|
||||
TMPQHash * pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
TMPQHash * pHash0 = GetHashEntry(ha, szFileName);
|
||||
TMPQHash * pHash = pHash0;
|
||||
DWORD dwHashIndex = 0;
|
||||
size_t nLength; // File name lentgth
|
||||
DWORD dwName1;
|
||||
DWORD dwName2;
|
||||
|
||||
// If the file does not exist within the MPQ, do nothing
|
||||
if(pHash == NULL)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// Remember the name
|
||||
dwName1 = pHash->dwName1;
|
||||
dwName2 = pHash->dwName2;
|
||||
|
||||
// Pass all entries in the hash table
|
||||
while(pHash->dwBlockIndex != HASH_ENTRY_FREE)
|
||||
{
|
||||
// There may be an entry deleted amongst various language versions
|
||||
if(pHash->dwBlockIndex != HASH_ENTRY_DELETED)
|
||||
{
|
||||
if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2)
|
||||
{
|
||||
// Compute the hash index
|
||||
dwHashIndex = (DWORD)(pHash - ha->pHashTable);
|
||||
|
||||
// Create the lang version, if none
|
||||
if((DWORD_PTR)ha->pListFile[dwHashIndex] >= LISTFILE_ENTRY_DELETED)
|
||||
{
|
||||
// Create the listfile node, if doesn't exist yet
|
||||
if(pNode == NULL)
|
||||
{
|
||||
nLength = strlen(szFileName);
|
||||
pNode = (TFileNode *)ALLOCMEM(char, sizeof(TFileNode) + nLength);
|
||||
pNode->dwRefCount = 0;
|
||||
pNode->nLength = nLength;
|
||||
strcpy(pNode->szFileName, szFileName);
|
||||
}
|
||||
|
||||
// Insert the node to the listfile table
|
||||
ha->pListFile[dwHashIndex] = pNode;
|
||||
pNode->dwRefCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwHashIndex = (DWORD)(pHash - ha->pHashTable);
|
||||
ha->pListFile[dwHashIndex] = (TFileNode *)LISTFILE_ENTRY_DELETED;
|
||||
}
|
||||
|
||||
// Move to the next hash entry
|
||||
if(++pHash >= pHashEnd)
|
||||
pHash = ha->pHashTable;
|
||||
if(pHash == pHash0)
|
||||
break;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// Adds a filename into the listfile. If the file name is already there,
|
||||
// does nothing.
|
||||
int SListFileCreateNode(TMPQArchive * ha, const char * szFileName, LCID lcLocale)
|
||||
{
|
||||
TFileNode * pNode = NULL;
|
||||
TMPQHash * pHash0 = GetHashEntry(ha, szFileName);
|
||||
TMPQHash * pHash1 = GetHashEntryEx(ha, szFileName, lcLocale);
|
||||
DWORD dwHashIndex0 = 0;
|
||||
DWORD dwHashIndex1 = 0;
|
||||
size_t nLength; // File name lentgth
|
||||
|
||||
// If the file does not exist within the MPQ, do nothing
|
||||
if(pHash1 == NULL || pHash1->dwBlockIndex >= HASH_ENTRY_DELETED)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// If the locale-cpecific listfile entry already exists, do nothing
|
||||
dwHashIndex0 = (DWORD)(pHash0 - ha->pHashTable);
|
||||
dwHashIndex1 = (DWORD)(pHash1 - ha->pHashTable);
|
||||
if((DWORD_PTR)ha->pListFile[dwHashIndex1] < LISTFILE_ENTRY_DELETED)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// Does the neutral table entry exist ?
|
||||
if((DWORD_PTR)ha->pListFile[dwHashIndex0] < LISTFILE_ENTRY_DELETED)
|
||||
pNode = ha->pListFile[dwHashIndex0];
|
||||
|
||||
// If no node yet, we have to create new one
|
||||
if(pNode == NULL)
|
||||
{
|
||||
nLength = strlen(szFileName);
|
||||
pNode = (TFileNode *)ALLOCMEM(char, sizeof(TFileNode) + nLength);
|
||||
pNode->dwRefCount = 1;
|
||||
pNode->nLength = nLength;
|
||||
strcpy(pNode->szFileName, szFileName);
|
||||
ha->pListFile[dwHashIndex0] = pNode;
|
||||
}
|
||||
|
||||
// Also insert the node in the locale-specific entry
|
||||
if(dwHashIndex1 != dwHashIndex0)
|
||||
{
|
||||
pNode->dwRefCount++;
|
||||
ha->pListFile[dwHashIndex1] = pNode;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// Removes a filename from the listfile.
|
||||
// If the name is not there, does nothing
|
||||
int SListFileRemoveNode(TMPQArchive * ha, const char * szFileName, LCID lcLocale)
|
||||
{
|
||||
TFileNode * pNode = NULL;
|
||||
TMPQHash * pHash = GetHashEntryEx(ha, szFileName, lcLocale);
|
||||
size_t nHashIndex = 0;
|
||||
|
||||
if(pHash != NULL)
|
||||
{
|
||||
nHashIndex = pHash - ha->pHashTable;
|
||||
pNode = ha->pListFile[nHashIndex];
|
||||
ha->pListFile[nHashIndex] = (TFileNode *)LISTFILE_ENTRY_DELETED;
|
||||
|
||||
// Free the node
|
||||
pNode->dwRefCount--;
|
||||
if(pNode->dwRefCount == 0)
|
||||
FREEMEM(pNode);
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
void SListFileFreeListFile(TMPQArchive * ha)
|
||||
{
|
||||
if(ha->pListFile != NULL)
|
||||
{
|
||||
for(DWORD i = 0; i < ha->pHeader->dwHashTableSize; i++)
|
||||
{
|
||||
TFileNode * pNode = ha->pListFile[i];
|
||||
|
||||
if((DWORD_PTR)pNode < LISTFILE_ENTRY_DELETED)
|
||||
{
|
||||
ha->pListFile[i] = (TFileNode *)LISTFILE_ENTRY_FREE;
|
||||
pNode->dwRefCount--;
|
||||
|
||||
if(pNode->dwRefCount == 0)
|
||||
FREEMEM(pNode);
|
||||
}
|
||||
}
|
||||
|
||||
FREEMEM(ha->pListFile);
|
||||
ha->pListFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Saves the whole listfile into the MPQ.
|
||||
int SListFileSaveToMpq(TMPQArchive * ha)
|
||||
{
|
||||
TFileNode * pNode = NULL;
|
||||
TMPQHash * pHashEnd = NULL;
|
||||
TMPQHash * pHash0 = NULL;
|
||||
TMPQHash * pHash = NULL;
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
char szListFile[MAX_PATH];
|
||||
char szBuffer[MAX_PATH+4];
|
||||
DWORD dwTransferred;
|
||||
size_t nLength = 0;
|
||||
DWORD dwName1 = 0;
|
||||
DWORD dwName2 = 0;
|
||||
LCID lcSave = lcLocale;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// If no listfile, do nothing
|
||||
if(ha->pListFile == NULL)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// Create the local listfile
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
GetListFileName(ha, szListFile);
|
||||
hFile = CreateFile(szListFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Find the hash entry corresponding to listfile
|
||||
pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
|
||||
pHash0 = pHash = GetHashEntry(ha, 0);
|
||||
if(pHash == NULL)
|
||||
pHash0 = pHash = ha->pHashTable;
|
||||
|
||||
// Save the file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(pHash->dwName1 != dwName1 && pHash->dwName2 != dwName2 && pHash->dwBlockIndex < HASH_ENTRY_DELETED)
|
||||
{
|
||||
dwName1 = pHash->dwName1;
|
||||
dwName2 = pHash->dwName2;
|
||||
pNode = ha->pListFile[pHash - ha->pHashTable];
|
||||
|
||||
if((DWORD_PTR)pNode < LISTFILE_ENTRY_DELETED)
|
||||
{
|
||||
memcpy(szBuffer, pNode->szFileName, pNode->nLength);
|
||||
szBuffer[pNode->nLength + 0] = 0x0D;
|
||||
szBuffer[pNode->nLength + 1] = 0x0A;
|
||||
WriteFile(hFile, szBuffer, (DWORD)(pNode->nLength + 2), &dwTransferred, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if(++pHash >= pHashEnd)
|
||||
pHash = ha->pHashTable;
|
||||
if(pHash == pHash0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Write the listfile name (if not already there)
|
||||
if(GetHashEntry(ha, LISTFILE_NAME) == NULL)
|
||||
{
|
||||
nLength = strlen(LISTFILE_NAME);
|
||||
memcpy(szBuffer, LISTFILE_NAME, nLength);
|
||||
szBuffer[nLength + 0] = 0x0D;
|
||||
szBuffer[nLength + 1] = 0x0A;
|
||||
WriteFile(hFile, szBuffer, (DWORD)(nLength + 2), &dwTransferred, NULL);
|
||||
}
|
||||
|
||||
// Add the listfile into the archive.
|
||||
SFileSetLocale(LANG_NEUTRAL);
|
||||
nError = AddFileToArchive(ha,
|
||||
hFile,
|
||||
LISTFILE_NAME,
|
||||
MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING,
|
||||
0,
|
||||
SFILE_TYPE_DATA,
|
||||
NULL);
|
||||
lcLocale = lcSave;
|
||||
}
|
||||
|
||||
// Close the temporary file and delete it.
|
||||
// There is no FILE_FLAG_DELETE_ON_CLOSE on LINUX.
|
||||
if(hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hFile);
|
||||
DeleteFile(szListFile);
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File functions
|
||||
|
||||
// Adds a listfile into the MPQ archive.
|
||||
// Note that the function does not remove the
|
||||
int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
HANDLE hListFile = NULL;
|
||||
char szFileName[MAX_PATH + 1];
|
||||
DWORD dwSearchScope = SFILE_OPEN_LOCAL_FILE;
|
||||
DWORD dwCacheSize = 0;
|
||||
DWORD dwFileSize = 0;
|
||||
size_t nLength = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// If the szListFile is NULL, it means we have to open internal listfile
|
||||
if(szListFile == NULL)
|
||||
{
|
||||
szListFile = LISTFILE_NAME;
|
||||
dwSearchScope = SFILE_OPEN_FROM_MPQ;
|
||||
}
|
||||
|
||||
// Open the local/internal listfile
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!SFileOpenFileEx((HANDLE)ha, szListFile, dwSearchScope, &hListFile))
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
dwCacheSize =
|
||||
dwFileSize = SFileGetFileSize(hListFile, NULL);
|
||||
|
||||
// Try to allocate memory for the complete file. If it fails,
|
||||
// load the part of the file
|
||||
pCache = (TListFileCache *)ALLOCMEM(char, (sizeof(TListFileCache) + dwCacheSize));
|
||||
if(pCache == NULL)
|
||||
{
|
||||
dwCacheSize = LISTFILE_CACHE_SIZE;
|
||||
pCache = (TListFileCache *)ALLOCMEM(char, sizeof(TListFileCache) + dwCacheSize);
|
||||
}
|
||||
|
||||
if(pCache == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Initialize the file cache
|
||||
memset(pCache, 0, sizeof(TListFileCache));
|
||||
pCache->hFile = hListFile;
|
||||
pCache->dwFileSize = dwFileSize;
|
||||
pCache->dwBuffSize = dwCacheSize;
|
||||
pCache->dwFilePos = 0;
|
||||
|
||||
// Fill the cache
|
||||
SFileReadFile(hListFile, pCache->Buffer, pCache->dwBuffSize, &pCache->dwBuffSize, NULL);
|
||||
|
||||
// Initialize the pointers
|
||||
pCache->pBegin =
|
||||
pCache->pPos = &pCache->Buffer[0];
|
||||
pCache->pEnd = pCache->pBegin + pCache->dwBuffSize;
|
||||
|
||||
// Load the node list. Add the node for every locale in the archive
|
||||
while((nLength = ReadLine(pCache, szFileName, sizeof(szFileName) - 1)) > 0)
|
||||
SListFileCreateNodeForAllLocales(ha, szFileName);
|
||||
|
||||
// Also, add three special files to the listfile:
|
||||
// (listfile) itself, (attributes) and (signature)
|
||||
SListFileCreateNodeForAllLocales(ha, LISTFILE_NAME);
|
||||
SListFileCreateNodeForAllLocales(ha, SIGNATURE_NAME);
|
||||
SListFileCreateNodeForAllLocales(ha, ATTRIBUTES_NAME);
|
||||
}
|
||||
|
||||
// Cleanup & exit
|
||||
if(pCache != NULL)
|
||||
SListFileFindClose((HANDLE)pCache);
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Passing through the listfile
|
||||
|
||||
HANDLE SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
HANDLE hListFile = NULL;
|
||||
DWORD dwSearchScope = SFILE_OPEN_LOCAL_FILE;
|
||||
DWORD dwCacheSize = 0;
|
||||
DWORD dwFileSize = 0;
|
||||
size_t nLength = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Initialize the structure with zeros
|
||||
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
|
||||
|
||||
// If the szListFile is NULL, it means we have to open internal listfile
|
||||
if(szListFile == NULL)
|
||||
{
|
||||
szListFile = LISTFILE_NAME;
|
||||
dwSearchScope = SFILE_OPEN_FROM_MPQ;
|
||||
}
|
||||
|
||||
// Open the local/internal listfile
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!SFileOpenFileEx((HANDLE)ha, szListFile, dwSearchScope, &hListFile))
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
dwCacheSize =
|
||||
dwFileSize = SFileGetFileSize(hListFile, NULL);
|
||||
|
||||
// Try to allocate memory for the complete file. If it fails,
|
||||
// load the part of the file
|
||||
pCache = (TListFileCache *)ALLOCMEM(char, sizeof(TListFileCache) + dwCacheSize);
|
||||
if(pCache == NULL)
|
||||
{
|
||||
dwCacheSize = LISTFILE_CACHE_SIZE;
|
||||
pCache = (TListFileCache *)ALLOCMEM(char, sizeof(TListFileCache) + dwCacheSize);
|
||||
}
|
||||
|
||||
if(pCache == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Initialize the file cache
|
||||
memset(pCache, 0, sizeof(TListFileCache));
|
||||
pCache->hFile = hListFile;
|
||||
pCache->dwFileSize = dwFileSize;
|
||||
pCache->dwBuffSize = dwCacheSize;
|
||||
pCache->dwFilePos = 0;
|
||||
if(szMask != NULL)
|
||||
{
|
||||
pCache->szMask = ALLOCMEM(char, strlen(szMask) + 1);
|
||||
strcpy(pCache->szMask, szMask);
|
||||
}
|
||||
|
||||
// Fill the cache
|
||||
SFileReadFile(hListFile, pCache->Buffer, pCache->dwBuffSize, &pCache->dwBuffSize, NULL);
|
||||
|
||||
// Initialize the pointers
|
||||
pCache->pBegin =
|
||||
pCache->pPos = &pCache->Buffer[0];
|
||||
pCache->pEnd = pCache->pBegin + pCache->dwBuffSize;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// Read the (next) line
|
||||
nLength = ReadLine(pCache, lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName));
|
||||
if(nLength == 0)
|
||||
{
|
||||
nError = ERROR_NO_MORE_FILES;
|
||||
break;
|
||||
}
|
||||
|
||||
// If some mask entered, check it
|
||||
if(CheckWildCard(lpFindFileData->cFileName, pCache->szMask))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup & exit
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
|
||||
SListFileFindClose((HANDLE)pCache);
|
||||
pCache = NULL;
|
||||
|
||||
SetLastError(nError);
|
||||
}
|
||||
return (HANDLE)pCache;
|
||||
}
|
||||
|
||||
BOOL SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TListFileCache * pCache = (TListFileCache *)hFind;
|
||||
size_t nLength;
|
||||
BOOL bResult = FALSE;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// Read the (next) line
|
||||
nLength = ReadLine(pCache, lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName));
|
||||
if(nLength == 0)
|
||||
{
|
||||
nError = ERROR_NO_MORE_FILES;
|
||||
break;
|
||||
}
|
||||
|
||||
// If some mask entered, check it
|
||||
if(CheckWildCard(lpFindFileData->cFileName, pCache->szMask))
|
||||
{
|
||||
bResult = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
BOOL SListFileFindClose(HANDLE hFind)
|
||||
{
|
||||
TListFileCache * pCache = (TListFileCache *)hFind;
|
||||
|
||||
if(pCache != NULL)
|
||||
{
|
||||
if(pCache->hFile != NULL)
|
||||
SFileCloseFile(pCache->hFile);
|
||||
if(pCache->szMask != NULL)
|
||||
FREEMEM(pCache->szMask);
|
||||
|
||||
FREEMEM(pCache);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
22
src/dep/src/StormLib/StormLib.bat
Normal file
22
src/dep/src/StormLib/StormLib.bat
Normal file
@ -0,0 +1,22 @@
|
||||
@echo off
|
||||
rem Post-build batch for StormLib project
|
||||
rem Called as StormLib.bat $(PlatformName) $(ConfigurationName)
|
||||
rem Example: StormLib.bat x64 Debug
|
||||
|
||||
copy src\StormPort.h ..\aaa\inc
|
||||
copy src\StormLib.h ..\aaa\inc
|
||||
|
||||
if x%1 == xWin32 goto PlatformWin32
|
||||
if x%1 == xx64 goto PlatformWin64
|
||||
goto exit
|
||||
|
||||
:PlatformWin32
|
||||
copy .\bin\Stormlib\%1\%2\*.lib ..\aaa\lib32
|
||||
goto exit
|
||||
|
||||
:PlatformWin64
|
||||
copy .\bin\Stormlib\%1\%2\*.lib ..\aaa\lib64
|
||||
goto exit
|
||||
|
||||
:exit
|
||||
|
||||
@ -1,644 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* StormLib.h Copyright (c) Ladislav Zezula 1999-2005 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* StormLib library v 5.00 */
|
||||
/* */
|
||||
/* Author : Ladislav Zezula */
|
||||
/* E-mail : ladik@zezula.net */
|
||||
/* WWW : http://www.zezula.net */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.99 1.00 Lad Created */
|
||||
/* 24.03.03 2.50 Lad Version 2.50 */
|
||||
/* 02.04.03 3.00 Lad Version 3.00 with compression */
|
||||
/* 11.04.03 3.01 Lad Renamed to StormLib.h for compatibility with */
|
||||
/* original headers for Storm.dll */
|
||||
/* 10.05.03 3.02 Lad Added Pkware DCL compression */
|
||||
/* 26.05.03 4.00 Lad Completed all compressions */
|
||||
/* 18.06.03 4.01 Lad Added SFileSetFileLocale */
|
||||
/* Added SFileExtractFile */
|
||||
/* 26.07.03 4.02 Lad Implemented nameless rename and delete */
|
||||
/* 26.07.03 4.03 Lad Added support for protected MPQs */
|
||||
/* 28.08.03 4.10 Lad Fixed bugs that caused StormLib incorrectly work */
|
||||
/* with Diablo I savegames and with files having full */
|
||||
/* hash table */
|
||||
/* 08.12.03 4.11 DCH Fixed bug in reading file block larger than 0x1000 */
|
||||
/* on certain files. */
|
||||
/* Fixed bug in AddFile with MPQ_FILE_REPLACE_EXISTING */
|
||||
/* (Thanx Daniel Chiamarello, dchiamarello@madvawes.com)*/
|
||||
/* 21.12.03 4.50 Lad Completed port for Mac */
|
||||
/* Fixed bug in compacting (if fsize is mul of 0x1000) */
|
||||
/* Fixed bug in SCompCompress */
|
||||
/* 27.05.04 4.51 Lad Changed memory management from new/delete to our */
|
||||
/* own macros */
|
||||
/* 22.06.04 4.60 Lad Optimized search. Support for multiple listfiles. */
|
||||
/* 30.09.04 4.61 Lad Fixed some bugs (Aaargh !!!) */
|
||||
/* Correctly works if HashTableSize > BlockTableSize */
|
||||
/* 29.12.04 4.70 Lad Fixed compatibility problem with MPQs from WoW */
|
||||
/* 14.07.05 5.00 Lad Added the BZLIB compression support */
|
||||
/* Added suport of files stored as single unit */
|
||||
/* 17.04.06 5.01 Lad Converted to MS Visual Studio 8.0 */
|
||||
/* Fixed issue with protected Warcraft 3 protected maps */
|
||||
/* 15.05.06 5.02 Lad Fixed issue with WoW 1.10+ */
|
||||
/* 07.09.06 5.10 Lad Fixed processing files longer than 2GB */
|
||||
/* 22.11.06 6.00 Lad Support for MPQ archives V2 */
|
||||
/* 12.06.07 6.10 Lad Support for extended file attributes */
|
||||
/* 10.09.07 6.12 Lad Support for MPQs protected by corrupting hash table */
|
||||
/* 03.12.07 6.13 Lad Support for MPQs with hash tbl size > block tbl size */
|
||||
/* 07.04.08 6.20 Lad Added SFileFlushArchive */
|
||||
/* 09.04.08 Lad Removed FilePointer variable from TMPQArchive, as */
|
||||
/* it caused more problems than benefits */
|
||||
/* 12.05.08 6.22 Lad Support for w3xMaster map protector */
|
||||
/* 05.10.08 6.23 Lad Support for protectors who set negative values in */
|
||||
/* the table of file blocks */
|
||||
/* 26.05.09 6.24 Lad Fixed search for multiple lang files with deleted */
|
||||
/* entries */
|
||||
/* 03.09.09 6.25 Lad Fixed decompression bug in huffmann decompression */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __STORMLIB_H_
|
||||
#define __STORMLIB_H_
|
||||
|
||||
#include "StormPort.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Use the apropriate library
|
||||
//
|
||||
// The library type is encoded in the library name as the following
|
||||
// StormLibXYZ.lib
|
||||
//
|
||||
// X - D for Debug version, R for Release version
|
||||
// Y - A for ANSI version, U for Unicode version (Unicode version does not exist yet)
|
||||
// Z - S for static C library, D for multithreaded DLL C-library
|
||||
//
|
||||
|
||||
// #if defined(_MSC_VER) && !defined (__STORMLIB_SELF__)
|
||||
// #ifdef _DEBUG // DEBUG VERSIONS
|
||||
// #ifdef _DLL
|
||||
// #pragma comment(lib, "StormLibDAD.lib") // Debug Ansi Dynamic version
|
||||
// #else
|
||||
// #pragma comment(lib, "StormLibDAS.lib") // Debug Ansi Static version
|
||||
// #endif
|
||||
// #else // RELEASE VERSIONS
|
||||
// #ifdef _DLL
|
||||
// #pragma comment(lib, "StormLibRAD.lib") // Release Ansi Dynamic version
|
||||
// #else
|
||||
// #pragma comment(lib, "StormLibRAS.lib") // Release Ansi Static version
|
||||
// #endif
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A')
|
||||
#define ID_MPQ_SHUNT 0x1B51504D // MPQ shunt entry ('MPQ\x1B')
|
||||
|
||||
#define ERROR_AVI_FILE 10000 // No MPQ file, but AVI file.
|
||||
|
||||
// Values for SFileCreateArchiveEx
|
||||
#define HASH_TABLE_SIZE_MIN 0x00004
|
||||
#define HASH_TABLE_SIZE_MAX 0x40000
|
||||
|
||||
#define HASH_ENTRY_DELETED 0xFFFFFFFE // Block index for deleted hash entry
|
||||
#define HASH_ENTRY_FREE 0xFFFFFFFF // Block index for free hash entry
|
||||
|
||||
// Values for SFileOpenArchive
|
||||
#define SFILE_OPEN_HARD_DISK_FILE 2 // Open the archive on HDD
|
||||
#define SFILE_OPEN_CDROM_FILE 3 // Open the archive only if it is on CDROM
|
||||
|
||||
// Values for SFileOpenFile
|
||||
#define SFILE_OPEN_FROM_MPQ 0 // Open the file from the MPQ archive
|
||||
#define SFILE_OPEN_BY_INDEX 1 // The 'szFileName' parameter is actually the file index
|
||||
#define SFILE_OPEN_LOCAL_FILE (DWORD)-1 // Open the file from the MPQ archive
|
||||
|
||||
// Flags for TMPQArchive::dwFlags
|
||||
#define MPQ_FLAG_CHANGED 0x00000001 // If set, the MPQ has been changed
|
||||
#define MPQ_FLAG_PROTECTED 0x00000002 // Set on protected MPQs (like W3M maps)
|
||||
|
||||
// Flags for SFileAddFile
|
||||
// Note: MPQ_FILE_COMPRESS_PKWARE has been replaced by MPQ_FILE_IMPLODE
|
||||
// Note: MPQ_FILE_COMPRESS_MULTI has been replaced by MPQ_FILE_COMPRESS
|
||||
#define MPQ_FILE_IMPLODE 0x00000100 // Implode method (By PKWARE Data Compression Library)
|
||||
#define MPQ_FILE_COMPRESS 0x00000200 // Compress methods (My various methods)
|
||||
#define MPQ_FILE_COMPRESSED 0x0000FF00 // File is compressed
|
||||
#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted
|
||||
#define MPQ_FILE_FIXSEED 0x00020000 // File decrypt seed has to be fixed
|
||||
#define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam)
|
||||
#define MPQ_FILE_DUMMY_FILE 0x02000000 // The file is only 1 byte long and its name is a hash
|
||||
#define MPQ_FILE_HAS_EXTRA 0x04000000 // The file has extra data appended after regular data.
|
||||
// Must be with compressed files only
|
||||
#define MPQ_FILE_EXISTS 0x80000000 // Set if file exists, reset when the file was deleted
|
||||
#define MPQ_FILE_REPLACEEXISTING 0x80000000 // Replace when the file exist (SFileAddFile)
|
||||
|
||||
#define MPQ_FILE_VALID_FLAGS (MPQ_FILE_IMPLODE | \
|
||||
MPQ_FILE_COMPRESS | \
|
||||
MPQ_FILE_ENCRYPTED | \
|
||||
MPQ_FILE_FIXSEED | \
|
||||
MPQ_FILE_SINGLE_UNIT | \
|
||||
MPQ_FILE_DUMMY_FILE | \
|
||||
MPQ_FILE_HAS_EXTRA | \
|
||||
MPQ_FILE_EXISTS)
|
||||
|
||||
// Compression types for multilpe compressions
|
||||
#define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only)
|
||||
#define MPQ_COMPRESSION_ZLIB 0x02 // ZLIB compression
|
||||
#define MPQ_COMPRESSION_PKWARE 0x08 // PKWARE DCL compression
|
||||
#define MPQ_COMPRESSION_BZIP2 0x10 // BZIP2 compression
|
||||
#define MPQ_COMPRESSION_WAVE_MONO 0x40 //
|
||||
#define MPQ_COMPRESSION_WAVE_STEREO 0x80 //
|
||||
|
||||
|
||||
// Constants for SFileAddWave
|
||||
#define MPQ_WAVE_QUALITY_HIGH 0 // Best quality, the worst compression
|
||||
#define MPQ_WAVE_QUALITY_MEDIUM 1 // Medium quality, medium compression
|
||||
#define MPQ_WAVE_QUALITY_LOW 2 // Low quality, the best compression
|
||||
|
||||
// Constants for SFileGetFileInfo
|
||||
#define SFILE_INFO_ARCHIVE_SIZE 1 // MPQ size (value from header)
|
||||
#define SFILE_INFO_HASH_TABLE_SIZE 2 // Size of hash table, in entries
|
||||
#define SFILE_INFO_BLOCK_TABLE_SIZE 3 // Number of entries in the block table
|
||||
#define SFILE_INFO_BLOCK_SIZE 4 // Size of file block (in bytes)
|
||||
#define SFILE_INFO_HASH_TABLE 5 // Pointer to Hash table (TMPQHash *)
|
||||
#define SFILE_INFO_BLOCK_TABLE 6 // Pointer to Block Table (TMPQBlock *)
|
||||
#define SFILE_INFO_NUM_FILES 7 // Real number of files within archive
|
||||
//------
|
||||
#define SFILE_INFO_HASH_INDEX 8 // Hash index of file in MPQ
|
||||
#define SFILE_INFO_CODENAME1 9 // The first codename of the file
|
||||
#define SFILE_INFO_CODENAME2 10 // The second codename of the file
|
||||
#define SFILE_INFO_LOCALEID 11 // Locale ID of file in MPQ
|
||||
#define SFILE_INFO_BLOCKINDEX 12 // Index to Block Table
|
||||
#define SFILE_INFO_FILE_SIZE 13 // Original file size
|
||||
#define SFILE_INFO_COMPRESSED_SIZE 14 // Compressed file size
|
||||
#define SFILE_INFO_FLAGS 15 // File flags
|
||||
#define SFILE_INFO_POSITION 16 // File position within archive
|
||||
#define SFILE_INFO_SEED 17 // File decryption seed
|
||||
#define SFILE_INFO_SEED_UNFIXED 18 // Decryption seed not fixed to file pos and size
|
||||
|
||||
// Values for compact callback
|
||||
#define CCB_CHECKING_FILES 1 // Checking archive (dwParam1 = current, dwParam2 = total)
|
||||
#define CCB_CHECKING_HASH_TABLE 2 // Checking hash table (dwParam1 = current, dwParam2 = total)
|
||||
#define CCB_COPYING_NON_MPQ_DATA 3 // Copying non-MPQ data: No params used
|
||||
#define CCB_COMPACTING_FILES 4 // Compacting archive (dwParam1 = current, dwParam2 = total)
|
||||
#define CCB_CLOSING_ARCHIVE 5 // Closing archive: No params used
|
||||
|
||||
#define LISTFILE_NAME "(listfile)" // Name of internal listfile
|
||||
#define SIGNATURE_NAME "(signature)" // Name of internal signature
|
||||
#define ATTRIBUTES_NAME "(attributes)" // Name of internal attributes file
|
||||
|
||||
#define STORMLIB_VERSION (0x0619) // Current version of StormLib
|
||||
|
||||
#define MPQ_FORMAT_VERSION_1 0 // Up to The Burning Crusade
|
||||
#define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer
|
||||
|
||||
// Flags for SFileOpenArchiveEx
|
||||
#define MPQ_OPEN_NO_LISTFILE 0x00000001 // Don't add the internal listfile
|
||||
#define MPQ_OPEN_NO_ATTRIBUTES 0x00000002 // Don't open the attributes
|
||||
#define MPQ_OPEN_FORCE_MPQ_V1 0x00000004 // Always open the archive as MPQ v 1.00, ignore the "wFormatVersion" variable in the header
|
||||
|
||||
// Flags for MPQ attributes
|
||||
#define MPQ_ATTRIBUTE_CRC32 0x00000001 // The "(attributes)" contain array of CRC32s
|
||||
#define MPQ_ATTRIBUTE_FILETIME 0x00000002 // The "(attributes)" contain array of FILETIMEs
|
||||
#define MPQ_ATTRIBUTE_MD5 0x00000004 // The "(attributes)" contain array of MD5s
|
||||
|
||||
// Supports archives with size > 4 GB
|
||||
// Additional flags for SFileCreateArchiveEx
|
||||
#define MPQ_CREATE_ARCHIVE_V1 0x00000000 // Creates archive with size up to 4GB
|
||||
#define MPQ_CREATE_ARCHIVE_V2 0x00010000 // Creates archive larger than 4 GB
|
||||
#define MPQ_CREATE_ATTRIBUTES 0x00100000 // Also add the (attributes) file
|
||||
|
||||
// Formats of (attributes) file
|
||||
#define MPQ_ATTRIBUTES_V1 100 // FOrmat version 1.00
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures
|
||||
|
||||
#if (defined(WIN32) || defined(WIN64))
|
||||
#include <pshpack1.h>
|
||||
#else
|
||||
#pragma pack(push,1)
|
||||
#endif
|
||||
|
||||
struct TMPQFile;
|
||||
|
||||
struct TMPQShunt
|
||||
{
|
||||
// The ID_MPQ_SHUNT ('MPQ\x1B') signature
|
||||
DWORD dwID;
|
||||
|
||||
DWORD dwUnknown;
|
||||
|
||||
// Position of the MPQ header, relative to the begin of the shunt
|
||||
DWORD dwHeaderPos;
|
||||
};
|
||||
|
||||
|
||||
// MPQ file header
|
||||
struct TMPQHeader
|
||||
{
|
||||
// The ID_MPQ ('MPQ\x1A') signature
|
||||
DWORD dwID;
|
||||
|
||||
// Size of the archive header
|
||||
DWORD dwHeaderSize;
|
||||
|
||||
// Size of MPQ archive
|
||||
// This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive
|
||||
// is calculated as the size from the beginning of the archive to the end of the hash table,
|
||||
// block table, or extended block table (whichever is largest).
|
||||
DWORD dwArchiveSize;
|
||||
|
||||
// 0 = Original format
|
||||
// 1 = Extended format (The Burning Crusade and newer)
|
||||
USHORT wFormatVersion;
|
||||
|
||||
// Power of two exponent specifying the number of 512-byte disk sectors in each logical sector
|
||||
// in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift.
|
||||
// Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors).
|
||||
USHORT wBlockSize;
|
||||
|
||||
// Offset to the beginning of the hash table, relative to the beginning of the archive.
|
||||
DWORD dwHashTablePos;
|
||||
|
||||
// Offset to the beginning of the block table, relative to the beginning of the archive.
|
||||
DWORD dwBlockTablePos;
|
||||
|
||||
// Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for
|
||||
// the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
|
||||
DWORD dwHashTableSize;
|
||||
|
||||
// Number of entries in the block table
|
||||
DWORD dwBlockTableSize;
|
||||
};
|
||||
|
||||
|
||||
// Extended MPQ file header. Valid only if wFormatVersion is 1 or higher
|
||||
struct TMPQHeader2 : public TMPQHeader
|
||||
{
|
||||
// Offset to the beginning of the extended block table, relative to the beginning of the archive.
|
||||
LARGE_INTEGER ExtBlockTablePos;
|
||||
|
||||
// High 16 bits of the hash table offset for large archives.
|
||||
USHORT wHashTablePosHigh;
|
||||
|
||||
// High 16 bits of the block table offset for large archives.
|
||||
USHORT wBlockTablePosHigh;
|
||||
};
|
||||
|
||||
|
||||
// Hash entry. All files in the archive are searched by their hashes.
|
||||
struct TMPQHash
|
||||
{
|
||||
// The hash of the file path, using method A.
|
||||
DWORD dwName1;
|
||||
|
||||
// The hash of the file path, using method B.
|
||||
DWORD dwName2;
|
||||
|
||||
#if PLATFORM_LITTLE_ENDIAN
|
||||
|
||||
// The language of the file. This is a Windows LANGID data type, and uses the same values.
|
||||
// 0 indicates the default language (American English), or that the file is language-neutral.
|
||||
USHORT lcLocale;
|
||||
|
||||
// The platform the file is used for. 0 indicates the default platform.
|
||||
// No other values have been observed.
|
||||
USHORT wPlatform;
|
||||
|
||||
#else
|
||||
|
||||
USHORT wPlatform;
|
||||
USHORT lcLocale;
|
||||
|
||||
#endif
|
||||
|
||||
// If the hash table entry is valid, this is the index into the block table of the file.
|
||||
// Otherwise, one of the following two values:
|
||||
// - FFFFFFFFh: Hash table entry is empty, and has always been empty.
|
||||
// Terminates searches for a given file.
|
||||
// - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file).
|
||||
// Does not terminate searches for a given file.
|
||||
DWORD dwBlockIndex;
|
||||
};
|
||||
|
||||
|
||||
// File description block contains informations about the file
|
||||
struct TMPQBlock
|
||||
{
|
||||
// Offset of the beginning of the block, relative to the beginning of the archive.
|
||||
DWORD dwFilePos;
|
||||
|
||||
// Compressed file size
|
||||
DWORD dwCSize;
|
||||
|
||||
// Only valid if the block is a file; otherwise meaningless, and should be 0.
|
||||
// If the file is compressed, this is the size of the uncompressed file data.
|
||||
DWORD dwFSize;
|
||||
|
||||
// Flags for the file. See MPQ_FILE_XXXX constants
|
||||
DWORD dwFlags;
|
||||
};
|
||||
|
||||
|
||||
// The extended block table was added to support archives larger than 4 gigabytes (2^32 bytes).
|
||||
// The table contains the upper bits of the archive offsets for each block in the block table.
|
||||
// It is simply an array of int16s, which become bits 32-47 of the archive offsets for each block,
|
||||
// with bits 48-63 being zero. Individual blocks in the archive are still limited to 4 gigabytes
|
||||
// in size. This table is only present in Burning Crusade format archives that exceed 4 gigabytes size.
|
||||
struct TMPQBlockEx
|
||||
{
|
||||
USHORT wFilePosHigh;
|
||||
};
|
||||
|
||||
|
||||
struct TFileNode
|
||||
{
|
||||
DWORD dwRefCount; // Number of references
|
||||
// There can be more files that have the same name.
|
||||
// (e.g. multiple language files). We don't want to
|
||||
// have an entry for each of them, so the entries will be referenced.
|
||||
// When a number of node references reaches zero,
|
||||
// the node will be deleted
|
||||
|
||||
size_t nLength; // File name length
|
||||
char szFileName[1]; // File name, variable length
|
||||
};
|
||||
|
||||
|
||||
// CRC32 present in the (attributes) file
|
||||
struct TMPQCRC32
|
||||
{
|
||||
DWORD dwValue; // Value of CRC32 for each block
|
||||
};
|
||||
|
||||
|
||||
// FILETIME present in the (attributes) file
|
||||
struct TMPQFileTime
|
||||
{
|
||||
DWORD dwFileTimeLow; // Low DWORD of the FILETIME
|
||||
DWORD dwFileTimeHigh; // High DWORD of the FILETIME
|
||||
};
|
||||
|
||||
|
||||
// MD5 presetn in the (attributes) file
|
||||
struct TMPQMD5
|
||||
{
|
||||
BYTE Value[0x10]; // 16 bytes of MD5
|
||||
};
|
||||
|
||||
|
||||
// Data from (attributes) file
|
||||
struct TMPQAttr
|
||||
{
|
||||
DWORD dwVersion; // Version of the (attributes) file. Must be 100 (0x64)
|
||||
DWORD dwFlags; // See MPQ_ATTRIBUTE_XXXX
|
||||
TMPQCRC32 * pCrc32; // Array of CRC32 (NULL if none)
|
||||
TMPQFileTime * pFileTime; // Array of FILETIME (NULL if not present)
|
||||
TMPQMD5 * pMd5; // Array of MD5 (NULL if none)
|
||||
};
|
||||
|
||||
|
||||
#if (defined(WIN32) || defined(WIN64))
|
||||
#include <poppack.h>
|
||||
#else
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// Archive handle structure
|
||||
struct TMPQArchive
|
||||
{
|
||||
// TMPQArchive * pNext; // Next archive (used by Storm.dll only)
|
||||
// TMPQArchive * pPrev; // Previous archive (used by Storm.dll only)
|
||||
char szFileName[MAX_PATH]; // Opened archive file name
|
||||
HANDLE hFile; // File handle
|
||||
DWORD dwPriority; // Priority of the archive
|
||||
LARGE_INTEGER ShuntPos; // MPQShunt offset (only valid if a shunt is present)
|
||||
LARGE_INTEGER MpqPos; // File header offset (relative to the begin of the file)
|
||||
LARGE_INTEGER HashTablePos; // Hash table offset (relative to the begin of the file)
|
||||
LARGE_INTEGER BlockTablePos; // Block table offset (relative to the begin of the file)
|
||||
LARGE_INTEGER ExtBlockTablePos; // Ext. block table offset (relative to the begin of the file)
|
||||
LARGE_INTEGER MpqSize; // Size of MPQ archive
|
||||
|
||||
TMPQFile * pLastFile; // Recently read file
|
||||
DWORD dwBlockPos; // Position of loaded block in the file
|
||||
DWORD dwBlockSize; // Size of file block
|
||||
BYTE * pbBlockBuffer; // Buffer (cache) for file block
|
||||
DWORD dwBuffPos; // Position in block buffer
|
||||
TMPQShunt * pShunt; // MPQ shunt (NULL if not present in the file)
|
||||
TMPQHeader2 * pHeader; // MPQ file header
|
||||
TMPQHash * pHashTable; // Hash table
|
||||
TMPQBlock * pBlockTable; // Block table
|
||||
TMPQBlockEx * pExtBlockTable; // Extended block table
|
||||
|
||||
TMPQShunt Shunt; // MPQ shunt. Valid only when ID_MPQ_SHUNT has been found
|
||||
TMPQHeader2 Header; // MPQ header
|
||||
|
||||
TMPQAttr * pAttributes; // MPQ attributes from "(attributes)" file (NULL if none)
|
||||
TFileNode ** pListFile; // File name array
|
||||
DWORD dwFlags; // See MPQ_FLAG_XXXXX
|
||||
};
|
||||
|
||||
|
||||
// File handle structure
|
||||
struct TMPQFile
|
||||
{
|
||||
HANDLE hFile; // File handle
|
||||
TMPQArchive * ha; // Archive handle
|
||||
TMPQHash * pHash; // Hash table entry
|
||||
TMPQBlockEx * pBlockEx; // Pointer to extended file block entry
|
||||
TMPQBlock * pBlock; // File block pointer
|
||||
DWORD dwSeed1; // Seed used for file decrypt
|
||||
DWORD dwFilePos; // Current file position
|
||||
LARGE_INTEGER RawFilePos; // Offset in MPQ archive (relative to file begin)
|
||||
LARGE_INTEGER MpqFilePos; // Offset in MPQ archive (relative to MPQ header)
|
||||
|
||||
DWORD * pdwBlockPos; // Position of each file block (only for compressed files)
|
||||
DWORD nBlocks; // Number of blocks in the file (incl. the last incomplete one)
|
||||
BOOL bBlockPosLoaded; // TRUE if block positions loaded
|
||||
BYTE * pbFileBuffer; // Decompressed file (for single unit files, size is the uncompressed file size)
|
||||
|
||||
TMPQCRC32 * pCrc32; // Pointer to CRC32 (NULL if none)
|
||||
TMPQFileTime * pFileTime; // Pointer to file's FILETIME (NULL if none)
|
||||
TMPQMD5 * pMd5; // Pointer to file's MD5 (NULL if none)
|
||||
|
||||
DWORD dwHashIndex; // Index to Hash table
|
||||
DWORD dwBlockIndex; // Index to Block table
|
||||
char szFileName[1]; // File name (variable length)
|
||||
};
|
||||
|
||||
// Used by searching in MPQ archives
|
||||
struct TMPQSearch
|
||||
{
|
||||
TMPQArchive * ha; // Handle to MPQ, where the search runs
|
||||
DWORD dwNextIndex; // Next hash index to be checked
|
||||
DWORD dwName1; // Lastly found Name1
|
||||
DWORD dwName2; // Lastly found Name2
|
||||
char szSearchMask[1]; // Search mask (variable length)
|
||||
};
|
||||
|
||||
|
||||
struct SFILE_FIND_DATA
|
||||
{
|
||||
char cFileName[MAX_PATH]; // Full name of the found file
|
||||
char * szPlainName; // Pointer to file part
|
||||
LCID lcLocale; // Locale version
|
||||
DWORD dwFileSize; // File size in bytes
|
||||
DWORD dwFileFlags; // File flags (compressed or encrypted)
|
||||
DWORD dwBlockIndex; // Block index for the file
|
||||
DWORD dwCompSize; // Compressed file size
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory management
|
||||
//
|
||||
// We use our own macros for allocating/freeing memory. If you want
|
||||
// to redefine them, please keep the following rules
|
||||
//
|
||||
// - The memory allocation must return NULL if not enough memory
|
||||
// (i.e not to throw exception)
|
||||
// - It is not necessary to fill the allocated block with zeros
|
||||
// - Memory freeing function must not test the pointer to NULL.
|
||||
//
|
||||
|
||||
|
||||
__inline void * DebugMalloc(char * szFile, int nLine, int nSize)
|
||||
{
|
||||
void * ptr = malloc(nSize + 100);
|
||||
char * plain;
|
||||
|
||||
plain = strrchr(szFile, '\\');
|
||||
if(plain == NULL)
|
||||
plain = strrchr(szFile, '/');
|
||||
if(plain == NULL)
|
||||
plain = szFile;
|
||||
|
||||
#if _MSC_VER > 1300
|
||||
sprintf_s((char *)ptr, nSize+100, "%s(%u)", plain, nLine);
|
||||
#else
|
||||
sprintf((char *)ptr, "%s(%u)", plain, nLine);
|
||||
#endif
|
||||
|
||||
return (char *)ptr + 100;
|
||||
}
|
||||
|
||||
|
||||
__inline void DebugFree(void * ptr)
|
||||
{
|
||||
free((char *)ptr - 100);
|
||||
}
|
||||
|
||||
|
||||
#ifndef ALLOCMEM
|
||||
#define ALLOCMEM(type, nitems) (type *)malloc((nitems) * sizeof(type))
|
||||
#define FREEMEM(ptr) free(ptr)
|
||||
#endif
|
||||
|
||||
//#define ALLOCMEM(type, nitems) (type *)DebugMalloc(__FILE__, __LINE__, (nitems) * sizeof(type))
|
||||
//#define FREEMEM(ptr) DebugFree(ptr)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions in StormLib - compatible with Storm.dll
|
||||
|
||||
// Typedefs for functions exported by Storm.dll
|
||||
typedef LCID (WINAPI * SFILESETLOCALE)(LCID);
|
||||
typedef BOOL (WINAPI * SFILEOPENARCHIVE)(const char *, DWORD, DWORD, HANDLE *);
|
||||
typedef BOOL (WINAPI * SFILECLOSEARCHIVE)(HANDLE);
|
||||
typedef BOOL (WINAPI * SFILEOPENFILEEX)(HANDLE, const char *, DWORD, HANDLE *);
|
||||
typedef BOOL (WINAPI * SFILECLOSEFILE)(HANDLE);
|
||||
typedef DWORD (WINAPI * SFILEGETFILESIZE)(HANDLE, DWORD *);
|
||||
typedef DWORD (WINAPI * SFILESETFILEPOINTER)(HANDLE, LONG, LONG *, DWORD);
|
||||
typedef BOOL (WINAPI * SFILEREADFILE)(HANDLE, VOID *, DWORD, DWORD *, LPOVERLAPPED);
|
||||
|
||||
// Archive opening/closing
|
||||
LCID WINAPI SFileSetLocale(LCID lcNewLocale);
|
||||
LCID WINAPI SFileGetLocale();
|
||||
BOOL WINAPI SFileOpenArchive(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMpq);
|
||||
BOOL WINAPI SFileFlushArchive(HANDLE hMpq);
|
||||
BOOL WINAPI SFileCloseArchive(HANDLE hMpq);
|
||||
|
||||
// File opening/closing
|
||||
BOOL WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile);
|
||||
BOOL WINAPI SFileCloseFile(HANDLE hFile);
|
||||
|
||||
// File I/O
|
||||
DWORD WINAPI SFileGetFilePos(HANDLE hFile, DWORD * pdwFilePosHigh = NULL);
|
||||
DWORD WINAPI SFileGetFileSize(HANDLE hFile, DWORD * pdwFileSizeHigh = NULL);
|
||||
DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * pdwFilePosHigh, DWORD dwMethod);
|
||||
BOOL WINAPI SFileReadFile(HANDLE hFile, VOID * lpBuffer, DWORD dwToRead, DWORD * pdwRead = NULL, LPOVERLAPPED lpOverlapped = NULL);
|
||||
|
||||
// Adds another listfile into MPQ. The currently added listfile(s) remain,
|
||||
// so you can use this API to combining more listfiles.
|
||||
// Note that this function is internally called by SFileFindFirstFile
|
||||
int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions in StormLib - not implemented in Storm.dll
|
||||
|
||||
// Archive creating and editing
|
||||
BOOL WINAPI SFileCreateArchiveEx(const char * szMpqName, DWORD dwCreationDisposition, DWORD dwHashTableSize, HANDLE * phMpq);
|
||||
BOOL WINAPI SFileAddFile(HANDLE hMpq, const char * szFileName, const char * szArchivedName, DWORD dwFlags);
|
||||
BOOL WINAPI SFileAddWave(HANDLE hMpq, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality);
|
||||
BOOL WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope = SFILE_OPEN_BY_INDEX);
|
||||
BOOL WINAPI SFileRenameFile(HANDLE hMpq, const char * szOldFileName, const char * szNewFileName);
|
||||
BOOL WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale);
|
||||
|
||||
// Retrieving info about the file
|
||||
BOOL WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName);
|
||||
BOOL WINAPI SFileGetFileName(HANDLE hFile, char * szFileName);
|
||||
DWORD_PTR WINAPI SFileGetFileInfo(HANDLE hMpqOrFile, DWORD dwInfoType);
|
||||
|
||||
// File search
|
||||
// Note that the SFileFindFirstFileEx has been removed. Use SListFileFindFirst/Next
|
||||
HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile);
|
||||
BOOL WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
|
||||
BOOL WINAPI SFileFindClose(HANDLE hFind);
|
||||
|
||||
// Listfile search
|
||||
HANDLE SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData);
|
||||
BOOL SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
|
||||
BOOL SListFileFindClose(HANDLE hFind);
|
||||
|
||||
// Archive compacting
|
||||
typedef void (WINAPI * COMPACTCB)(void * lpUserData, DWORD dwWorkType, DWORD dwParam1, DWORD dwParam2);
|
||||
BOOL WINAPI SFileSetCompactCallback(HANDLE hMpq, COMPACTCB CompactCB, void * lpData);
|
||||
BOOL WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile = NULL, BOOL bReserved = 0);
|
||||
|
||||
// Locale support
|
||||
int WINAPI SFileEnumLocales(HANDLE hMpq, const char * szFileName, LCID * plcLocales, DWORD * pdwMaxLocales, DWORD dwSearchScope);
|
||||
|
||||
// (De)compression
|
||||
int WINAPI SCompCompress (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCompressions, int nCmpType, int nCmpLevel);
|
||||
int WINAPI SCompDecompress (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength);
|
||||
|
||||
// Sets the default data compression for files added to MPQ,
|
||||
// if MPQ_FILE_COMPRESS_MULTI has been specified in call to SFileAddFile
|
||||
// Use one of the MPQ_COMPRESSION_XXX values
|
||||
int WINAPI SCompSetDataCompression(int nDataCompression);
|
||||
|
||||
// Verifies file against its extended attributes (depending on dwFlags).
|
||||
// For dwFlags, use one or more of MPQ_ATTRIBUTE_MD5
|
||||
BOOL WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags);
|
||||
|
||||
// High-level extract function
|
||||
BOOL WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const char * szExtracted);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions from Storm.dll. They use slightly different names for keeping
|
||||
// possibility to use them together with StormLib (StormXXX instead of SFileXXX)
|
||||
|
||||
#ifdef __LINK_STORM_DLL__
|
||||
#define STORM_ALTERNATE_NAMES // Force Storm.h to use alternate fnc names
|
||||
#include "StormDll.h"
|
||||
#endif // __LINK_STORM_DLL__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GFX decode functions. See GfxDecode.cpp for details and description
|
||||
|
||||
USHORT WINAPI celGetFrameCount(BYTE * fileBuf);
|
||||
BYTE * WINAPI celGetFrameData(BYTE *fileBuf, BYTE *palette, USHORT xsize, USHORT frame, USHORT *ysize, USHORT *maxX=NULL);
|
||||
USHORT WINAPI cl2GetFrameCount(BYTE *fileBuf);
|
||||
BYTE ** WINAPI cl2GetDirData(BYTE *fileBuf, BYTE *palette, USHORT xsize, USHORT dir, USHORT *ysize);
|
||||
BYTE * WINAPI pcxGetData(BYTE *filebuf, DWORD filesize, BYTE transcol, USHORT *xsize, USHORT *ysize);
|
||||
|
||||
#endif // __STORMLIB_H_
|
||||
170
src/dep/src/StormLib/StormLib.sln
Normal file
170
src/dep/src/StormLib/StormLib.sln
Normal file
@ -0,0 +1,170 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib_dll", "StormLib_dll.vcproj", "{CB385198-50B1-4CF4-883B-11F042DED6AA}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib_test", "StormLib_test.vcproj", "{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Storm_dll", "Storm_dll.vcproj", "{BD600973-C6FA-4CE3-8821-67F6418B7F9C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib", "StormLib.vcproj", "{78424708-1F6E-4D4B-920C-FB6D26847055}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
DebugAD|Win32 = DebugAD|Win32
|
||||
DebugAD|x64 = DebugAD|x64
|
||||
DebugAS|Win32 = DebugAS|Win32
|
||||
DebugAS|x64 = DebugAS|x64
|
||||
DebugUD|Win32 = DebugUD|Win32
|
||||
DebugUD|x64 = DebugUD|x64
|
||||
DebugUS|Win32 = DebugUS|Win32
|
||||
DebugUS|x64 = DebugUS|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
ReleaseAD|Win32 = ReleaseAD|Win32
|
||||
ReleaseAD|x64 = ReleaseAD|x64
|
||||
ReleaseAS|Win32 = ReleaseAS|Win32
|
||||
ReleaseAS|x64 = ReleaseAS|x64
|
||||
ReleaseUD|Win32 = ReleaseUD|Win32
|
||||
ReleaseUD|x64 = ReleaseUD|x64
|
||||
ReleaseUS|Win32 = ReleaseUS|Win32
|
||||
ReleaseUS|x64 = ReleaseUS|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.Debug|x64.Build.0 = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugAD|Win32.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugAD|x64.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugAD|x64.Build.0 = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugAS|Win32.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugAS|x64.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugAS|x64.Build.0 = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugUD|Win32.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugUD|x64.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugUD|x64.Build.0 = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugUS|Win32.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugUS|x64.ActiveCfg = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.DebugUS|x64.Build.0 = Debug|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.Release|Win32.Build.0 = Release|Win32
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.Release|x64.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.Release|x64.Build.0 = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseAD|Win32.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseAD|x64.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseAD|x64.Build.0 = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseAS|Win32.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseAS|x64.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseAS|x64.Build.0 = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseUD|Win32.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseUD|x64.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseUD|x64.Build.0 = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseUS|Win32.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseUS|x64.ActiveCfg = Release|x64
|
||||
{CB385198-50B1-4CF4-883B-11F042DED6AA}.ReleaseUS|x64.Build.0 = Release|x64
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugAD|Win32.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugAD|Win32.Build.0 = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugAD|x64.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugAS|Win32.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugAS|Win32.Build.0 = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugAS|x64.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugUD|Win32.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugUD|Win32.Build.0 = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugUD|x64.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugUS|Win32.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugUS|Win32.Build.0 = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.DebugUS|x64.ActiveCfg = Debug|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.Release|Win32.Build.0 = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.Release|x64.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseAD|Win32.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseAD|Win32.Build.0 = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseAD|x64.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseAS|Win32.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseAS|Win32.Build.0 = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseAS|x64.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseUD|Win32.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseUD|Win32.Build.0 = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseUD|x64.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseUS|Win32.ActiveCfg = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseUS|Win32.Build.0 = Release|Win32
|
||||
{AA561A7B-26EA-49AF-90E8-C53C1FA2965D}.ReleaseUS|x64.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugAD|Win32.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugAD|Win32.Build.0 = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugAD|x64.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugAS|Win32.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugAS|Win32.Build.0 = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugAS|x64.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugUD|Win32.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugUD|Win32.Build.0 = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugUD|x64.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugUS|Win32.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugUS|Win32.Build.0 = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.DebugUS|x64.ActiveCfg = Debug|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.Release|Win32.Build.0 = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.Release|x64.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseAD|Win32.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseAD|Win32.Build.0 = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseAD|x64.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseAS|Win32.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseAS|Win32.Build.0 = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseAS|x64.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseUD|Win32.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseUD|Win32.Build.0 = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseUD|x64.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseUS|Win32.ActiveCfg = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseUS|Win32.Build.0 = Release|Win32
|
||||
{BD600973-C6FA-4CE3-8821-67F6418B7F9C}.ReleaseUS|x64.ActiveCfg = Release|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|Win32.ActiveCfg = DebugAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|x64.ActiveCfg = DebugAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|x64.Build.0 = DebugAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugAD|Win32.ActiveCfg = DebugAD|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugAD|Win32.Build.0 = DebugAD|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugAD|x64.ActiveCfg = DebugAD|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugAD|x64.Build.0 = DebugAD|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugAS|Win32.ActiveCfg = DebugAS|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugAS|Win32.Build.0 = DebugAS|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugAS|x64.ActiveCfg = DebugAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugAS|x64.Build.0 = DebugAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugUD|Win32.ActiveCfg = DebugUD|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugUD|Win32.Build.0 = DebugUD|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugUD|x64.ActiveCfg = DebugUD|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugUD|x64.Build.0 = DebugUD|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugUS|Win32.ActiveCfg = DebugUS|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugUS|Win32.Build.0 = DebugUS|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugUS|x64.ActiveCfg = DebugUS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.DebugUS|x64.Build.0 = DebugUS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|Win32.ActiveCfg = ReleaseAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|x64.ActiveCfg = ReleaseAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|x64.Build.0 = ReleaseAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseAD|Win32.ActiveCfg = ReleaseAD|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseAD|Win32.Build.0 = ReleaseAD|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseAD|x64.ActiveCfg = ReleaseAD|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseAD|x64.Build.0 = ReleaseAD|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseAS|Win32.ActiveCfg = ReleaseAS|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseAS|Win32.Build.0 = ReleaseAS|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseAS|x64.ActiveCfg = ReleaseAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseAS|x64.Build.0 = ReleaseAS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseUD|Win32.ActiveCfg = ReleaseUD|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseUD|Win32.Build.0 = ReleaseUD|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseUD|x64.ActiveCfg = ReleaseUD|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseUD|x64.Build.0 = ReleaseUD|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseUS|Win32.ActiveCfg = ReleaseUS|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseUS|Win32.Build.0 = ReleaseUS|Win32
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseUS|x64.ActiveCfg = ReleaseUS|x64
|
||||
{78424708-1F6E-4D4B-920C-FB6D26847055}.ReleaseUS|x64.Build.0 = ReleaseUS|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
21605
src/dep/src/StormLib/StormLib.vcproj
Normal file
21605
src/dep/src/StormLib/StormLib.vcproj
Normal file
File diff suppressed because it is too large
Load Diff
1996
src/dep/src/StormLib/StormLib.xcodeproj/project.pbxproj
Normal file
1996
src/dep/src/StormLib/StormLib.xcodeproj/project.pbxproj
Normal file
File diff suppressed because it is too large
Load Diff
2499
src/dep/src/StormLib/StormLib_dll.vcproj
Normal file
2499
src/dep/src/StormLib/StormLib_dll.vcproj
Normal file
File diff suppressed because it is too large
Load Diff
4
src/dep/src/StormLib/StormLib_test.kdev4
Normal file
4
src/dep/src/StormLib/StormLib_test.kdev4
Normal file
@ -0,0 +1,4 @@
|
||||
[Project]
|
||||
Name=StormLib_test
|
||||
Manager=KDevCMakeManager
|
||||
VersionControl=
|
||||
1952
src/dep/src/StormLib/StormLib_test.vcproj
Normal file
1952
src/dep/src/StormLib/StormLib_test.vcproj
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,270 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* StormPort.h Copyright (c) Marko Friedemann 2001 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Portability module for the StormLib library. Contains a wrapper symbols */
|
||||
/* to make the compilation under Linux work */
|
||||
/* */
|
||||
/* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de> */
|
||||
/* Created at: Mon Jan 29 18:26:01 CEST 2001 */
|
||||
/* Computer: whiplash.flachland-chemnitz.de */
|
||||
/* System: Linux 2.4.0 on i686 */
|
||||
/* */
|
||||
/* Author: Sam Wilkins */
|
||||
/* System: Mac OS X and port to big endian processor */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 29.01.01 1.00 Mar Created */
|
||||
/* 24.03.03 1.01 Lad Some cosmetic changes */
|
||||
/* 12.11.03 1.02 Dan Macintosh compatibility */
|
||||
/* 24.07.04 1.03 Sam Mac OS X compatibility */
|
||||
/* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */
|
||||
/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __STORMPORT_H__
|
||||
#define __STORMPORT_H__
|
||||
|
||||
// Defines for Windows
|
||||
#if !defined(PLATFORM_DEFINED) && (defined(WIN32) || defined(WIN64))
|
||||
|
||||
// In MSVC 8.0, there are some functions declared as deprecated.
|
||||
#if _MSC_VER >= 1400
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_NON_CONFORMING_SWPRINTFS
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#define PLATFORM_LITTLE_ENDIAN 1
|
||||
|
||||
#ifdef WIN64
|
||||
#define PLATFORM_64BIT
|
||||
#else
|
||||
#define PLATFORM_32BIT
|
||||
#endif
|
||||
|
||||
#define PLATFORM_DEFINED // The platform is known now
|
||||
|
||||
#endif
|
||||
|
||||
// Defines for Mac Carbon
|
||||
#if !defined(PLATFORM_DEFINED) && defined(__APPLE__) // Mac Carbon API
|
||||
|
||||
// Macintosh using Carbon
|
||||
#include <Carbon/Carbon.h> // Mac OS X
|
||||
|
||||
#define PKEXPORT
|
||||
#define __SYS_ZLIB
|
||||
#define __SYS_BZLIB
|
||||
#define LANG_NEUTRAL 0
|
||||
|
||||
#if defined(__BIG_ENDIAN__)
|
||||
#define PLATFORM_LITTLE_ENDIAN 0
|
||||
#else
|
||||
#define PLATFORM_LITTLE_ENDIAN 1 // Apple is now making Macs with Intel CPUs
|
||||
#endif
|
||||
|
||||
#ifdef __LP64__
|
||||
#define PLATFORM_64BIT
|
||||
#else
|
||||
#define PLATFORM_32BIT
|
||||
#endif
|
||||
|
||||
#define PLATFORM_DEFINED // The platform is known now
|
||||
|
||||
#endif
|
||||
|
||||
// Assumption: we are not on Windows nor Macintosh, so this must be linux *grin*
|
||||
// Ladik : Why the hell Linux does not use some OS-dependent #define ?
|
||||
#if !defined(PLATFORM_DEFINED)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define PLATFORM_LITTLE_ENDIAN 1
|
||||
#define PLATFORM_DEFINED
|
||||
#define LANG_NEUTRAL 0
|
||||
|
||||
#endif /* not __powerc */
|
||||
|
||||
|
||||
#if !defined(WIN32) && !defined(WIN64)
|
||||
|
||||
// Typedefs for ANSI C
|
||||
typedef unsigned char BYTE;
|
||||
typedef int16_t SHORT;
|
||||
typedef uint16_t WORD;
|
||||
typedef uint16_t USHORT;
|
||||
typedef int32_t LONG;
|
||||
typedef uint32_t DWORD;
|
||||
typedef intptr_t DWORD_PTR;
|
||||
typedef intptr_t LONG_PTR;
|
||||
typedef intptr_t INT_PTR;
|
||||
typedef int64_t LONGLONG;
|
||||
#ifndef __OBJC__
|
||||
#ifdef __cplusplus
|
||||
#define BOOL bool
|
||||
#else
|
||||
#define BOOL int
|
||||
#endif
|
||||
#endif
|
||||
typedef void * HANDLE;
|
||||
typedef void * LPOVERLAPPED; // Unsupported on Linux and Mac
|
||||
typedef char TCHAR;
|
||||
typedef uint32_t LCID;
|
||||
typedef unsigned int UINT;
|
||||
typedef LONG * PLONG;
|
||||
typedef DWORD * LPDWORD;
|
||||
typedef BYTE * LPBYTE;
|
||||
|
||||
typedef struct _FILETIME
|
||||
{
|
||||
DWORD dwLowDateTime;
|
||||
DWORD dwHighDateTime;
|
||||
}
|
||||
FILETIME, *PFILETIME;
|
||||
|
||||
typedef union _LARGE_INTEGER
|
||||
{
|
||||
#if PLATFORM_LITTLE_ENDIAN
|
||||
struct
|
||||
{
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
};
|
||||
#else
|
||||
struct
|
||||
{
|
||||
LONG HighPart;
|
||||
DWORD LowPart;
|
||||
};
|
||||
#endif
|
||||
LONGLONG QuadPart;
|
||||
}
|
||||
LARGE_INTEGER, *PLARGE_INTEGER;
|
||||
|
||||
// Some Windows-specific defines
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 1024
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE true
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE false
|
||||
#endif
|
||||
|
||||
#define VOID void
|
||||
#define WINAPI
|
||||
|
||||
#define FILE_BEGIN SEEK_SET
|
||||
#define FILE_CURRENT SEEK_CUR
|
||||
#define FILE_END SEEK_END
|
||||
|
||||
#define CREATE_NEW 1
|
||||
#define CREATE_ALWAYS 2
|
||||
#define OPEN_EXISTING 3
|
||||
#define OPEN_ALWAYS 4
|
||||
|
||||
#define FILE_SHARE_READ 0x00000001L
|
||||
#define GENERIC_WRITE 0x40000000
|
||||
#define GENERIC_READ 0x80000000
|
||||
|
||||
#define ERROR_SUCCESS 0
|
||||
#define ERROR_INVALID_FUNCTION 1
|
||||
#define ERROR_FILE_NOT_FOUND 2
|
||||
#define ERROR_ACCESS_DENIED 5
|
||||
#define ERROR_NOT_ENOUGH_MEMORY 8
|
||||
#define ERROR_BAD_FORMAT 11
|
||||
#define ERROR_NO_MORE_FILES 18
|
||||
#define ERROR_WRITE_FAULT 29
|
||||
#define ERROR_GEN_FAILURE 31
|
||||
#define ERROR_HANDLE_EOF 38
|
||||
#define ERROR_HANDLE_DISK_FULL 39
|
||||
#define ERROR_NOT_SUPPORTED 50
|
||||
#define ERROR_INVALID_PARAMETER 87
|
||||
#define ERROR_DISK_FULL 112
|
||||
#define ERROR_CALL_NOT_IMPLEMENTED 120
|
||||
#define ERROR_ALREADY_EXISTS 183
|
||||
#define ERROR_CAN_NOT_COMPLETE 1003
|
||||
#define ERROR_PARAMETER_QUOTA_EXCEEDED 1283
|
||||
#define ERROR_FILE_CORRUPT 1392
|
||||
#define ERROR_INSUFFICIENT_BUFFER 4999
|
||||
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE) -1)
|
||||
|
||||
#define _stricmp strcasecmp
|
||||
#define _strnicmp strncasecmp
|
||||
|
||||
extern int globalerr;
|
||||
|
||||
void SetLastError(int err);
|
||||
int GetLastError();
|
||||
char *ErrString(int err);
|
||||
|
||||
// Emulation of functions for file I/O available in Win32
|
||||
HANDLE CreateFile(const char * lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, void * lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
BOOL CloseHandle(HANDLE hObject);
|
||||
|
||||
DWORD GetFileSize(HANDLE hFile, DWORD * lpFileSizeHigh);
|
||||
DWORD SetFilePointer(HANDLE, LONG lDistanceToMove, LONG * lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
BOOL SetEndOfFile(HANDLE hFile);
|
||||
|
||||
BOOL ReadFile(HANDLE hFile, void * lpBuffer, DWORD nNumberOfBytesToRead, DWORD * lpNumberOfBytesRead, void * lpOverLapped);
|
||||
BOOL WriteFile(HANDLE hFile, const void * lpBuffer, DWORD nNumberOfBytesToWrite, DWORD * lpNumberOfBytesWritten, void * lpOverLapped);
|
||||
|
||||
BOOL IsBadReadPtr(const void * ptr, int size);
|
||||
DWORD GetFileAttributes(const char * szileName);
|
||||
|
||||
BOOL DeleteFile(const char * lpFileName);
|
||||
BOOL MoveFile(const char * lpFromFileName, const char * lpToFileName);
|
||||
void GetTempPath(DWORD szTempLength, char * szTemp);
|
||||
void GetTempFileName(const char * lpTempFolderPath, const char * lpFileName, DWORD something, char * szLFName);
|
||||
|
||||
#define strnicmp strncasecmp
|
||||
|
||||
#endif // !WIN32
|
||||
|
||||
#if PLATFORM_LITTLE_ENDIAN
|
||||
#define BSWAP_INT16_UNSIGNED(a) (a)
|
||||
#define BSWAP_INT16_SIGNED(a) (a)
|
||||
#define BSWAP_INT32_UNSIGNED(a) (a)
|
||||
#define BSWAP_INT32_SIGNED(a) (a)
|
||||
#define BSWAP_ARRAY16_UNSIGNED(a,b) {}
|
||||
#define BSWAP_ARRAY32_UNSIGNED(a,b) {}
|
||||
#define BSWAP_TMPQSHUNT(a) {}
|
||||
#define BSWAP_TMPQHEADER(a) {}
|
||||
#else
|
||||
extern uint16_t SwapUShort(uint16_t);
|
||||
extern uint32_t SwapULong(uint32_t);
|
||||
extern int16_t SwapShort(uint16_t);
|
||||
extern int32_t SwapLong(uint32_t);
|
||||
extern void ConvertUnsignedLongBuffer(uint32_t *buffer, uint32_t nbLongs);
|
||||
extern void ConvertUnsignedShortBuffer(uint16_t *buffer, uint32_t nbShorts);
|
||||
extern void ConvertTMPQShunt(void *shunt);
|
||||
extern void ConvertTMPQHeader(void *header);
|
||||
#define BSWAP_INT16_UNSIGNED(a) SwapUShort((a))
|
||||
#define BSWAP_INT32_UNSIGNED(a) SwapULong((a))
|
||||
#define BSWAP_INT16_SIGNED(a) SwapShort((a))
|
||||
#define BSWAP_INT32_SIGNED(a) SwapLong((a))
|
||||
#define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUnsignedShortBuffer((a),(b))
|
||||
#define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUnsignedLongBuffer((a),(b))
|
||||
#define BSWAP_TMPQSHUNT(a) ConvertTMPQShunt((a))
|
||||
#define BSWAP_TMPQHEADER(a) ConvertTMPQHeader((a))
|
||||
#endif
|
||||
|
||||
#endif // __STORMPORT_H__
|
||||
@ -1,196 +0,0 @@
|
||||
/********************************************************************
|
||||
*
|
||||
* Description: implementation for StormLib - linux port
|
||||
* intended to be used in GLdiablo
|
||||
*
|
||||
* ----> StormLib was originally developed for Windows by
|
||||
* Ladislav Zezula (www.zezula.net), and he did
|
||||
* a _great_ job! Thanks Ladislav!
|
||||
*
|
||||
* this is currently a quick and dirty hack to get it working
|
||||
* don't expect beauty and/or miracles :)
|
||||
*
|
||||
* these are function wraps to execute Windows API calls
|
||||
* as native Macintosh file calls (open/close/read/write/...)
|
||||
*
|
||||
* continue you work: added some wrapping functions for GNU/Linux by XPinguin
|
||||
*
|
||||
* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
|
||||
* Created at: Mon Jan 29 19:01:37 CEST 2001
|
||||
* Computer: whiplash.flachland-chemnitz.de
|
||||
* System: Linux 2.4.0 on i686
|
||||
*
|
||||
* Copyright (c) 2001 BMX-Chemnitz.DE All rights reserved.
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "StormPort.h"
|
||||
|
||||
int globalerr;
|
||||
|
||||
void SetLastError(int err)
|
||||
{
|
||||
globalerr = err;
|
||||
}
|
||||
|
||||
int GetLastError()
|
||||
{
|
||||
return(globalerr);
|
||||
}
|
||||
|
||||
char *ErrString(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case ERROR_INVALID_FUNCTION:
|
||||
return "function not implemented";
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
return "file not found";
|
||||
case ERROR_ACCESS_DENIED:
|
||||
return "access denied";
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
return "not enough memory";
|
||||
case ERROR_BAD_FORMAT:
|
||||
return "bad format";
|
||||
case ERROR_NO_MORE_FILES:
|
||||
return "no more files";
|
||||
case ERROR_HANDLE_EOF:
|
||||
return "access beyound EOF";
|
||||
case ERROR_HANDLE_DISK_FULL:
|
||||
return "no space left on device";
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
return "invalid parameter";
|
||||
case ERROR_DISK_FULL:
|
||||
return "no space left on device";
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
return "file exists";
|
||||
case ERROR_CAN_NOT_COMPLETE:
|
||||
return "operation cannot be completed";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE CreateFile(const char *sFileName, DWORD ulMode, DWORD ulSharing, void *pSecAttrib, DWORD ulCreation, DWORD ulFlags, HANDLE hFile)
|
||||
{
|
||||
switch (ulCreation)
|
||||
{
|
||||
case OPEN_EXISTING:
|
||||
return (HANDLE)open(sFileName, O_RDONLY | O_LARGEFILE);
|
||||
|
||||
case OPEN_ALWAYS:
|
||||
return (HANDLE)open(sFileName, O_RDWR | O_CREAT, 0);
|
||||
|
||||
case CREATE_ALWAYS:
|
||||
case CREATE_NEW:
|
||||
return (HANDLE)open(sFileName, O_RDWR | O_CREAT | O_TRUNC, 0);
|
||||
|
||||
default:
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CloseHandle(HANDLE hFile)
|
||||
{
|
||||
return (close((intptr_t)hFile) == 0);
|
||||
}
|
||||
|
||||
DWORD GetFileSize(HANDLE hFile, DWORD *ulOffSetHigh)
|
||||
{
|
||||
// Fix by Taiche : removed the hFile == NULL test because the CreateFile function above
|
||||
// can return a HANDLE equal to 0 WHICH IS A LEGAL VALUE and does not mean the handle is NULL.
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
struct stat64 fileinfo;
|
||||
fstat64((intptr_t)hFile, &fileinfo);
|
||||
|
||||
// Fix by Ladik: If "ulOffSetHigh" is not NULL, it needs to be set
|
||||
// to higher 32 bits of a file size.
|
||||
// TODO: Could some Linux programmer verify this ?
|
||||
if(ulOffSetHigh != NULL)
|
||||
*ulOffSetHigh = (fileinfo.st_size >> 32);
|
||||
|
||||
return (DWORD)fileinfo.st_size;
|
||||
}
|
||||
|
||||
DWORD SetFilePointer(HANDLE hFile, LONG lOffSetLow, LONG *pOffSetHigh, DWORD ulMethod)
|
||||
{
|
||||
off64_t nFileOffset = (DWORD)lOffSetLow;
|
||||
|
||||
if(pOffSetHigh != NULL)
|
||||
nFileOffset |= (*(off64_t *)pOffSetHigh) << 32;
|
||||
|
||||
return lseek64((intptr_t)hFile, nFileOffset, ulMethod);
|
||||
}
|
||||
|
||||
BOOL SetEndOfFile(HANDLE hFile)
|
||||
{
|
||||
return (ftruncate((intptr_t)hFile, lseek((intptr_t)hFile, 0, SEEK_CUR)) == 0);
|
||||
}
|
||||
|
||||
BOOL ReadFile(HANDLE hFile, void *pBuffer, DWORD ulLen, DWORD *ulRead, void *pOverLapped)
|
||||
{
|
||||
ssize_t count;
|
||||
if ((count = read((intptr_t)hFile, pBuffer, ulLen)) == -1) {
|
||||
*ulRead = 0;
|
||||
return false;
|
||||
}
|
||||
*ulRead = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL WriteFile(HANDLE hFile, const void *pBuffer, DWORD ulLen, DWORD *ulWritten, void *pOverLapped)
|
||||
{
|
||||
ssize_t count;
|
||||
if ((count = write((intptr_t)hFile, pBuffer, ulLen)) == -1) {
|
||||
*ulWritten = 0;
|
||||
return false;
|
||||
}
|
||||
*ulWritten = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if a memory block is accessible for reading
|
||||
BOOL IsBadReadPtr(const void * ptr, int size)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Returns attributes of a file
|
||||
DWORD GetFileAttributes(const char * szFileName)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GetTempPath(DWORD szTempLength, char * szTemp)
|
||||
{
|
||||
strncpy(szTemp, P_tmpdir, szTempLength);
|
||||
}
|
||||
|
||||
void GetTempFileName(const char * lpTempFolderPath, const char * lpFileName, DWORD something, char * szLFName)
|
||||
{
|
||||
//strcpy(szLFName, tempnam(lpTempFolderPath, lpFileName));
|
||||
char tempName[15] = "/tmp/sl.XXXXXX";
|
||||
int sfp = mkstemp(tempName);
|
||||
|
||||
if(sfp != -1)
|
||||
{
|
||||
close(sfp);
|
||||
strcpy(szLFName, tempName);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL DeleteFile(const char *lpFileName)
|
||||
{
|
||||
return (BOOL)remove(lpFileName);
|
||||
}
|
||||
|
||||
BOOL MoveFile(const char *lpExistingFileName, const char *lpNewFileName)
|
||||
{
|
||||
return rename(lpExistingFileName, lpNewFileName);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,710 +0,0 @@
|
||||
/********************************************************************
|
||||
*
|
||||
* Description: implementation for StormLib - Macintosh port
|
||||
*
|
||||
* these are function wraps to execute Windows API calls
|
||||
* as native Macintosh file calls (open/close/read/write/...)
|
||||
* requires Mac OS X
|
||||
*
|
||||
* Derived from Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
|
||||
* StormPort.cpp for Linux
|
||||
*
|
||||
* Author: Daniel Chiaramello <daniel@chiaramello.net>
|
||||
*
|
||||
* Carbonized by: Sam Wilkins <swilkins1337@gmail.com>
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
#if (!defined(_WIN32) && !defined(_WIN64))
|
||||
#include "StormPort.h"
|
||||
#include "StormLib.h"
|
||||
|
||||
// FUNCTIONS EXTRACTED FROM MOREFILE PACKAGE!!!
|
||||
// FEEL FREE TO REMOVE THEM AND TO ADD THE ORIGINAL ONES!
|
||||
|
||||
/*****************************************************************************
|
||||
* BEGIN OF MOREFILES COPY-PASTE
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef __USEPRAGMAINTERNAL
|
||||
#ifdef __MWERKS__
|
||||
#pragma internal on
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static OSErr FSOpenDFCompat(FSRef *ref, char permission, short *refNum)
|
||||
{
|
||||
HFSUniStr255 forkName;
|
||||
OSErr theErr;
|
||||
Boolean isFolder, wasChanged;
|
||||
|
||||
theErr = FSResolveAliasFile(ref, TRUE, &isFolder, &wasChanged);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
return theErr;
|
||||
}
|
||||
|
||||
FSGetDataForkName(&forkName);
|
||||
#ifdef PLATFORM_64BIT
|
||||
theErr = FSOpenFork(ref, forkName.length, forkName.unicode, permission, (FSIORefNum *)refNum);
|
||||
#else
|
||||
theErr = FSOpenFork(ref, forkName.length, forkName.unicode, permission, refNum);
|
||||
#endif
|
||||
return theErr;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* END OF MOREFILES COPY-PASTE
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma mark -
|
||||
|
||||
int globalerr;
|
||||
|
||||
/********************************************************************
|
||||
* SwapLong
|
||||
********************************************************************/
|
||||
|
||||
uint32_t SwapULong(uint32_t data)
|
||||
{
|
||||
return CFSwapInt32(data);
|
||||
}
|
||||
|
||||
int32_t SwapLong(uint32_t data)
|
||||
{
|
||||
return (int32_t)CFSwapInt32(data);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* SwapShort
|
||||
********************************************************************/
|
||||
uint16_t SwapUShort(uint16_t data)
|
||||
{
|
||||
return CFSwapInt16(data);
|
||||
}
|
||||
|
||||
int16_t SwapShort(uint16_t data)
|
||||
{
|
||||
return (int16_t)CFSwapInt16(data);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* ConvertUnsignedLongBuffer
|
||||
********************************************************************/
|
||||
void ConvertUnsignedLongBuffer(uint32_t *buffer, uint32_t nbLongs)
|
||||
{
|
||||
while (nbLongs-- > 0)
|
||||
{
|
||||
*buffer = SwapLong(*buffer);
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* ConvertUnsignedShortBuffer
|
||||
********************************************************************/
|
||||
void ConvertUnsignedShortBuffer(uint16_t *buffer, uint32_t nbShorts)
|
||||
{
|
||||
while (nbShorts-- > 0)
|
||||
{
|
||||
*buffer = SwapShort(*buffer);
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* ConvertTMPQShunt
|
||||
********************************************************************/
|
||||
void ConvertTMPQShunt(void *shunt)
|
||||
{
|
||||
TMPQShunt * theShunt = (TMPQShunt *)shunt;
|
||||
|
||||
theShunt->dwID = SwapULong(theShunt->dwID);
|
||||
theShunt->dwUnknown = SwapULong(theShunt->dwUnknown);
|
||||
theShunt->dwHeaderPos = SwapULong(theShunt->dwHeaderPos);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* ConvertTMPQHeader
|
||||
********************************************************************/
|
||||
void ConvertTMPQHeader(void *header)
|
||||
{
|
||||
TMPQHeader2 * theHeader = (TMPQHeader2 *)header;
|
||||
|
||||
theHeader->dwID = SwapULong(theHeader->dwID);
|
||||
theHeader->dwHeaderSize = SwapULong(theHeader->dwHeaderSize);
|
||||
theHeader->dwArchiveSize = SwapULong(theHeader->dwArchiveSize);
|
||||
theHeader->wFormatVersion = SwapUShort(theHeader->wFormatVersion);
|
||||
theHeader->wBlockSize = SwapUShort(theHeader->wBlockSize);
|
||||
theHeader->dwHashTablePos = SwapULong(theHeader->dwHashTablePos);
|
||||
theHeader->dwBlockTablePos = SwapULong(theHeader->dwBlockTablePos);
|
||||
theHeader->dwHashTableSize = SwapULong(theHeader->dwHashTableSize);
|
||||
theHeader->dwBlockTableSize = SwapULong(theHeader->dwBlockTableSize);
|
||||
|
||||
if(theHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
|
||||
{
|
||||
DWORD dwTemp = theHeader->ExtBlockTablePos.LowPart;
|
||||
theHeader->ExtBlockTablePos.LowPart = theHeader->ExtBlockTablePos.HighPart;
|
||||
theHeader->ExtBlockTablePos.HighPart = dwTemp;
|
||||
theHeader->ExtBlockTablePos.LowPart = SwapULong(theHeader->ExtBlockTablePos.LowPart);
|
||||
theHeader->ExtBlockTablePos.HighPart = SwapULong(theHeader->ExtBlockTablePos.HighPart);
|
||||
theHeader->wHashTablePosHigh = SwapUShort(theHeader->wHashTablePosHigh);
|
||||
theHeader->wBlockTablePosHigh = SwapUShort(theHeader->wBlockTablePosHigh);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/********************************************************************
|
||||
* SetLastError
|
||||
********************************************************************/
|
||||
void SetLastError(int err)
|
||||
{
|
||||
globalerr = err;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* GetLastError
|
||||
********************************************************************/
|
||||
int GetLastError()
|
||||
{
|
||||
return globalerr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* ErrString
|
||||
********************************************************************/
|
||||
char *ErrString(int err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case ERROR_INVALID_FUNCTION:
|
||||
return "function not implemented";
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
return "file not found";
|
||||
case ERROR_ACCESS_DENIED:
|
||||
return "access denied";
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
return "not enough memory";
|
||||
case ERROR_BAD_FORMAT:
|
||||
return "bad format";
|
||||
case ERROR_NO_MORE_FILES:
|
||||
return "no more files";
|
||||
case ERROR_HANDLE_EOF:
|
||||
return "access beyond EOF";
|
||||
case ERROR_HANDLE_DISK_FULL:
|
||||
return "no space left on device";
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
return "invalid parameter";
|
||||
case ERROR_DISK_FULL:
|
||||
return "no space left on device";
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
return "file exists";
|
||||
case ERROR_CAN_NOT_COMPLETE:
|
||||
return "operation cannot be completed";
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
return "insufficient buffer";
|
||||
case ERROR_WRITE_FAULT:
|
||||
return "unable to write to device";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/********************************************************************
|
||||
* GetTempPath - returns a '/' or ':'-terminated path
|
||||
* szTempLength: length for path
|
||||
* szTemp: file path
|
||||
********************************************************************/
|
||||
void GetTempPath(DWORD szTempLength, char * szTemp)
|
||||
{
|
||||
FSRef theFSRef;
|
||||
OSErr theErr = FSFindFolder(kOnAppropriateDisk, kTemporaryFolderType, kCreateFolder, &theFSRef);
|
||||
if (theErr == noErr)
|
||||
{
|
||||
theErr = FSRefMakePath(&theFSRef, (UInt8 *)szTemp, szTempLength);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
szTemp[0] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
szTemp[0] = '\0';
|
||||
}
|
||||
strcat(szTemp, "/");
|
||||
|
||||
SetLastError(theErr);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* GetTempFileName
|
||||
* lpTempFolderPath: the temporary folder path, terminated by "/"
|
||||
* lpFileName: a file name base
|
||||
* something: unknown
|
||||
* szLFName: the final path, built from the path, the file name and a random pattern
|
||||
********************************************************************/
|
||||
void GetTempFileName(const char * lpTempFolderPath, const char * lpFileName, DWORD something, char * szLFName)
|
||||
{
|
||||
#pragma unused (something)
|
||||
char tmp[2] = "A";
|
||||
|
||||
while (true)
|
||||
{
|
||||
HANDLE fHandle;
|
||||
|
||||
strcpy(szLFName, lpTempFolderPath);
|
||||
strcat(szLFName, lpFileName);
|
||||
strcat(szLFName, tmp);
|
||||
|
||||
if ((fHandle = CreateFile(szLFName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// OK we found it!
|
||||
break;
|
||||
}
|
||||
CloseHandle(fHandle);
|
||||
tmp[0]++;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* DeleteFile
|
||||
* lpFileName: file path
|
||||
********************************************************************/
|
||||
BOOL DeleteFile(const char * lpFileName)
|
||||
{
|
||||
OSErr theErr;
|
||||
FSRef theFileRef;
|
||||
|
||||
theErr = FSPathMakeRef((const UInt8 *)lpFileName, &theFileRef, NULL);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
theErr = FSDeleteObject(&theFileRef);
|
||||
|
||||
SetLastError(theErr);
|
||||
|
||||
return theErr == noErr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* MoveFile
|
||||
* lpFromFileName: old file path
|
||||
* lpToFileName: new file path
|
||||
********************************************************************/
|
||||
BOOL MoveFile(const char * lpFromFileName, const char * lpToFileName)
|
||||
{
|
||||
OSErr theErr;
|
||||
FSRef fromFileRef;
|
||||
FSRef toFileRef;
|
||||
FSRef parentFolderRef;
|
||||
|
||||
// Get the path to the old file
|
||||
theErr = FSPathMakeRef((const UInt8 *)lpFromFileName, &fromFileRef, NULL);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the path to the new folder for the file
|
||||
char folderName[strlen(lpToFileName)];
|
||||
CFStringRef folderPathCFString = CFStringCreateWithCString(NULL, lpToFileName, kCFStringEncodingUTF8);
|
||||
CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, folderPathCFString, kCFURLPOSIXPathStyle, FALSE);
|
||||
CFURLRef folderURL = CFURLCreateCopyDeletingLastPathComponent(NULL, fileURL);
|
||||
CFURLGetFileSystemRepresentation(folderURL, TRUE, (UInt8 *)folderName, strlen(lpToFileName));
|
||||
theErr = FSPathMakeRef((UInt8 *)folderName, &parentFolderRef, NULL);
|
||||
CFRelease(fileURL);
|
||||
CFRelease(folderURL);
|
||||
CFRelease(folderPathCFString);
|
||||
|
||||
// Move the old file
|
||||
theErr = FSMoveObject(&fromFileRef, &parentFolderRef, &toFileRef);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get a CFString for the new file name
|
||||
CFStringRef newFileNameCFString = CFStringCreateWithCString(NULL, lpToFileName, kCFStringEncodingUTF8);
|
||||
fileURL = CFURLCreateWithFileSystemPath(NULL, newFileNameCFString, kCFURLPOSIXPathStyle, FALSE);
|
||||
CFRelease(newFileNameCFString);
|
||||
newFileNameCFString = CFURLCopyLastPathComponent(fileURL);
|
||||
CFRelease(fileURL);
|
||||
|
||||
// Convert CFString to Unicode and rename the file
|
||||
UniChar unicodeFileName[256];
|
||||
CFStringGetCharacters(newFileNameCFString, CFRangeMake(0, CFStringGetLength(newFileNameCFString)),
|
||||
unicodeFileName);
|
||||
theErr = FSRenameUnicode(&toFileRef, CFStringGetLength(newFileNameCFString), unicodeFileName,
|
||||
kTextEncodingUnknown, NULL);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
CFRelease(newFileNameCFString);
|
||||
return false;
|
||||
}
|
||||
|
||||
CFRelease(newFileNameCFString);
|
||||
|
||||
SetLastError(theErr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* CreateFile
|
||||
* ulMode: GENERIC_READ | GENERIC_WRITE
|
||||
* ulSharing: FILE_SHARE_READ
|
||||
* pSecAttrib: NULL
|
||||
* ulCreation: OPEN_EXISTING, OPEN_ALWAYS, CREATE_NEW
|
||||
* ulFlags: 0
|
||||
* hFile: NULL
|
||||
********************************************************************/
|
||||
HANDLE CreateFile( const char *sFileName, /* file name */
|
||||
DWORD ulMode, /* access mode */
|
||||
DWORD ulSharing, /* share mode */
|
||||
void *pSecAttrib, /* SD */
|
||||
DWORD ulCreation, /* how to create */
|
||||
DWORD ulFlags, /* file attributes */
|
||||
HANDLE hFile ) /* handle to template file */
|
||||
{
|
||||
#pragma unused (ulSharing, pSecAttrib, ulFlags, hFile)
|
||||
|
||||
OSErr theErr;
|
||||
FSRef theFileRef;
|
||||
FSRef theParentRef;
|
||||
short fileRef;
|
||||
char permission;
|
||||
|
||||
theErr = FSPathMakeRef((const UInt8 *)sFileName, &theFileRef, NULL);
|
||||
if (theErr == fnfErr)
|
||||
{ // Create the FSRef for the parent directory.
|
||||
memset(&theFileRef, 0, sizeof(FSRef));
|
||||
UInt8 folderName[MAX_PATH];
|
||||
CFStringRef folderPathCFString = CFStringCreateWithCString(NULL, sFileName, kCFStringEncodingUTF8);
|
||||
CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, folderPathCFString, kCFURLPOSIXPathStyle, FALSE);
|
||||
CFURLRef folderURL = CFURLCreateCopyDeletingLastPathComponent(NULL, fileURL);
|
||||
CFURLGetFileSystemRepresentation(folderURL, TRUE, folderName, MAX_PATH);
|
||||
theErr = FSPathMakeRef(folderName, &theParentRef, NULL);
|
||||
CFRelease(fileURL);
|
||||
CFRelease(folderURL);
|
||||
CFRelease(folderPathCFString);
|
||||
}
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
if (ulCreation == OPEN_EXISTING || theErr != fnfErr)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (ulCreation != OPEN_EXISTING)
|
||||
{ /* We create the file */
|
||||
UniChar unicodeFileName[256];
|
||||
CFStringRef filePathCFString = CFStringCreateWithCString(NULL, sFileName, kCFStringEncodingUTF8);
|
||||
CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, filePathCFString, kCFURLPOSIXPathStyle, FALSE);
|
||||
CFStringRef fileNameCFString = CFURLCopyLastPathComponent(fileURL);
|
||||
CFStringGetCharacters(fileNameCFString, CFRangeMake(0, CFStringGetLength(fileNameCFString)),
|
||||
unicodeFileName);
|
||||
theErr = FSCreateFileUnicode(&theParentRef, CFStringGetLength(fileNameCFString), unicodeFileName,
|
||||
kFSCatInfoNone, NULL, &theFileRef, NULL);
|
||||
CFRelease(fileNameCFString);
|
||||
CFRelease(filePathCFString);
|
||||
CFRelease(fileURL);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ulMode == GENERIC_READ)
|
||||
{
|
||||
permission = fsRdPerm;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ulMode == GENERIC_WRITE)
|
||||
{
|
||||
permission = fsWrPerm;
|
||||
}
|
||||
else
|
||||
{
|
||||
permission = fsRdWrPerm;
|
||||
}
|
||||
}
|
||||
theErr = FSOpenDFCompat(&theFileRef, permission, &fileRef);
|
||||
|
||||
SetLastError(theErr);
|
||||
|
||||
if (theErr == noErr)
|
||||
{
|
||||
return (HANDLE)(int)fileRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* CloseHandle
|
||||
********************************************************************/
|
||||
BOOL CloseHandle( HANDLE hFile ) /* handle to object */
|
||||
{
|
||||
OSErr theErr;
|
||||
|
||||
if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
theErr = FSCloseFork((short)(long)hFile);
|
||||
|
||||
SetLastError(theErr);
|
||||
|
||||
return theErr == noErr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* GetFileSize
|
||||
********************************************************************/
|
||||
DWORD GetFileSize( HANDLE hFile, /* handle to file */
|
||||
DWORD *ulOffSetHigh ) /* high-order word of file size */
|
||||
{
|
||||
SInt64 fileLength;
|
||||
OSErr theErr;
|
||||
|
||||
if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return -1u;
|
||||
}
|
||||
|
||||
theErr = FSGetForkSize((short)(long)hFile, &fileLength);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return -1u;
|
||||
}
|
||||
|
||||
if (ulOffSetHigh != NULL)
|
||||
{
|
||||
*ulOffSetHigh = fileLength >> 32;
|
||||
}
|
||||
|
||||
SetLastError(theErr);
|
||||
|
||||
return fileLength;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* SetFilePointer
|
||||
* pOffSetHigh: NULL
|
||||
* ulMethod: FILE_BEGIN, FILE_CURRENT
|
||||
********************************************************************/
|
||||
DWORD SetFilePointer( HANDLE hFile, /* handle to file */
|
||||
LONG lOffSetLow, /* bytes to move pointer */
|
||||
LONG *pOffSetHigh, /* bytes to move pointer */
|
||||
DWORD ulMethod ) /* starting point */
|
||||
{
|
||||
OSErr theErr;
|
||||
|
||||
if (ulMethod == FILE_CURRENT)
|
||||
{
|
||||
SInt64 bytesToMove;
|
||||
|
||||
if (pOffSetHigh != NULL)
|
||||
{
|
||||
bytesToMove = ((SInt64)*pOffSetHigh << 32) + lOffSetLow;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesToMove = lOffSetLow;
|
||||
}
|
||||
|
||||
SInt64 newPos;
|
||||
|
||||
theErr = FSSetForkPosition((short)(long)hFile, fsFromMark, bytesToMove);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return -1u;
|
||||
}
|
||||
|
||||
theErr = FSGetForkPosition((short)(long)hFile, &newPos);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return -1u;
|
||||
}
|
||||
|
||||
if (pOffSetHigh != NULL)
|
||||
{
|
||||
*pOffSetHigh = newPos >> 32;
|
||||
}
|
||||
|
||||
SetLastError(theErr);
|
||||
return newPos;
|
||||
}
|
||||
else if (ulMethod == FILE_BEGIN)
|
||||
{
|
||||
SInt64 bytesToMove;
|
||||
|
||||
if (pOffSetHigh != NULL)
|
||||
{
|
||||
bytesToMove = ((SInt64)*pOffSetHigh << 32) + lOffSetLow;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesToMove = lOffSetLow;
|
||||
}
|
||||
|
||||
theErr = FSSetForkPosition((short)(long)hFile, fsFromStart, bytesToMove);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return -1u;
|
||||
}
|
||||
|
||||
SetLastError(theErr);
|
||||
return lOffSetLow;
|
||||
}
|
||||
else
|
||||
{
|
||||
SInt64 bytesToMove;
|
||||
|
||||
if (pOffSetHigh != NULL)
|
||||
{
|
||||
bytesToMove = ((SInt64)*pOffSetHigh << 32) + lOffSetLow;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesToMove = lOffSetLow;
|
||||
}
|
||||
|
||||
SInt64 newPos;
|
||||
|
||||
theErr = FSSetForkPosition((short)(long)hFile, fsFromLEOF, bytesToMove);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return -1u;
|
||||
}
|
||||
|
||||
theErr = FSGetForkPosition((short)(long)hFile, &newPos);
|
||||
if (theErr != noErr)
|
||||
{
|
||||
SetLastError(theErr);
|
||||
return -1u;
|
||||
}
|
||||
|
||||
if (pOffSetHigh != NULL)
|
||||
{
|
||||
*pOffSetHigh = newPos >> 32;
|
||||
}
|
||||
|
||||
SetLastError(theErr);
|
||||
return newPos;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* SetEndOfFile
|
||||
********************************************************************/
|
||||
BOOL SetEndOfFile( HANDLE hFile ) /* handle to file */
|
||||
{
|
||||
OSErr theErr;
|
||||
|
||||
theErr = FSSetForkSize((short)(long)hFile, fsAtMark, 0);
|
||||
|
||||
SetLastError(theErr);
|
||||
|
||||
return theErr == noErr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* ReadFile
|
||||
* pOverLapped: NULL
|
||||
********************************************************************/
|
||||
BOOL ReadFile( HANDLE hFile, /* handle to file */
|
||||
void *pBuffer, /* data buffer */
|
||||
DWORD ulLen, /* number of bytes to read */
|
||||
DWORD *ulRead, /* number of bytes read */
|
||||
void *pOverLapped ) /* overlapped buffer */
|
||||
{
|
||||
#pragma unused (pOverLapped)
|
||||
|
||||
ByteCount nbCharsRead;
|
||||
OSErr theErr;
|
||||
|
||||
nbCharsRead = ulLen;
|
||||
theErr = FSReadFork((short)(long)hFile, fsAtMark, 0, nbCharsRead, pBuffer, &nbCharsRead);
|
||||
*ulRead = nbCharsRead;
|
||||
|
||||
SetLastError(theErr);
|
||||
|
||||
return theErr == noErr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* WriteFile
|
||||
* pOverLapped: NULL
|
||||
********************************************************************/
|
||||
BOOL WriteFile( HANDLE hFile, /* handle to file */
|
||||
const void *pBuffer, /* data buffer */
|
||||
DWORD ulLen, /* number of bytes to write */
|
||||
DWORD *ulWritten, /* number of bytes written */
|
||||
void *pOverLapped ) /* overlapped buffer */
|
||||
{
|
||||
#pragma unused (pOverLapped)
|
||||
|
||||
ByteCount nbCharsToWrite;
|
||||
OSErr theErr;
|
||||
|
||||
nbCharsToWrite = ulLen;
|
||||
theErr = FSWriteFork((short)(long)hFile, fsAtMark, 0, nbCharsToWrite, pBuffer, &nbCharsToWrite);
|
||||
*ulWritten = nbCharsToWrite;
|
||||
|
||||
SetLastError(theErr);
|
||||
|
||||
return theErr == noErr;
|
||||
}
|
||||
|
||||
// Check if a memory block is accessible for reading. I doubt it's
|
||||
// possible to check on Mac, so sorry, we'll just have to crash
|
||||
BOOL IsBadReadPtr(const void * ptr, int size)
|
||||
{
|
||||
#pragma unused (ptr, size)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Returns attributes of a file. Actually, it doesn't, it just checks if
|
||||
// the file exists, since that's all StormLib uses it for
|
||||
DWORD GetFileAttributes(const char * szFileName)
|
||||
{
|
||||
FSRef theRef;
|
||||
OSErr theErr;
|
||||
|
||||
theErr = FSPathMakeRef((const UInt8 *)szFileName, &theRef, NULL);
|
||||
|
||||
if (theErr != noErr)
|
||||
{
|
||||
return -1u;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
18
src/dep/src/StormLib/Storm_dll.bat
Normal file
18
src/dep/src/StormLib/Storm_dll.bat
Normal file
@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
rem Post-build batch for StormDll project
|
||||
rem Called as StormDll.bat $(PlatformName) $(ConfigurationName)
|
||||
rem Example: StormDll.bat x64 Debug
|
||||
|
||||
if x%1 == xWin32 goto PlatformWin32
|
||||
if x%1 == xx64 goto PlatformWin64
|
||||
goto exit
|
||||
|
||||
:PlatformWin32
|
||||
copy .\bin\Storm_dll\%1\%2\*.lib .
|
||||
goto exit
|
||||
|
||||
:PlatformWin64
|
||||
copy .\bin\Storm_dll\%1\%2\*.lib .
|
||||
goto exit
|
||||
|
||||
:exit
|
||||
206
src/dep/src/StormLib/Storm_dll.vcproj
Normal file
206
src/dep/src/StormLib/Storm_dll.vcproj
Normal file
@ -0,0 +1,206 @@
|
||||
<?xml version="1.0" encoding="windows-1250"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="Storm_dll"
|
||||
ProjectGUID="{BD600973-C6FA-4CE3-8821-67F6418B7F9C}"
|
||||
RootNamespace="Storm_dll"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\bin\Storm_dll\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory=".\bin\Storm_dll\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;Storm_dll_EXPORTS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\storm.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateManifest="false"
|
||||
ModuleDefinitionFile=".\Storm_dll\Storm_dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
BaseAddress="0x15000000"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="Storm_dll.bat $(PlatformName) $(ConfigurationName)"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\bin\Storm_dll\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory=".\bin\Storm_dll\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;Storm_dll_EXPORTS"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\storm.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateManifest="false"
|
||||
ModuleDefinitionFile=".\Storm_dll\storm_dll.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
BaseAddress="0x15000000"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="Storm_dll.bat $(PlatformName) $(ConfigurationName)"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Storm_dll\storm_dll.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\storm_dll\storm_dll.def"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Storm_dll\storm_dll.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,514 +0,0 @@
|
||||
/*-----------------------------------------------------------*/
|
||||
/*--- Block recoverer program for bzip2 ---*/
|
||||
/*--- bzip2recover.c ---*/
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
/* This program is a complete hack and should be rewritten properly.
|
||||
It isn't very complicated. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* This program records bit locations in the file to be recovered.
|
||||
That means that if 64-bit ints are not supported, we will not
|
||||
be able to recover .bz2 files over 512MB (2^32 bits) long.
|
||||
On GNU supported platforms, we take advantage of the 64-bit
|
||||
int support to circumvent this problem. Ditto MSVC.
|
||||
|
||||
This change occurred in version 1.0.2; all prior versions have
|
||||
the 512MB limitation.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
typedef unsigned long long int MaybeUInt64;
|
||||
# define MaybeUInt64_FMT "%Lu"
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 MaybeUInt64;
|
||||
# define MaybeUInt64_FMT "%I64u"
|
||||
#else
|
||||
typedef unsigned int MaybeUInt64;
|
||||
# define MaybeUInt64_FMT "%u"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef unsigned int UInt32;
|
||||
typedef int Int32;
|
||||
typedef unsigned char UChar;
|
||||
typedef char Char;
|
||||
typedef unsigned char Bool;
|
||||
#define True ((Bool)1)
|
||||
#define False ((Bool)0)
|
||||
|
||||
|
||||
#define BZ_MAX_FILENAME 2000
|
||||
|
||||
Char inFileName[BZ_MAX_FILENAME];
|
||||
Char outFileName[BZ_MAX_FILENAME];
|
||||
Char progName[BZ_MAX_FILENAME];
|
||||
|
||||
MaybeUInt64 bytesOut = 0;
|
||||
MaybeUInt64 bytesIn = 0;
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- Header bytes ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
#define BZ_HDR_B 0x42 /* 'B' */
|
||||
#define BZ_HDR_Z 0x5a /* 'Z' */
|
||||
#define BZ_HDR_h 0x68 /* 'h' */
|
||||
#define BZ_HDR_0 0x30 /* '0' */
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- I/O errors ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static void readError ( void )
|
||||
{
|
||||
fprintf ( stderr,
|
||||
"%s: I/O error reading `%s', possible reason follows.\n",
|
||||
progName, inFileName );
|
||||
perror ( progName );
|
||||
fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
|
||||
progName );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static void writeError ( void )
|
||||
{
|
||||
fprintf ( stderr,
|
||||
"%s: I/O error reading `%s', possible reason follows.\n",
|
||||
progName, inFileName );
|
||||
perror ( progName );
|
||||
fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
|
||||
progName );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static void mallocFail ( Int32 n )
|
||||
{
|
||||
fprintf ( stderr,
|
||||
"%s: malloc failed on request for %d bytes.\n",
|
||||
progName, n );
|
||||
fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n",
|
||||
progName );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static void tooManyBlocks ( Int32 max_handled_blocks )
|
||||
{
|
||||
fprintf ( stderr,
|
||||
"%s: `%s' appears to contain more than %d blocks\n",
|
||||
progName, inFileName, max_handled_blocks );
|
||||
fprintf ( stderr,
|
||||
"%s: and cannot be handled. To fix, increase\n",
|
||||
progName );
|
||||
fprintf ( stderr,
|
||||
"%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n",
|
||||
progName );
|
||||
exit ( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- Bit stream I/O ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
typedef
|
||||
struct {
|
||||
FILE* handle;
|
||||
Int32 buffer;
|
||||
Int32 buffLive;
|
||||
Char mode;
|
||||
}
|
||||
BitStream;
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static BitStream* bsOpenReadStream ( FILE* stream )
|
||||
{
|
||||
BitStream *bs = malloc ( sizeof(BitStream) );
|
||||
if (bs == NULL) mallocFail ( sizeof(BitStream) );
|
||||
bs->handle = stream;
|
||||
bs->buffer = 0;
|
||||
bs->buffLive = 0;
|
||||
bs->mode = 'r';
|
||||
return bs;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static BitStream* bsOpenWriteStream ( FILE* stream )
|
||||
{
|
||||
BitStream *bs = malloc ( sizeof(BitStream) );
|
||||
if (bs == NULL) mallocFail ( sizeof(BitStream) );
|
||||
bs->handle = stream;
|
||||
bs->buffer = 0;
|
||||
bs->buffLive = 0;
|
||||
bs->mode = 'w';
|
||||
return bs;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static void bsPutBit ( BitStream* bs, Int32 bit )
|
||||
{
|
||||
if (bs->buffLive == 8) {
|
||||
Int32 retVal = putc ( (UChar) bs->buffer, bs->handle );
|
||||
if (retVal == EOF) writeError();
|
||||
bytesOut++;
|
||||
bs->buffLive = 1;
|
||||
bs->buffer = bit & 0x1;
|
||||
} else {
|
||||
bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) );
|
||||
bs->buffLive++;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
/*--
|
||||
Returns 0 or 1, or 2 to indicate EOF.
|
||||
--*/
|
||||
static Int32 bsGetBit ( BitStream* bs )
|
||||
{
|
||||
if (bs->buffLive > 0) {
|
||||
bs->buffLive --;
|
||||
return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 );
|
||||
} else {
|
||||
Int32 retVal = getc ( bs->handle );
|
||||
if ( retVal == EOF ) {
|
||||
if (errno != 0) readError();
|
||||
return 2;
|
||||
}
|
||||
bs->buffLive = 7;
|
||||
bs->buffer = retVal;
|
||||
return ( ((bs->buffer) >> 7) & 0x1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static void bsClose ( BitStream* bs )
|
||||
{
|
||||
Int32 retVal;
|
||||
|
||||
if ( bs->mode == 'w' ) {
|
||||
while ( bs->buffLive < 8 ) {
|
||||
bs->buffLive++;
|
||||
bs->buffer <<= 1;
|
||||
};
|
||||
retVal = putc ( (UChar) (bs->buffer), bs->handle );
|
||||
if (retVal == EOF) writeError();
|
||||
bytesOut++;
|
||||
retVal = fflush ( bs->handle );
|
||||
if (retVal == EOF) writeError();
|
||||
}
|
||||
retVal = fclose ( bs->handle );
|
||||
if (retVal == EOF) {
|
||||
if (bs->mode == 'w') writeError(); else readError();
|
||||
}
|
||||
free ( bs );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static void bsPutUChar ( BitStream* bs, UChar c )
|
||||
{
|
||||
Int32 i;
|
||||
for (i = 7; i >= 0; i--)
|
||||
bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static void bsPutUInt32 ( BitStream* bs, UInt32 c )
|
||||
{
|
||||
Int32 i;
|
||||
|
||||
for (i = 31; i >= 0; i--)
|
||||
bsPutBit ( bs, (c >> i) & 0x1 );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
static Bool endsInBz2 ( Char* name )
|
||||
{
|
||||
Int32 n = strlen ( name );
|
||||
if (n <= 4) return False;
|
||||
return
|
||||
(name[n-4] == '.' &&
|
||||
name[n-3] == 'b' &&
|
||||
name[n-2] == 'z' &&
|
||||
name[n-1] == '2');
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
/* This logic isn't really right when it comes to Cygwin. */
|
||||
#ifdef _WIN32
|
||||
# define BZ_SPLIT_SYM '\\' /* path splitter on Windows platform */
|
||||
#else
|
||||
# define BZ_SPLIT_SYM '/' /* path splitter on Unix platform */
|
||||
#endif
|
||||
|
||||
#define BLOCK_HEADER_HI 0x00003141UL
|
||||
#define BLOCK_HEADER_LO 0x59265359UL
|
||||
|
||||
#define BLOCK_ENDMARK_HI 0x00001772UL
|
||||
#define BLOCK_ENDMARK_LO 0x45385090UL
|
||||
|
||||
/* Increase if necessary. However, a .bz2 file with > 50000 blocks
|
||||
would have an uncompressed size of at least 40GB, so the chances
|
||||
are low you'll need to up this.
|
||||
*/
|
||||
#define BZ_MAX_HANDLED_BLOCKS 50000
|
||||
|
||||
MaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS];
|
||||
MaybeUInt64 bEnd [BZ_MAX_HANDLED_BLOCKS];
|
||||
MaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS];
|
||||
MaybeUInt64 rbEnd [BZ_MAX_HANDLED_BLOCKS];
|
||||
|
||||
Int32 main ( Int32 argc, Char** argv )
|
||||
{
|
||||
FILE* inFile;
|
||||
FILE* outFile;
|
||||
BitStream* bsIn, *bsWr;
|
||||
Int32 b, wrBlock, currBlock, rbCtr;
|
||||
MaybeUInt64 bitsRead;
|
||||
|
||||
UInt32 buffHi, buffLo, blockCRC;
|
||||
Char* p;
|
||||
|
||||
strcpy ( progName, argv[0] );
|
||||
inFileName[0] = outFileName[0] = 0;
|
||||
|
||||
fprintf ( stderr,
|
||||
"bzip2recover 1.0.5: extracts blocks from damaged .bz2 files.\n" );
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n",
|
||||
progName, progName );
|
||||
switch (sizeof(MaybeUInt64)) {
|
||||
case 8:
|
||||
fprintf(stderr,
|
||||
"\trestrictions on size of recovered file: None\n");
|
||||
break;
|
||||
case 4:
|
||||
fprintf(stderr,
|
||||
"\trestrictions on size of recovered file: 512 MB\n");
|
||||
fprintf(stderr,
|
||||
"\tto circumvent, recompile with MaybeUInt64 as an\n"
|
||||
"\tunsigned 64-bit int.\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"\tsizeof(MaybeUInt64) is not 4 or 8 -- "
|
||||
"configuration error.\n");
|
||||
break;
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) {
|
||||
fprintf ( stderr,
|
||||
"%s: supplied filename is suspiciously (>= %d chars) long. Bye!\n",
|
||||
progName, (int)strlen(argv[1]) );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strcpy ( inFileName, argv[1] );
|
||||
|
||||
inFile = fopen ( inFileName, "rb" );
|
||||
if (inFile == NULL) {
|
||||
fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bsIn = bsOpenReadStream ( inFile );
|
||||
fprintf ( stderr, "%s: searching for block boundaries ...\n", progName );
|
||||
|
||||
bitsRead = 0;
|
||||
buffHi = buffLo = 0;
|
||||
currBlock = 0;
|
||||
bStart[currBlock] = 0;
|
||||
|
||||
rbCtr = 0;
|
||||
|
||||
while (True) {
|
||||
b = bsGetBit ( bsIn );
|
||||
bitsRead++;
|
||||
if (b == 2) {
|
||||
if (bitsRead >= bStart[currBlock] &&
|
||||
(bitsRead - bStart[currBlock]) >= 40) {
|
||||
bEnd[currBlock] = bitsRead-1;
|
||||
if (currBlock > 0)
|
||||
fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT
|
||||
" to " MaybeUInt64_FMT " (incomplete)\n",
|
||||
currBlock, bStart[currBlock], bEnd[currBlock] );
|
||||
} else
|
||||
currBlock--;
|
||||
break;
|
||||
}
|
||||
buffHi = (buffHi << 1) | (buffLo >> 31);
|
||||
buffLo = (buffLo << 1) | (b & 1);
|
||||
if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI
|
||||
&& buffLo == BLOCK_HEADER_LO)
|
||||
||
|
||||
( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI
|
||||
&& buffLo == BLOCK_ENDMARK_LO)
|
||||
) {
|
||||
if (bitsRead > 49) {
|
||||
bEnd[currBlock] = bitsRead-49;
|
||||
} else {
|
||||
bEnd[currBlock] = 0;
|
||||
}
|
||||
if (currBlock > 0 &&
|
||||
(bEnd[currBlock] - bStart[currBlock]) >= 130) {
|
||||
fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT
|
||||
" to " MaybeUInt64_FMT "\n",
|
||||
rbCtr+1, bStart[currBlock], bEnd[currBlock] );
|
||||
rbStart[rbCtr] = bStart[currBlock];
|
||||
rbEnd[rbCtr] = bEnd[currBlock];
|
||||
rbCtr++;
|
||||
}
|
||||
if (currBlock >= BZ_MAX_HANDLED_BLOCKS)
|
||||
tooManyBlocks(BZ_MAX_HANDLED_BLOCKS);
|
||||
currBlock++;
|
||||
|
||||
bStart[currBlock] = bitsRead;
|
||||
}
|
||||
}
|
||||
|
||||
bsClose ( bsIn );
|
||||
|
||||
/*-- identified blocks run from 1 to rbCtr inclusive. --*/
|
||||
|
||||
if (rbCtr < 1) {
|
||||
fprintf ( stderr,
|
||||
"%s: sorry, I couldn't find any block boundaries.\n",
|
||||
progName );
|
||||
exit(1);
|
||||
};
|
||||
|
||||
fprintf ( stderr, "%s: splitting into blocks\n", progName );
|
||||
|
||||
inFile = fopen ( inFileName, "rb" );
|
||||
if (inFile == NULL) {
|
||||
fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName );
|
||||
exit(1);
|
||||
}
|
||||
bsIn = bsOpenReadStream ( inFile );
|
||||
|
||||
/*-- placate gcc's dataflow analyser --*/
|
||||
blockCRC = 0; bsWr = 0;
|
||||
|
||||
bitsRead = 0;
|
||||
outFile = NULL;
|
||||
wrBlock = 0;
|
||||
while (True) {
|
||||
b = bsGetBit(bsIn);
|
||||
if (b == 2) break;
|
||||
buffHi = (buffHi << 1) | (buffLo >> 31);
|
||||
buffLo = (buffLo << 1) | (b & 1);
|
||||
if (bitsRead == 47+rbStart[wrBlock])
|
||||
blockCRC = (buffHi << 16) | (buffLo >> 16);
|
||||
|
||||
if (outFile != NULL && bitsRead >= rbStart[wrBlock]
|
||||
&& bitsRead <= rbEnd[wrBlock]) {
|
||||
bsPutBit ( bsWr, b );
|
||||
}
|
||||
|
||||
bitsRead++;
|
||||
|
||||
if (bitsRead == rbEnd[wrBlock]+1) {
|
||||
if (outFile != NULL) {
|
||||
bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 );
|
||||
bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 );
|
||||
bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 );
|
||||
bsPutUInt32 ( bsWr, blockCRC );
|
||||
bsClose ( bsWr );
|
||||
}
|
||||
if (wrBlock >= rbCtr) break;
|
||||
wrBlock++;
|
||||
} else
|
||||
if (bitsRead == rbStart[wrBlock]) {
|
||||
/* Create the output file name, correctly handling leading paths.
|
||||
(31.10.2001 by Sergey E. Kusikov) */
|
||||
Char* split;
|
||||
Int32 ofs, k;
|
||||
for (k = 0; k < BZ_MAX_FILENAME; k++)
|
||||
outFileName[k] = 0;
|
||||
strcpy (outFileName, inFileName);
|
||||
split = strrchr (outFileName, BZ_SPLIT_SYM);
|
||||
if (split == NULL) {
|
||||
split = outFileName;
|
||||
} else {
|
||||
++split;
|
||||
}
|
||||
/* Now split points to the start of the basename. */
|
||||
ofs = split - outFileName;
|
||||
sprintf (split, "rec%5d", wrBlock+1);
|
||||
for (p = split; *p != 0; p++) if (*p == ' ') *p = '0';
|
||||
strcat (outFileName, inFileName + ofs);
|
||||
|
||||
if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" );
|
||||
|
||||
fprintf ( stderr, " writing block %d to `%s' ...\n",
|
||||
wrBlock+1, outFileName );
|
||||
|
||||
outFile = fopen ( outFileName, "wb" );
|
||||
if (outFile == NULL) {
|
||||
fprintf ( stderr, "%s: can't write `%s'\n",
|
||||
progName, outFileName );
|
||||
exit(1);
|
||||
}
|
||||
bsWr = bsOpenWriteStream ( outFile );
|
||||
bsPutUChar ( bsWr, BZ_HDR_B );
|
||||
bsPutUChar ( bsWr, BZ_HDR_Z );
|
||||
bsPutUChar ( bsWr, BZ_HDR_h );
|
||||
bsPutUChar ( bsWr, BZ_HDR_0 + 9 );
|
||||
bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 );
|
||||
bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 );
|
||||
bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 );
|
||||
}
|
||||
}
|
||||
|
||||
fprintf ( stderr, "%s: finished\n", progName );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/*--- end bzip2recover.c ---*/
|
||||
/*-----------------------------------------------------------*/
|
||||
@ -1,175 +0,0 @@
|
||||
/*
|
||||
minibz2
|
||||
libbz2.dll test program.
|
||||
by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
|
||||
This file is Public Domain. Welcome any email to me.
|
||||
|
||||
usage: minibz2 [-d] [-{1,2,..9}] [[srcfilename] destfilename]
|
||||
*/
|
||||
|
||||
#define BZ_IMPORT
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "bzlib.h"
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define BZ2_LIBNAME "libbz2-1.0.2.DLL"
|
||||
|
||||
#include <windows.h>
|
||||
static int BZ2DLLLoaded = 0;
|
||||
static HINSTANCE BZ2DLLhLib;
|
||||
int BZ2DLLLoadLibrary(void)
|
||||
{
|
||||
HINSTANCE hLib;
|
||||
|
||||
if(BZ2DLLLoaded==1){return 0;}
|
||||
hLib=LoadLibrary(BZ2_LIBNAME);
|
||||
if(hLib == NULL){
|
||||
fprintf(stderr,"Can't load %s\n",BZ2_LIBNAME);
|
||||
return -1;
|
||||
}
|
||||
BZ2_bzlibVersion=GetProcAddress(hLib,"BZ2_bzlibVersion");
|
||||
BZ2_bzopen=GetProcAddress(hLib,"BZ2_bzopen");
|
||||
BZ2_bzdopen=GetProcAddress(hLib,"BZ2_bzdopen");
|
||||
BZ2_bzread=GetProcAddress(hLib,"BZ2_bzread");
|
||||
BZ2_bzwrite=GetProcAddress(hLib,"BZ2_bzwrite");
|
||||
BZ2_bzflush=GetProcAddress(hLib,"BZ2_bzflush");
|
||||
BZ2_bzclose=GetProcAddress(hLib,"BZ2_bzclose");
|
||||
BZ2_bzerror=GetProcAddress(hLib,"BZ2_bzerror");
|
||||
|
||||
if (!BZ2_bzlibVersion || !BZ2_bzopen || !BZ2_bzdopen
|
||||
|| !BZ2_bzread || !BZ2_bzwrite || !BZ2_bzflush
|
||||
|| !BZ2_bzclose || !BZ2_bzerror) {
|
||||
fprintf(stderr,"GetProcAddress failed.\n");
|
||||
return -1;
|
||||
}
|
||||
BZ2DLLLoaded=1;
|
||||
BZ2DLLhLib=hLib;
|
||||
return 0;
|
||||
|
||||
}
|
||||
int BZ2DLLFreeLibrary(void)
|
||||
{
|
||||
if(BZ2DLLLoaded==0){return 0;}
|
||||
FreeLibrary(BZ2DLLhLib);
|
||||
BZ2DLLLoaded=0;
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
puts("usage: minibz2 [-d] [-{1,2,..9}] [[srcfilename] destfilename]");
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
int decompress = 0;
|
||||
int level = 9;
|
||||
char *fn_r = NULL;
|
||||
char *fn_w = NULL;
|
||||
|
||||
#ifdef _WIN32
|
||||
if(BZ2DLLLoadLibrary()<0){
|
||||
fprintf(stderr,"Loading of %s failed. Giving up.\n", BZ2_LIBNAME);
|
||||
exit(1);
|
||||
}
|
||||
printf("Loading of %s succeeded. Library version is %s.\n",
|
||||
BZ2_LIBNAME, BZ2_bzlibVersion() );
|
||||
#endif
|
||||
while(++argv,--argc){
|
||||
if(**argv =='-' || **argv=='/'){
|
||||
char *p;
|
||||
|
||||
for(p=*argv+1;*p;p++){
|
||||
if(*p=='d'){
|
||||
decompress = 1;
|
||||
}else if('1'<=*p && *p<='9'){
|
||||
level = *p - '0';
|
||||
}else{
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(argc>=1){
|
||||
fn_r = *argv;
|
||||
argc--;argv++;
|
||||
}else{
|
||||
fn_r = NULL;
|
||||
}
|
||||
if(argc>=1){
|
||||
fn_w = *argv;
|
||||
argc--;argv++;
|
||||
}else{
|
||||
fn_w = NULL;
|
||||
}
|
||||
{
|
||||
int len;
|
||||
char buff[0x1000];
|
||||
char mode[10];
|
||||
|
||||
if(decompress){
|
||||
BZFILE *BZ2fp_r = NULL;
|
||||
FILE *fp_w = NULL;
|
||||
|
||||
if(fn_w){
|
||||
if((fp_w = fopen(fn_w,"wb"))==NULL){
|
||||
printf("can't open [%s]\n",fn_w);
|
||||
perror("reason:");
|
||||
exit(1);
|
||||
}
|
||||
}else{
|
||||
fp_w = stdout;
|
||||
}
|
||||
if((fn_r == NULL && (BZ2fp_r = BZ2_bzdopen(fileno(stdin),"rb"))==NULL)
|
||||
|| (fn_r != NULL && (BZ2fp_r = BZ2_bzopen(fn_r,"rb"))==NULL)){
|
||||
printf("can't bz2openstream\n");
|
||||
exit(1);
|
||||
}
|
||||
while((len=BZ2_bzread(BZ2fp_r,buff,0x1000))>0){
|
||||
fwrite(buff,1,len,fp_w);
|
||||
}
|
||||
BZ2_bzclose(BZ2fp_r);
|
||||
if(fp_w != stdout) fclose(fp_w);
|
||||
}else{
|
||||
BZFILE *BZ2fp_w = NULL;
|
||||
FILE *fp_r = NULL;
|
||||
|
||||
if(fn_r){
|
||||
if((fp_r = fopen(fn_r,"rb"))==NULL){
|
||||
printf("can't open [%s]\n",fn_r);
|
||||
perror("reason:");
|
||||
exit(1);
|
||||
}
|
||||
}else{
|
||||
fp_r = stdin;
|
||||
}
|
||||
mode[0]='w';
|
||||
mode[1] = '0' + level;
|
||||
mode[2] = '\0';
|
||||
|
||||
if((fn_w == NULL && (BZ2fp_w = BZ2_bzdopen(fileno(stdout),mode))==NULL)
|
||||
|| (fn_w !=NULL && (BZ2fp_w = BZ2_bzopen(fn_w,mode))==NULL)){
|
||||
printf("can't bz2openstream\n");
|
||||
exit(1);
|
||||
}
|
||||
while((len=fread(buff,1,0x1000,fp_r))>0){
|
||||
BZ2_bzwrite(BZ2fp_w,buff,len);
|
||||
}
|
||||
BZ2_bzclose(BZ2fp_w);
|
||||
if(fp_r!=stdin)fclose(fp_r);
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
BZ2DLLFreeLibrary();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
|
||||
/* Spew out a long sequence of the byte 251. When fed to bzip2
|
||||
versions 1.0.0 or 1.0.1, causes it to die with internal error
|
||||
1007 in blocksort.c. This assertion misses an extremely rare
|
||||
case, which is fixed in this version (1.0.2) and above.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 48500000 ; i++)
|
||||
putchar(251);
|
||||
return 0;
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
|
||||
/* spew out a thoroughly gigantic file designed so that bzip2
|
||||
can compress it reasonably rapidly. This is to help test
|
||||
support for large files (> 2GB) in a reasonable amount of time.
|
||||
I suggest you use the undocumented --exponential option to
|
||||
bzip2 when compressing the resulting file; this saves a bit of
|
||||
time. Note: *don't* bother with --exponential when compressing
|
||||
Real Files; it'll just waste a lot of CPU time :-)
|
||||
(but is otherwise harmless).
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* The number of megabytes of junk to spew out (roughly) */
|
||||
#define MEGABYTES 5000
|
||||
|
||||
#define N_BUF 1000000
|
||||
char buf[N_BUF];
|
||||
|
||||
int main ( int argc, char** argv )
|
||||
{
|
||||
int ii, kk, p;
|
||||
srandom(1);
|
||||
setbuffer ( stdout, buf, N_BUF );
|
||||
for (kk = 0; kk < MEGABYTES * 515; kk+=3) {
|
||||
p = 25+random()%50;
|
||||
for (ii = 0; ii < p; ii++)
|
||||
printf ( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" );
|
||||
for (ii = 0; ii < p-1; ii++)
|
||||
printf ( "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" );
|
||||
for (ii = 0; ii < p+1; ii++)
|
||||
printf ( "ccccccccccccccccccccccccccccccccccccc" );
|
||||
}
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
@ -1,141 +0,0 @@
|
||||
|
||||
/* A test program written to test robustness to decompression of
|
||||
corrupted data. Usage is
|
||||
unzcrash filename
|
||||
and the program will read the specified file, compress it (in memory),
|
||||
and then repeatedly decompress it, each time with a different bit of
|
||||
the compressed data inverted, so as to test all possible one-bit errors.
|
||||
This should not cause any invalid memory accesses. If it does,
|
||||
I want to know about it!
|
||||
|
||||
PS. As you can see from the above description, the process is
|
||||
incredibly slow. A file of size eg 5KB will cause it to run for
|
||||
many hours.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "bzlib.h"
|
||||
|
||||
#define M_BLOCK 1000000
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#define M_BLOCK_OUT (M_BLOCK + 1000000)
|
||||
uchar inbuf[M_BLOCK];
|
||||
uchar outbuf[M_BLOCK_OUT];
|
||||
uchar zbuf[M_BLOCK + 600 + (M_BLOCK / 100)];
|
||||
|
||||
int nIn, nOut, nZ;
|
||||
|
||||
static char *bzerrorstrings[] = {
|
||||
"OK"
|
||||
,"SEQUENCE_ERROR"
|
||||
,"PARAM_ERROR"
|
||||
,"MEM_ERROR"
|
||||
,"DATA_ERROR"
|
||||
,"DATA_ERROR_MAGIC"
|
||||
,"IO_ERROR"
|
||||
,"UNEXPECTED_EOF"
|
||||
,"OUTBUFF_FULL"
|
||||
,"???" /* for future */
|
||||
,"???" /* for future */
|
||||
,"???" /* for future */
|
||||
,"???" /* for future */
|
||||
,"???" /* for future */
|
||||
,"???" /* for future */
|
||||
};
|
||||
|
||||
void flip_bit ( int bit )
|
||||
{
|
||||
int byteno = bit / 8;
|
||||
int bitno = bit % 8;
|
||||
uchar mask = 1 << bitno;
|
||||
//fprintf ( stderr, "(byte %d bit %d mask %d)",
|
||||
// byteno, bitno, (int)mask );
|
||||
zbuf[byteno] ^= mask;
|
||||
}
|
||||
|
||||
int main ( int argc, char** argv )
|
||||
{
|
||||
FILE* f;
|
||||
int r;
|
||||
int bit;
|
||||
int i;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf ( stderr, "usage: unzcrash filename\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
f = fopen ( argv[1], "r" );
|
||||
if (!f) {
|
||||
fprintf ( stderr, "unzcrash: can't open %s\n", argv[1] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
nIn = fread ( inbuf, 1, M_BLOCK, f );
|
||||
fprintf ( stderr, "%d bytes read\n", nIn );
|
||||
|
||||
nZ = M_BLOCK;
|
||||
r = BZ2_bzBuffToBuffCompress (
|
||||
zbuf, &nZ, inbuf, nIn, 9, 0, 30 );
|
||||
|
||||
assert (r == BZ_OK);
|
||||
fprintf ( stderr, "%d after compression\n", nZ );
|
||||
|
||||
for (bit = 0; bit < nZ*8; bit++) {
|
||||
fprintf ( stderr, "bit %d ", bit );
|
||||
flip_bit ( bit );
|
||||
nOut = M_BLOCK_OUT;
|
||||
r = BZ2_bzBuffToBuffDecompress (
|
||||
outbuf, &nOut, zbuf, nZ, 0, 0 );
|
||||
fprintf ( stderr, " %d %s ", r, bzerrorstrings[-r] );
|
||||
|
||||
if (r != BZ_OK) {
|
||||
fprintf ( stderr, "\n" );
|
||||
} else {
|
||||
if (nOut != nIn) {
|
||||
fprintf(stderr, "nIn/nOut mismatch %d %d\n", nIn, nOut );
|
||||
return 1;
|
||||
} else {
|
||||
for (i = 0; i < nOut; i++)
|
||||
if (inbuf[i] != outbuf[i]) {
|
||||
fprintf(stderr, "mismatch at %d\n", i );
|
||||
return 1;
|
||||
}
|
||||
if (i == nOut) fprintf(stderr, "really ok!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
flip_bit ( bit );
|
||||
}
|
||||
|
||||
#if 0
|
||||
assert (nOut == nIn);
|
||||
for (i = 0; i < nOut; i++) {
|
||||
if (inbuf[i] != outbuf[i]) {
|
||||
fprintf ( stderr, "difference at %d !\n", i );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf ( stderr, "all ok\n" );
|
||||
return 0;
|
||||
}
|
||||
62
src/dep/src/StormLib/doc/History.txt
Normal file
62
src/dep/src/StormLib/doc/History.txt
Normal file
@ -0,0 +1,62 @@
|
||||
|
||||
StormLib history
|
||||
================
|
||||
|
||||
Version 8.02
|
||||
|
||||
- Support for UNICODE encoding for on-disk files
|
||||
- Optimized file deleting
|
||||
|
||||
Version 8.01
|
||||
|
||||
- SFileFindFirstFile and SFileFindNextFile no longer find files that have
|
||||
patch file in the oldest MPQ in the patch chain
|
||||
- Write support for MPQs version 4
|
||||
|
||||
Version 8.00
|
||||
|
||||
- Updated support for protected maps from Warcraft III
|
||||
|
||||
Version 7.11
|
||||
|
||||
- Support for MPQs v 3.0 (WOW-Cataclysm BETA)
|
||||
- StormLib now deals properly with files that have MPQ_SECTOR_CHECKSUM missing,
|
||||
but have sector checksum entry present in the sector offset table
|
||||
|
||||
Version 7.10
|
||||
|
||||
- Support for partial MPQs ("interface.MPQ.part")
|
||||
- The only operation that is externally allowed to do with internal files
|
||||
("(listfile)", "(attributes)" and "(signature)") is reading. Attempt to modify any of the file
|
||||
fails and GetLastError returns ERROR_INTERNAL_FILE
|
||||
- Fixed memory leak that has occured when writing more than one sector to the file at once
|
||||
|
||||
Version 7.01
|
||||
|
||||
- Support for adding files from memory
|
||||
- Fixed improper validation of handles to MPQ file and MPQ archive
|
||||
- Fixed bug where StormLib didn't save CRC32 of the file when added to archive
|
||||
|
||||
Version 7.00
|
||||
|
||||
- Properly deals with MPQs protected by w3xMaster
|
||||
- Major rewrite
|
||||
- Fixed support for (attributes)
|
||||
- Added file verification
|
||||
- Added MPQ signature verification
|
||||
|
||||
Version 6.22
|
||||
|
||||
- Properly deals with MPQs protected by w3xMaster
|
||||
|
||||
Version 6.21
|
||||
|
||||
- SFileRenameFile now properly re-crypts the file if necessary.
|
||||
- SFileFindFirstFile correctly deals with deleted files
|
||||
|
||||
Version 6.20
|
||||
|
||||
- Fixed lots of bugs when processing files with same names but different locales
|
||||
- Fixed bugs when repeately extracts the same file with MPQ_FILE_SINGLE_UNIT flag
|
||||
- Added SFileFlushArchive
|
||||
- Fixed issue opening AVI files renamed to MPQ using SFileCreateArchiveEx
|
||||
318
src/dep/src/StormLib/doc/The MoPaQ File Format 0.9.txt
Normal file
318
src/dep/src/StormLib/doc/The MoPaQ File Format 0.9.txt
Normal file
@ -0,0 +1,318 @@
|
||||
THE MOPAQ ARCHIVE FORMAT
|
||||
v0.9 (Thursday, June 30, 2005)
|
||||
by Justin Olbrantz(Quantam)
|
||||
|
||||
Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quoting
|
||||
in other works is freely allowed, as long as the source and author of the quote is stated.
|
||||
|
||||
TABLE OF CONTENTS
|
||||
1. Introduction to the MoPaQ Format
|
||||
2. The MoPaQ Format
|
||||
2.1 General Archive Layout
|
||||
2.2 Archive Header
|
||||
2.3 Block Table
|
||||
2.4 Hash Table
|
||||
2.5 File Data
|
||||
2.6 Listfile
|
||||
2.7 Extended Attributes
|
||||
2.8 Weak (Old) Digital Signature
|
||||
2.9 Strong (New) Digital Signature
|
||||
3. Algorithm Source Code
|
||||
3.1 Encryption/Decryption
|
||||
3.2 Hashing
|
||||
3.3 Conversion of FILETIME and time_t
|
||||
|
||||
1. INTRODUCTION TO THE MOPAQ FORMAT
|
||||
The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard
|
||||
Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be
|
||||
a read-only game archive format, and excels at this role.
|
||||
|
||||
The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked.
|
||||
The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked.
|
||||
|
||||
2. THE MOPAQ FORMAT
|
||||
All numbers in the MoPaQ format are in little endian. Data types are listed either as int (integer, the number of bits specified),
|
||||
byte (8 bits), and char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise.
|
||||
Structure members are listed in the following general form:
|
||||
offset from the beginning of the structure: data type(array size) member name : member description
|
||||
|
||||
2.1 GENERAL ARCHIVE LAYOUT
|
||||
- Archive Header
|
||||
- File Data
|
||||
- File Data - Special Files
|
||||
- Hash Table
|
||||
- Block Table
|
||||
- Strong Digital signature
|
||||
|
||||
This is the usual archive format, and is not absolutely essential. Some archives have been observed placing the hash table
|
||||
and file table after the archive header, and before the file data.
|
||||
|
||||
2.2 ARCHIVE HEADER
|
||||
00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah.
|
||||
04h: int32 HeaderSize : Size of the archive header. Should be 32.
|
||||
08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present.
|
||||
This size is used, among other things, for determining the region to hash in computing the digital signature.
|
||||
0Ch: int16 Unknown : Unknown
|
||||
0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector
|
||||
in the archive. The size of each logical sector the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate
|
||||
that this should always be 3 (4096 byte sectors).
|
||||
10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive.
|
||||
14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive.
|
||||
18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16.
|
||||
1Ch: int32 BlockTableEntries : Number of entries in the block table.
|
||||
|
||||
The archive header is the first structure in the archive, at archive offset 0, but the archive does not need to be at offset
|
||||
0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not
|
||||
at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the
|
||||
archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer
|
||||
versions (due to the strong digital signature not being considered a part of the archive).
|
||||
|
||||
2.3 BLOCK TABLE
|
||||
The block table contains entries for each region in the archive. Regions may be either files or empty space, which may be
|
||||
overwritten by new files (typically this space is from deleted file data). The block table is encrypted, using the hash
|
||||
of "(block table)" as the key. Each entry is structured as follows:
|
||||
|
||||
00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive. Meaningless if the block size is 0.
|
||||
04h: int32 BlockSize : Size of the block in the archive.
|
||||
08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file, otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data.
|
||||
0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified:
|
||||
80000000h: Block is a file, and follows the file data format; otherwise, block is free space, and may be overwritten. If the block is not a file, all other flags should be cleared.
|
||||
01000000h: File is stored as a single unit, rather than split into sectors.
|
||||
00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted.
|
||||
00010000h: File is encrypted.
|
||||
00000200h: File is compressed. Mutually exclusive to file imploded.
|
||||
00000100h: File is imploded. Mutually exclusive to file compressed.
|
||||
|
||||
2.4 HASH TABLE
|
||||
Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows:
|
||||
|
||||
00h: int32 FilePathHashA : The hash of the file path, using method A.
|
||||
04h: int32 FilePathHashB : The hash of the file path, using method B.
|
||||
08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral.
|
||||
0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed.
|
||||
0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values:
|
||||
FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file.
|
||||
FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file.
|
||||
|
||||
2.5 FILE DATA
|
||||
00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector's data, relative to the beginning of the file data. Not present if this information is calculatable (see details below).
|
||||
immediately following SectorOffsetTable: SectorData : Data of each sector in the file, packed end to end (see details below).
|
||||
|
||||
Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may be smaller than this, depending on the size of the file data. This sector size is the size of the raw file data; if the file is compressed, the compressed sector will be smaller or the same size as the uncompressed sector size. Individual sectors in a compressed file may be stored uncompressed; this occurs if and only if the sector could not be compressed by the algorithm used (if the compressed sector size was greater than or equal to the size of the raw data), and is indicated by the sector's compressed size in SectorOffsetTable being equal to the uncompressed size of the sector (which may be calculated from the FileSize).
|
||||
|
||||
If the sector is compressed (but not imploded), a bit mask byte of the compression algorithm(s) used to compress the sector is appended to the beginning of the compressed sector data. This additional byte counts towards the total size of the sector; if the size of the sector (including this byte) exceeds or matches the uncompressed size of the sector data, the sector will be stored uncompressed, and this byte omitted. Multiple compression algorithms may be used on the same sector; in this case, successive compression occurs in the order the algorithms are listed below, and decompression occurs in the opposite order. For implimentations of all of these algorithms, see StormLib.
|
||||
40h: IMA ADPCM mono
|
||||
80h: IMA ADPCM stereo
|
||||
01h: Huffman encoded
|
||||
02h: Deflated (see ZLib)
|
||||
08h: Imploded (see PKWare Data Compression Library)
|
||||
10h: BZip2 compressed (see BZip2)
|
||||
|
||||
If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which
|
||||
contains the entire file.
|
||||
|
||||
If the file is encrypted, each sector (after compression and appendage of the compression type byte, if applicable)
|
||||
is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the
|
||||
directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is
|
||||
adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset)
|
||||
XOR FileSize) (StormLib - an open-source implementation of the MoPaQ reading and writing functions,
|
||||
by Ladislav Zezula - incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the
|
||||
0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1.
|
||||
|
||||
The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize.
|
||||
This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors
|
||||
is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the
|
||||
SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously.
|
||||
Note that the SectorOffsetTable will always be present if the file is compressed/imploded and the file is not stored as
|
||||
a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the
|
||||
archive's sector size).
|
||||
|
||||
2.6 LISTFILE
|
||||
The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive.
|
||||
The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)",
|
||||
and is simply a non-Unix-style text file with one file path on each line, lines terminated with the bytes 0Dh 0Ah. The file
|
||||
"(listfile)" may not be listed in the listfile.
|
||||
|
||||
2.7 EXTENDED ATTRIBUTES
|
||||
The extended attributes are optional file attributes for files in the block table. These attributes were added at times after
|
||||
the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes.
|
||||
If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although
|
||||
the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the
|
||||
blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file,
|
||||
in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other
|
||||
structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some
|
||||
archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This
|
||||
file is structured as follows:
|
||||
|
||||
00h: int32 Version : Specifies the extended attributes format version. For now, must be 100.
|
||||
04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive:
|
||||
00000001h: File CRC32s.
|
||||
00000002h: File timestamps.
|
||||
00000004h: File MD5s.
|
||||
08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the
|
||||
archive does not have CRC32s. immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block
|
||||
in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps.
|
||||
immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive.
|
||||
Omitted if the archive does not have MD5s.
|
||||
|
||||
2.8 WEAK DIGITAL SIGNATURE
|
||||
The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation of the RSASSA-PKCS1-v1_5
|
||||
digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak) RSA key (for more information about this
|
||||
protocol, see the RSA Labs PKCS1 specification). The public key and exponent are stored in a resource in Storm. The signature
|
||||
is stored uncompressed, unencrypted in the file "(signature)" in the archive. The archive is hashed from the beginning of the
|
||||
archive (ArchiveOffset in the containing file) to the end of the archive (the length indicated by ArchiveSize); the signature
|
||||
file is added to the archive before signing, and the space occupied by the file is considered to be all binary 0s during
|
||||
signing/verification. This file is structured as follows:
|
||||
|
||||
00h: int32 Unknown : Must be 0.
|
||||
04h: int32 Unknown : must be 0.
|
||||
08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored in little-endian order.
|
||||
|
||||
2.9 STRONG DIGITAL SIGNATURE
|
||||
The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and
|
||||
a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well.
|
||||
The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize
|
||||
bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format:
|
||||
|
||||
00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards).
|
||||
04h: int2048 Signature : The digital signature, stored in little-endian format.
|
||||
|
||||
When the Signature field is decrypted with the public key and exponent, and the result stored in little-endian order, it is structured as follows:
|
||||
|
||||
00h: byte Padding : Must be 0Bh.
|
||||
01h: byte(235) Padding : Must be BBh.
|
||||
ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 format.
|
||||
|
||||
3. ALGORITHM SOURCE CODE
|
||||
3.1 ENCRYPTION/DECRYPTION
|
||||
I believe this was derived at some point from code in StormLib. Assumes the long type to be 32 bits, and the machine to be little endian order.
|
||||
|
||||
unsigned long dwCryptTable[0x500];
|
||||
|
||||
void InitializeCryptTable()
|
||||
{
|
||||
unsigned long seed = 0x00100001;
|
||||
unsigned long index1 = 0;
|
||||
unsigned long index2 = 0;
|
||||
int i;
|
||||
|
||||
for (index1 = 0; index1 < 0x100; index1++)
|
||||
{
|
||||
for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
|
||||
{
|
||||
unsigned long temp1, temp2;
|
||||
|
||||
seed = (seed * 125 + 3) % 0x2AAAAB;
|
||||
temp1 = (seed & 0xFFFF) << 0x10;
|
||||
|
||||
seed = (seed * 125 + 3) % 0x2AAAAB;
|
||||
temp2 = (seed & 0xFFFF);
|
||||
|
||||
dwCryptTable[index2] = (temp1 | temp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
|
||||
{
|
||||
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
|
||||
unsigned long seed = 0xEEEEEEEE;
|
||||
unsigned long ch;
|
||||
|
||||
assert(lpbyBuffer);
|
||||
|
||||
dwLength /= sizeof(unsigned long);
|
||||
|
||||
while(dwLength-- > 0)
|
||||
{
|
||||
seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
|
||||
ch = *lpdwBuffer ^ (dwKey + seed);
|
||||
|
||||
dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
|
||||
seed = *lpdwBuffer + seed + (seed << 5) + 3;
|
||||
|
||||
*lpdwBuffer++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
|
||||
{
|
||||
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
|
||||
unsigned long seed = 0xEEEEEEEE;
|
||||
unsigned long ch;
|
||||
|
||||
assert(lpbyBuffer);
|
||||
|
||||
dwLength /= sizeof(unsigned long);
|
||||
|
||||
while(dwLength-- > 0)
|
||||
{
|
||||
seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
|
||||
ch = *lpdwBuffer ^ (dwKey + seed);
|
||||
|
||||
dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
|
||||
seed = ch + seed + (seed << 5) + 3;
|
||||
|
||||
*lpdwBuffer++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
3.2 HASHING
|
||||
Based on code from StormLib.
|
||||
|
||||
// Different types of hashes to make with HashString
|
||||
#define MPQ_HASH_TABLE_OFFSET 0
|
||||
#define MPQ_HASH_NAME_A 1
|
||||
#define MPQ_HASH_NAME_B 2
|
||||
#define MPQ_HASH_FILE_KEY 3
|
||||
|
||||
unsigned long HashString(const char *lpszString, unsigned long dwHashType)
|
||||
{
|
||||
unsigned long seed1 = 0x7FED7FED;
|
||||
unsigned long seed2 = 0xEEEEEEEE;
|
||||
int ch;
|
||||
|
||||
while (*lpszString != 0)
|
||||
{
|
||||
ch = toupper(*lpszString++);
|
||||
|
||||
seed1 = dwCryptTable[(dwHashType * 0xFF) + ch] ^ (seed1 + seed2);
|
||||
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
|
||||
}
|
||||
return seed1;
|
||||
}
|
||||
|
||||
3.3 CONVERSION OF FILETIME AND time_t
|
||||
|
||||
#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970
|
||||
|
||||
bool GetTimeFromFileTime(FILETIME &fileTime, time_t &time)
|
||||
{
|
||||
// The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601
|
||||
unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
|
||||
|
||||
if (nTime < EPOCH_OFFSET)
|
||||
return false;
|
||||
|
||||
nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970
|
||||
nTime /= 10000000ULL; // Convert 100 ns to sec
|
||||
|
||||
time = (time_t)nTime;
|
||||
|
||||
// Test for overflow (FILETIME is 64 bits, time_t is 32 bits)
|
||||
if ((nTime - (unsigned long long)time) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetFileTimeFromTime(time_t &time, FILETIME &fileTime)
|
||||
{
|
||||
unsigned long long nTime = (unsigned long long)time;
|
||||
|
||||
nTime *= 10000000ULL;
|
||||
nTime += EPOCH_OFFSET;
|
||||
|
||||
fileTime.dwLowDateTime = (DWORD)nTime;
|
||||
fileTime.dwHighDateTime = (DWORD)(nTime >> 32);
|
||||
}
|
||||
433
src/dep/src/StormLib/doc/The MoPaQ File Format 1.0.txt
Normal file
433
src/dep/src/StormLib/doc/The MoPaQ File Format 1.0.txt
Normal file
@ -0,0 +1,433 @@
|
||||
THE MOPAQ ARCHIVE FORMAT
|
||||
v1.0 (Friday, September 1, 2006)
|
||||
by Justin Olbrantz(Quantam)
|
||||
|
||||
Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quotation in other works is freely allowed, as long as the source and author of the quote are stated.
|
||||
|
||||
TABLE OF CONTENTS
|
||||
1. Introduction to the MoPaQ Format
|
||||
2. The MoPaQ Format
|
||||
2.1 General Archive Layout
|
||||
2.2 Archive Header
|
||||
2.3 Block Table
|
||||
2.4 Extended Block Table
|
||||
2.5 Hash Table
|
||||
2.6 File Data
|
||||
2.7 Listfile
|
||||
2.8 Extended Attributes
|
||||
2.9 Weak (Old) Digital Signature
|
||||
2.10 Strong (New) Digital Signature
|
||||
3. Algorithm Source Code
|
||||
3.1 Encryption/Decryption
|
||||
3.2 Hashing and File Key Computation
|
||||
3.3 Finding Files
|
||||
3.4 Deleting Files
|
||||
3.5 Conversion of FILETIME and time_t
|
||||
3.6 Forming a 64-bit Large Archive Offset from 32-bit and 16-bit Components
|
||||
4. Revision History
|
||||
|
||||
1. INTRODUCTION TO THE MOPAQ FORMAT
|
||||
The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be a read-only game archive format, and excels at this role.
|
||||
|
||||
The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked. The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked.
|
||||
|
||||
StormLib - mentioned several times in this specification - is an open-source MoPaQ reading and writing library written by Ladislav Zezula (no affiliation with Blizzard Entertainment). While it's a bit dated, and does not support all of the newer MoPaQ features, it contains source code to the more exotic compression methods used by MoPaQ, such as the PKWare implode algorithm, MoPaQ's huffman compression algorithm, and the IMA ADPCM compression used by MoPaQ.
|
||||
|
||||
2. THE MOPAQ FORMAT
|
||||
All numbers in the MoPaQ format are in little endian byte order; signed numbers use the two's complement system. Data types are listed either as int (integer, the number of bits specified), byte (8 bits), or char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise. Structure members are listed in the following general form:
|
||||
offset from the beginning of the structure: data type(array size) member name : member description
|
||||
|
||||
2.1 GENERAL ARCHIVE LAYOUT
|
||||
- Archive Header
|
||||
- File Data
|
||||
- File Data - Special Files
|
||||
- Hash Table
|
||||
- Block Table
|
||||
- Extended Block Table
|
||||
- Strong Digital signature
|
||||
|
||||
This is the usual archive format, but it is not mandatory. Some archives have been observed placing the hash table and file table after the archive header, and before the file data.
|
||||
|
||||
2.2 ARCHIVE HEADER
|
||||
00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah.
|
||||
04h: int32 HeaderSize : Size of the archive header.
|
||||
08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present. This size is used, among other things, for determining the region to hash in computing the digital signature. This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive is calculated as the size from the beginning of the archive to the end of the hash table, block table, or extended block table (whichever is largest).
|
||||
0Ch: int16 FormatVersion : MoPaQ format version. MPQAPI will not open archives where this is negative. Known versions:
|
||||
0000h: Original format. HeaderSize should be 20h, and large archives are not supported.
|
||||
0001h: Burning Crusade format. Header size should be 2Ch, and large archives are supported.
|
||||
0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors).
|
||||
10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive.
|
||||
14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive.
|
||||
18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
|
||||
1Ch: int32 BlockTableEntries : Number of entries in the block table.
|
||||
Fields only present in the Burning Crusade format and later:
|
||||
20h: int64 ExtendedBlockTableOffset : Offset to the beginning of the extended block table, relative to the beginning of the archive.
|
||||
28h: int16 HashTableOffsetHigh : High 16 bits of the hash table offset for large archives.
|
||||
2Ah: int16 BlockTableOffsetHigh : High 16 bits of the block table offset for large archives.
|
||||
|
||||
The archive header is the first structure in the archive, at archive offset 0; however, the archive does not need to be at offset 0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer versions (due to the strong digital signature not being considered a part of the archive).
|
||||
|
||||
2.3 BLOCK TABLE
|
||||
The block table contains entries for each region in the archive. Regions may be either files, empty space, which may be overwritten by new files (typically this space is from deleted file data), or unused block table entries. Empty space entries should have BlockOffset and BlockSize nonzero, and FileSize and Flags zero; unused block table entries should have BlockSize, FileSize, and Flags zero. The block table is encrypted, using the hash of "(block table)" as the key. Each entry is structured as follows:
|
||||
|
||||
00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive.
|
||||
04h: int32 BlockSize : Size of the block in the archive.
|
||||
08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file; otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data.
|
||||
0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified:
|
||||
80000000h: Block is a file, and follows the file data format; otherwise, block is free space or unused. If the block is not a file, all other flags should be cleared, and FileSize should be 0.
|
||||
01000000h: File is stored as a single unit, rather than split into sectors.
|
||||
00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted.
|
||||
00010000h: File is encrypted.
|
||||
00000200h: File is compressed. File cannot be imploded.
|
||||
00000100h: File is imploded. File cannot be compressed.
|
||||
|
||||
2.4 EXTENDED BLOCK TABLE
|
||||
The extended block table was added to support archives larger than 4 gigabytes (2^32 bytes). The table contains the upper bits of the archive offsets for each block in the block table. It is simply an array of int16s, which become bits 32-47 of the archive offsets for each block, with bits 48-63 being zero. Individual blocks in the archive are still limited to 4 gigabytes in size. This table is only present in Burning Crusade format archives that exceed 4 gigabytes size.
|
||||
|
||||
As of the Burning Crusade Friends and Family beta, this table is not encrypted.
|
||||
|
||||
2.5 HASH TABLE
|
||||
Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows:
|
||||
|
||||
00h: int32 FilePathHashA : The hash of the file path, using method A.
|
||||
04h: int32 FilePathHashB : The hash of the file path, using method B.
|
||||
08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral.
|
||||
0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed.
|
||||
0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values:
|
||||
FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file.
|
||||
FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file.
|
||||
|
||||
2.6 FILE DATA
|
||||
The data for each file is composed of the following structure:
|
||||
00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector, relative to the beginning of the file data. The last entry contains the file size, making it possible to easily calculate the size of any given sector. This table is not present if this information can be calculated (see details below).
|
||||
immediately following SectorOffsetTable: SECTOR Sectors(SectorsInFile) : Data of each sector in the file, packed end to end (see details below).
|
||||
|
||||
Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may contain less than this, depending on the size of the entire file's data. If the file is compressed or imploded, the sector will be smaller or the same size as the file data it contains. Individual sectors in a compressed or imploded file may be stored uncompressed; this occurs if and only if the file data the sector contains could not be compressed by the algorithm(s) used (if the compressed sector size was greater than or equal to the size of the file data), and is indicated by the sector's size in SectorOffsetTable being equal to the size of the file data in the sector (which may be calculated from the FileSize).
|
||||
|
||||
The format of each sector depends on the kind of sector it is. Uncompressed sectors are simply the the raw file data contained in the sector. Imploded sectors are the raw compressed data following compression with the implode algorithm (these sectors can only be in imploded files). Compressed sectors (only found in compressed - not imploded - files) are compressed with one or more compression algorithms, and have the following structure:
|
||||
00h: byte CompressionMask : Mask of the compression types applied to this sector. If multiple compression types are used, they are applied in the order listed below, and decompression is performed in the opposite order. This byte counts towards the total sector size, meaning that the sector will be stored uncompressed if the data cannot be compressed by at least two bytes; as well, this byte is encrypted with the sector data, if applicable. The following compression types are defined (for implementations of these algorithms, see StormLib):
|
||||
40h: IMA ADPCM mono
|
||||
80h: IMA ADPCM stereo
|
||||
01h: Huffman encoded
|
||||
02h: Deflated (see ZLib)
|
||||
08h: Imploded (see PKWare Data Compression Library)
|
||||
10h: BZip2 compressed (see BZip2)
|
||||
01h: byte(SectorSize - 1) SectorData : The compressed data for the sector.
|
||||
|
||||
If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which contains the entire file data.
|
||||
|
||||
If the file is encrypted, each sector (after compression/implosion, if applicable) is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset) XOR FileSize) (StormLib incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the 0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1.
|
||||
|
||||
The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize. This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously. However, the SectorOffsetTable will be present if the file is compressed/imploded and the file is not stored as a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the archive's sector size).
|
||||
|
||||
2.7 LISTFILE
|
||||
The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive. The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)" (default language and platform), and is simply a text file with file paths separated by ';', 0Dh, 0Ah, or some combination of these. The file "(listfile)" may not be listed in the listfile.
|
||||
|
||||
2.8 EXTENDED ATTRIBUTES
|
||||
The extended attributes are optional file attributes for files in the block table. These attributes were added at times after the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes. If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file (default language and platform), in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This file is structured as follows:
|
||||
|
||||
00h: int32 Version : Specifies the extended attributes format version. For now, must be 100.
|
||||
04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive:
|
||||
00000001h: File CRC32s.
|
||||
00000002h: File timestamps.
|
||||
00000004h: File MD5s.
|
||||
08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the archive does not have CRC32s.
|
||||
immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps.
|
||||
immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive. Omitted if the archive does not have MD5s.
|
||||
|
||||
2.9 WEAK DIGITAL SIGNATURE
|
||||
The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation
|
||||
of the RSASSA-PKCS1-v1_5 digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak)
|
||||
RSA key (for more information about this protocol, see the RSA Labs PKCS1 specification). The public key
|
||||
and exponent are stored in a resource in Storm, the private key is stored in a separate file, whose filename
|
||||
is passed to MPQAPI (the private key is not stored in MPQAPI). The signature is stored uncompressed,
|
||||
unencrypted in the file "(signature)" (default language and platform) in the archive. The archive
|
||||
is hashed from the beginning of the archive (ArchiveOffset in the containing file) to the end of
|
||||
the archive (the length indicated by ArchiveSize, or calculated in the Burning Crusade MoPaQ format);
|
||||
the signature file is added to the archive before signing, and the space occupied by the file is considered
|
||||
to be all binary 0s during signing/verification. This file is structured as follows:
|
||||
|
||||
00h: int32 Unknown : Must be 0.
|
||||
04h: int32 Unknown : Must be 0.
|
||||
08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored
|
||||
in little-endian order. The structure of this, when decrypted, follows the RSASSA-PKCS1-v1_5 specification;
|
||||
this format is rather icky to work with (I wrote a program to verify this signature using nothing but an MD5
|
||||
function and huge integer functions; it wasn't pleasant), and best left to an encryption library such as Cryto++.
|
||||
|
||||
2.10 STRONG DIGITAL SIGNATURE
|
||||
The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well. The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format:
|
||||
|
||||
00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards).
|
||||
04h: int2048 Signature : The digital signature, stored in little-endian format.
|
||||
|
||||
When the Signature field is decrypted with the public key and exponent, and the resulting large integer is stored in little-endian order, it is structured as follows:
|
||||
|
||||
00h: byte Padding : Must be 0Bh.
|
||||
01h: byte(235) Padding : Must be BBh.
|
||||
ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 byte order.
|
||||
|
||||
3. ALGORITHM SOURCE CODE
|
||||
All of the sample code here assumes little endian machine byte order, that the short type is 16 bits, that the long type is 32 bits, and that the long long type is 64 bits. Adjustments must be made if these assumptions are not correct on a given platform. All code not credited otherwise was written by myself in the writing of this specification.
|
||||
|
||||
3.1 ENCRYPTION/DECRYPTION
|
||||
Based on code from StormLib.
|
||||
|
||||
unsigned long dwCryptTable[0x500];
|
||||
|
||||
// The encryption and hashing functions use a number table in their procedures. This table must be initialized before the functions are called the first time.
|
||||
void InitializeCryptTable()
|
||||
{
|
||||
unsigned long seed = 0x00100001;
|
||||
unsigned long index1 = 0;
|
||||
unsigned long index2 = 0;
|
||||
int i;
|
||||
|
||||
for (index1 = 0; index1 < 0x100; index1++)
|
||||
{
|
||||
for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
|
||||
{
|
||||
unsigned long temp1, temp2;
|
||||
|
||||
seed = (seed * 125 + 3) % 0x2AAAAB;
|
||||
temp1 = (seed & 0xFFFF) << 0x10;
|
||||
|
||||
seed = (seed * 125 + 3) % 0x2AAAAB;
|
||||
temp2 = (seed & 0xFFFF);
|
||||
|
||||
dwCryptTable[index2] = (temp1 | temp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
|
||||
{
|
||||
assert(lpbyBuffer);
|
||||
|
||||
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
|
||||
unsigned long seed = 0xEEEEEEEE;
|
||||
unsigned long ch;
|
||||
|
||||
dwLength /= sizeof(unsigned long);
|
||||
|
||||
while(dwLength-- > 0)
|
||||
{
|
||||
seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
|
||||
ch = *lpdwBuffer ^ (dwKey + seed);
|
||||
|
||||
dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
|
||||
seed = *lpdwBuffer + seed + (seed << 5) + 3;
|
||||
|
||||
*lpdwBuffer++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
|
||||
{
|
||||
assert(lpbyBuffer);
|
||||
|
||||
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
|
||||
unsigned long seed = 0xEEEEEEEEL;
|
||||
unsigned long ch;
|
||||
|
||||
dwLength /= sizeof(unsigned long);
|
||||
|
||||
while(dwLength-- > 0)
|
||||
{
|
||||
seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
|
||||
ch = *lpdwBuffer ^ (dwKey + seed);
|
||||
|
||||
dwKey = ((~dwKey << 0x15) + 0x11111111L) | (dwKey >> 0x0B);
|
||||
seed = ch + seed + (seed << 5) + 3;
|
||||
|
||||
*lpdwBuffer++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
3.2 HASHING AND FILE KEY COMPUTATION
|
||||
These functions may have been derived from StormLib code at some point in the very distant past. It was so long ago that I don't remember for certain.
|
||||
|
||||
// Different types of hashes to make with HashString
|
||||
#define MPQ_HASH_TABLE_OFFSET 0
|
||||
#define MPQ_HASH_NAME_A 1
|
||||
#define MPQ_HASH_NAME_B 2
|
||||
#define MPQ_HASH_FILE_KEY 3
|
||||
|
||||
// Based on code from StormLib.
|
||||
unsigned long HashString(const char *lpszString, unsigned long dwHashType)
|
||||
{
|
||||
assert(lpszString);
|
||||
assert(dwHashType <= MPQ_HASH_FILE_KEY);
|
||||
|
||||
unsigned long seed1 = 0x7FED7FEDL;
|
||||
unsigned long seed2 = 0xEEEEEEEEL;
|
||||
int ch;
|
||||
|
||||
while (*lpszString != 0)
|
||||
{
|
||||
ch = toupper(*lpszString++);
|
||||
|
||||
seed1 = dwCryptTable[(dwHashType * 0x100) + ch] ^ (seed1 + seed2);
|
||||
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
|
||||
}
|
||||
return seed1;
|
||||
}
|
||||
|
||||
#define BLOCK_OFFSET_ADJUSTED_KEY 0x00020000L
|
||||
|
||||
unsigned long ComputeFileKey(const char *lpszFilePath, const BlockTableEntry &blockEntry, unsigned long nArchiveOffset)
|
||||
{
|
||||
assert(lpszFilePath);
|
||||
|
||||
// Find the file name part of the path
|
||||
const char *lpszFileName = strrchr(lpszFilePath, '\\');
|
||||
if (lpszFileName)
|
||||
lpszFileName++; // Skip the \
|
||||
else
|
||||
lpszFileName = lpszFilePath;
|
||||
|
||||
// Hash the name to get the base key
|
||||
unsigned long nFileKey = HashString(lpszFileName, MPQ_HASH_FILE_KEY);
|
||||
|
||||
// Offset-adjust the key if necessary
|
||||
if (blockEntry.Flags & BLOCK_OFFSET_ADJUSTED_KEY)
|
||||
nFileKey = (nFileKey + blockEntry.BlockOffset) ^ blockEntry.FileSize;
|
||||
|
||||
return nFileKey;
|
||||
}
|
||||
|
||||
3.3 FINDING FILES
|
||||
|
||||
#define MPQ_HASH_ENTRY_EMPTY 0xFFFFFFFFL
|
||||
#define MPQ_HASH_ENTRY_DELETED 0xFFFFFFFEL
|
||||
|
||||
bool FindFileInHashTable(const HashTableEntry *lpHashTable, unsigned long nHashTableSize, const char *lpszFilePath, unsigned short nLang, unsigned char nPlatform, unsigned long &iFileHashEntry)
|
||||
{
|
||||
assert(lpHashTable);
|
||||
assert(nHashTableSize);
|
||||
assert(lpszFilePath);
|
||||
|
||||
// Find the home entry in the hash table for the file
|
||||
unsigned long iInitEntry = HashString(lpszFilePath, MPQ_HASH_TABLE_OFFSET) & (nHashTableSize - 1);
|
||||
|
||||
// Is there anything there at all?
|
||||
if (lpHashTable[iInitEntry].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY)
|
||||
return false;
|
||||
|
||||
// Compute the hashes to compare the hash table entry against
|
||||
unsigned long nNameHashA = HashString(lpszFilePath, MPQ_HASH_NAME_A),
|
||||
nNameHashB = HashString(lpszFilePath, MPQ_HASH_NAME_B),
|
||||
iCurEntry = iInitEntry;
|
||||
|
||||
// Check each entry in the hash table till a termination point is reached
|
||||
do
|
||||
{
|
||||
if (lpHashTable[iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_DELETED)
|
||||
{
|
||||
if (lpHashTable[iCurEntry].FilePathHashA == nNameHashA
|
||||
&& lpHashTable[iCurEntry].FilePathHashB == nNameHashB
|
||||
&& lpHashTable[iCurEntry].Language == nLang
|
||||
&& lpHashTable[iCurEntry].Platform == nPlatform)
|
||||
{
|
||||
iFileHashEntry = iCurEntry;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
iCurEntry = (iCurEntry + 1) & (nHashTableSize - 1);
|
||||
} while (iCurEntry != iInitEntry && lpHashTable[iCurEntry].FileBlockIndex != MPQ_HASH_ENTRY_EMPTY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
3.4 DELETING FILES
|
||||
|
||||
bool DeleteFile(HashTableEntry *lpHashTable, unsigned long nHashTableSize, BlockTableEntry *lpBlockTable, const char *lpszFilePath, unsigned short nLang, unsigned char nPlatform)
|
||||
{
|
||||
assert(lpHashTable);
|
||||
assert(nHashTableSize);
|
||||
assert(lpBlockTable);
|
||||
|
||||
// Find the file in the hash table
|
||||
unsigned long iFileHashEntry;
|
||||
|
||||
if (!FindFileInHashTable(lpHashTable, nHashTableSize, lpszFilePath, nLang, nPlatform, iFileHashEntry))
|
||||
return false;
|
||||
|
||||
// Get the block table index before we nuke the hash table entry
|
||||
unsigned long iFileBlockEntry = lpHashTable[iFileHashEntry].FileBlockIndex;
|
||||
|
||||
// Delete the file's entry in the hash table
|
||||
memset(&lpHashTable[iFileHashEntry], 0xFF, sizeof(HashTableEntry));
|
||||
|
||||
// If the next entry is empty, mark this one as empty; otherwise, mark this as deleted.
|
||||
if (lpHashTable[(iFileHashEntry + 1) & (nHashTableSize - 1)].FileBlockIndex == MPQ_HASH_ENTRY_EMPTY)
|
||||
lpHashTable[iFileHashEntry].FileBlockIndex = MPQ_HASH_ENTRY_EMPTY;
|
||||
else
|
||||
lpHashTable[iFileHashEntry].FileBlockIndex = MPQ_HASH_ENTRY_DELETED;
|
||||
|
||||
// If the block occupies space, mark the block as free space; otherwise, clear the block table entry.
|
||||
if (lpBlockTable[iFileBlockEntry].BlockSize > 0)
|
||||
{
|
||||
lpBlockTable[iFileBlockEntry].FileSize = 0;
|
||||
lpBlockTable[iFileBlockEntry].Flags = 0;
|
||||
}
|
||||
else
|
||||
memset(&lpBlockTable[iFileBlockEntry], 0, sizeof(BlockTableEntry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
3.5 CONVERSION OF FILETIME AND time_t
|
||||
This code assumes that the base ("zero") date for time_t is 01/01/1970. This is true on Windows, Unix System V systems, and Mac OS X. It is unknown whether this is true on all other platforms. You'll need to research this yourself, if you plan on porting it somewhere else.
|
||||
|
||||
#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970
|
||||
|
||||
bool GetTimeFromFileTime(const FILETIME &fileTime, time_t &time)
|
||||
{
|
||||
// The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601
|
||||
unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
|
||||
|
||||
if (nTime < EPOCH_OFFSET)
|
||||
return false;
|
||||
|
||||
nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970
|
||||
nTime /= 10000000ULL; // Convert 100 ns to sec
|
||||
|
||||
time = (time_t)nTime;
|
||||
|
||||
// Test for overflow (FILETIME is 64 bits, time_t is 32 bits)
|
||||
if ((nTime - (unsigned long long)time) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetFileTimeFromTime(const time_t &time, FILETIME &fileTime)
|
||||
{
|
||||
unsigned long long nTime = (unsigned long long)time;
|
||||
|
||||
nTime *= 10000000ULL;
|
||||
nTime += EPOCH_OFFSET;
|
||||
|
||||
fileTime.dwLowDateTime = (DWORD)nTime;
|
||||
fileTime.dwHighDateTime = (DWORD)(nTime >> 32);
|
||||
}
|
||||
|
||||
3.6 FORMING A 64-BIT LARGE ARCHIVE OFFSET FROM 32-BIT AND 16-BIT COMPONENTS
|
||||
unsigned long long MakeLargeArchiveOffset(unsigned long nOffsetLow, unsigned short nOffsetHigh)
|
||||
{
|
||||
return ((unsigned long long)nOffsetHigh << 32) + (unsigned long long)nOffsetLow;
|
||||
}
|
||||
|
||||
4. REVISION HISTORY
|
||||
1.0
|
||||
- Updated to include most of the changes found in the Burning Crusade Friends and Family beta
|
||||
|
||||
0.91.
|
||||
- Updated several structure member descriptions
|
||||
- Listed the full set of characters that can separate list file entries
|
||||
- Noted that (attributes), (listfile), and (signature) use the default language and platform codes
|
||||
- Redid part of the file data specs to clarify the format of sectors
|
||||
- Enhanced descriptions of the different kinds of block table entries
|
||||
- Added ComputeFileKey, FindFileInHashTable, and DeleteFile source
|
||||
268
src/dep/src/StormLib/makefile.w32
Normal file
268
src/dep/src/StormLib/makefile.w32
Normal file
@ -0,0 +1,268 @@
|
||||
#####################################################################
|
||||
#
|
||||
# Makefile for compiling StormLib with MINGW
|
||||
#
|
||||
# Author: Ladislav Zezula
|
||||
# Created: Mon May 10 14:13:00 CEST 2010
|
||||
# System: Windows Seven
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
PATH = C:\TOOLS32\MINGW\bin
|
||||
CPP = g++
|
||||
CC = gcc
|
||||
CFLAGS = -Wall
|
||||
DFLAGS = -D_7ZIP_ST
|
||||
LFLAGS = -shared
|
||||
#LFLAGS = -lbz2 -lz
|
||||
AR = ar
|
||||
ARFLAGS= rcs
|
||||
|
||||
LIBRARY = StormLib.dll
|
||||
#LIBRARY = StormLib.lib
|
||||
|
||||
OBJS_CPP = src/adpcm/adpcm.o \
|
||||
src/huffman/huff.o \
|
||||
src/sparse/sparse.o \
|
||||
src/FileStream.o \
|
||||
src/SBaseCommon.o \
|
||||
src/SBaseFileTable.o \
|
||||
src/SCompression.o \
|
||||
src/SFileAddFile.o \
|
||||
src/SFileAttributes.o \
|
||||
src/SFileCompactArchive.o \
|
||||
src/SFileCreateArchive.o \
|
||||
src/SFileExtractFile.o \
|
||||
src/SFileFindFile.o \
|
||||
src/SFileListFile.o \
|
||||
src/SFileOpenArchive.o \
|
||||
src/SFileOpenFileEx.o \
|
||||
src/SFilePatchArchives.o \
|
||||
src/SFileReadFile.o \
|
||||
src/SFileVerify.o
|
||||
|
||||
|
||||
OBJS_C = src/bzip2/blocksort.o \
|
||||
src/bzip2/bzlib.o \
|
||||
src/bzip2/compress.o \
|
||||
src/bzip2/crctable.o \
|
||||
src/bzip2/decompress.o \
|
||||
src/bzip2/huffman.o \
|
||||
src/bzip2/randtable.o \
|
||||
src/jenkins/lookup3.o \
|
||||
src/libtomcrypt/src/hashes/hash_memory.o \
|
||||
src/libtomcrypt/src/hashes/md5.o \
|
||||
src/libtomcrypt/src/hashes/sha1.o\
|
||||
src/libtomcrypt/src/math/ltm_desc.o \
|
||||
src/libtomcrypt/src/math/multi.o \
|
||||
src/libtomcrypt/src/math/rand_prime.o \
|
||||
src/libtomcrypt/src/misc/base64_decode.o \
|
||||
src/libtomcrypt/src/misc/crypt_argchk.o \
|
||||
src/libtomcrypt/src/misc/crypt_find_hash.o \
|
||||
src/libtomcrypt/src/misc/crypt_find_prng.o \
|
||||
src/libtomcrypt/src/misc/crypt_hash_descriptor.o \
|
||||
src/libtomcrypt/src/misc/crypt_hash_is_valid.o \
|
||||
src/libtomcrypt/src/misc/crypt_libc.o \
|
||||
src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.o \
|
||||
src/libtomcrypt/src/misc/crypt_prng_descriptor.o \
|
||||
src/libtomcrypt/src/misc/crypt_prng_is_valid.o \
|
||||
src/libtomcrypt/src/misc/crypt_register_hash.o \
|
||||
src/libtomcrypt/src/misc/crypt_register_prng.o \
|
||||
src/libtomcrypt/src/misc/zeromem.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_bit_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_boolean.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_choice.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_integer.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_octet_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_printable_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_short_integer.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utctime.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_bit_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_boolean.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_ia5_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_integer.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_object_identifier.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_octet_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_printable_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_sequence.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_short_integer.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utctime.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_length_utf8_string.o \
|
||||
src/libtomcrypt/src/pk/asn1/der_sequence_free.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_map.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_points.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.o \
|
||||
src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.o \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.o \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.o \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.o \
|
||||
src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_exptmod.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_free.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_import.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_make_key.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_hash.o \
|
||||
src/libtomcrypt/src/pk/rsa/rsa_verify_simple.o \
|
||||
src/libtommath/bncore.o \
|
||||
src/libtommath/bn_fast_mp_invmod.o \
|
||||
src/libtommath/bn_fast_mp_montgomery_reduce.o \
|
||||
src/libtommath/bn_fast_s_mp_mul_digs.o \
|
||||
src/libtommath/bn_fast_s_mp_mul_high_digs.o \
|
||||
src/libtommath/bn_fast_s_mp_sqr.o \
|
||||
src/libtommath/bn_mp_2expt.o \
|
||||
src/libtommath/bn_mp_abs.o \
|
||||
src/libtommath/bn_mp_add.o \
|
||||
src/libtommath/bn_mp_addmod.o \
|
||||
src/libtommath/bn_mp_add_d.o \
|
||||
src/libtommath/bn_mp_and.o \
|
||||
src/libtommath/bn_mp_clamp.o \
|
||||
src/libtommath/bn_mp_clear.o \
|
||||
src/libtommath/bn_mp_clear_multi.o \
|
||||
src/libtommath/bn_mp_cmp.o \
|
||||
src/libtommath/bn_mp_cmp_d.o \
|
||||
src/libtommath/bn_mp_cmp_mag.o \
|
||||
src/libtommath/bn_mp_cnt_lsb.o \
|
||||
src/libtommath/bn_mp_copy.o \
|
||||
src/libtommath/bn_mp_count_bits.o \
|
||||
src/libtommath/bn_mp_div.o \
|
||||
src/libtommath/bn_mp_div_2.o \
|
||||
src/libtommath/bn_mp_div_2d.o \
|
||||
src/libtommath/bn_mp_div_3.o \
|
||||
src/libtommath/bn_mp_div_d.o \
|
||||
src/libtommath/bn_mp_dr_is_modulus.o \
|
||||
src/libtommath/bn_mp_dr_reduce.o \
|
||||
src/libtommath/bn_mp_dr_setup.o \
|
||||
src/libtommath/bn_mp_exch.o \
|
||||
src/libtommath/bn_mp_exptmod.o \
|
||||
src/libtommath/bn_mp_exptmod_fast.o \
|
||||
src/libtommath/bn_mp_expt_d.o \
|
||||
src/libtommath/bn_mp_exteuclid.o \
|
||||
src/libtommath/bn_mp_fread.o \
|
||||
src/libtommath/bn_mp_fwrite.o \
|
||||
src/libtommath/bn_mp_gcd.o \
|
||||
src/libtommath/bn_mp_get_int.o \
|
||||
src/libtommath/bn_mp_grow.o \
|
||||
src/libtommath/bn_mp_init.o \
|
||||
src/libtommath/bn_mp_init_copy.o \
|
||||
src/libtommath/bn_mp_init_multi.o \
|
||||
src/libtommath/bn_mp_init_set.o \
|
||||
src/libtommath/bn_mp_init_set_int.o \
|
||||
src/libtommath/bn_mp_init_size.o \
|
||||
src/libtommath/bn_mp_invmod.o \
|
||||
src/libtommath/bn_mp_invmod_slow.o \
|
||||
src/libtommath/bn_mp_is_square.o \
|
||||
src/libtommath/bn_mp_jacobi.o \
|
||||
src/libtommath/bn_mp_karatsuba_mul.o \
|
||||
src/libtommath/bn_mp_karatsuba_sqr.o \
|
||||
src/libtommath/bn_mp_lcm.o \
|
||||
src/libtommath/bn_mp_lshd.o \
|
||||
src/libtommath/bn_mp_mod.o \
|
||||
src/libtommath/bn_mp_mod_2d.o \
|
||||
src/libtommath/bn_mp_mod_d.o \
|
||||
src/libtommath/bn_mp_montgomery_calc_normalization.o \
|
||||
src/libtommath/bn_mp_montgomery_reduce.o \
|
||||
src/libtommath/bn_mp_montgomery_setup.o \
|
||||
src/libtommath/bn_mp_mul.o \
|
||||
src/libtommath/bn_mp_mulmod.o \
|
||||
src/libtommath/bn_mp_mul_2.o \
|
||||
src/libtommath/bn_mp_mul_2d.o \
|
||||
src/libtommath/bn_mp_mul_d.o \
|
||||
src/libtommath/bn_mp_neg.o \
|
||||
src/libtommath/bn_mp_n_root.o \
|
||||
src/libtommath/bn_mp_or.o \
|
||||
src/libtommath/bn_mp_prime_fermat.o \
|
||||
src/libtommath/bn_mp_prime_is_divisible.o \
|
||||
src/libtommath/bn_mp_prime_is_prime.o \
|
||||
src/libtommath/bn_mp_prime_miller_rabin.o \
|
||||
src/libtommath/bn_mp_prime_next_prime.o \
|
||||
src/libtommath/bn_mp_prime_rabin_miller_trials.o \
|
||||
src/libtommath/bn_mp_prime_random_ex.o \
|
||||
src/libtommath/bn_mp_radix_size.o \
|
||||
src/libtommath/bn_mp_radix_smap.o \
|
||||
src/libtommath/bn_mp_rand.o \
|
||||
src/libtommath/bn_mp_read_radix.o \
|
||||
src/libtommath/bn_mp_read_signed_bin.o \
|
||||
src/libtommath/bn_mp_read_unsigned_bin.o \
|
||||
src/libtommath/bn_mp_reduce.o \
|
||||
src/libtommath/bn_mp_reduce_2k.o \
|
||||
src/libtommath/bn_mp_reduce_2k_l.o \
|
||||
src/libtommath/bn_mp_reduce_2k_setup.o \
|
||||
src/libtommath/bn_mp_reduce_2k_setup_l.o \
|
||||
src/libtommath/bn_mp_reduce_is_2k.o \
|
||||
src/libtommath/bn_mp_reduce_is_2k_l.o \
|
||||
src/libtommath/bn_mp_reduce_setup.o \
|
||||
src/libtommath/bn_mp_rshd.o \
|
||||
src/libtommath/bn_mp_set.o \
|
||||
src/libtommath/bn_mp_set_int.o \
|
||||
src/libtommath/bn_mp_shrink.o \
|
||||
src/libtommath/bn_mp_signed_bin_size.o \
|
||||
src/libtommath/bn_mp_sqr.o \
|
||||
src/libtommath/bn_mp_sqrmod.o \
|
||||
src/libtommath/bn_mp_sqrt.o \
|
||||
src/libtommath/bn_mp_sub.o \
|
||||
src/libtommath/bn_mp_submod.o \
|
||||
src/libtommath/bn_mp_sub_d.o \
|
||||
src/libtommath/bn_mp_toom_mul.o \
|
||||
src/libtommath/bn_mp_toom_sqr.o \
|
||||
src/libtommath/bn_mp_toradix.o \
|
||||
src/libtommath/bn_mp_toradix_n.o \
|
||||
src/libtommath/bn_mp_to_signed_bin.o \
|
||||
src/libtommath/bn_mp_to_signed_bin_n.o \
|
||||
src/libtommath/bn_mp_to_unsigned_bin.o \
|
||||
src/libtommath/bn_mp_to_unsigned_bin_n.o \
|
||||
src/libtommath/bn_mp_unsigned_bin_size.o \
|
||||
src/libtommath/bn_mp_xor.o \
|
||||
src/libtommath/bn_mp_zero.o \
|
||||
src/libtommath/bn_prime_tab.o \
|
||||
src/libtommath/bn_reverse.o \
|
||||
src/libtommath/bn_s_mp_add.o \
|
||||
src/libtommath/bn_s_mp_exptmod.o \
|
||||
src/libtommath/bn_s_mp_mul_digs.o \
|
||||
src/libtommath/bn_s_mp_mul_high_digs.o \
|
||||
src/libtommath/bn_s_mp_sqr.o \
|
||||
src/libtommath/bn_s_mp_sub.o \
|
||||
src/lzma/C/LzFind.o \
|
||||
src/lzma/C/LzmaDec.o \
|
||||
src/lzma/C/LzmaEnc.o \
|
||||
src/pklib/explode.o \
|
||||
src/pklib/implode.o \
|
||||
src/zlib/adler32.o \
|
||||
src/zlib/compress2.o \
|
||||
src/zlib/crc32.o \
|
||||
src/zlib/deflate.o \
|
||||
src/zlib/inffast.o \
|
||||
src/zlib/inflate.o \
|
||||
src/zlib/inftrees.o \
|
||||
src/zlib/trees.o \
|
||||
src/zlib/zutil.o \
|
||||
stormlib_dll/DllMain.o
|
||||
|
||||
all: $(LIBRARY)
|
||||
|
||||
#clean:
|
||||
# rm -f $(OBJS) $(LIBRARY)
|
||||
|
||||
#install: $(LIBRARY)
|
||||
# install $(LIBRARY) /usr/local/lib
|
||||
# mkdir -p /usr/local/include/StormLib
|
||||
# cp StormLib.h /usr/local/include/StormLib
|
||||
# cp StormPort.h /usr/local/include/StormLib
|
||||
|
||||
$(LIBRARY): $(OBJS_C) $(OBJS_CPP)
|
||||
$(CPP) $(CFLAGS) $(DFLAGS) -o $(LIBRARY) $(OBJS_C) $(OBJS_CPP) $(LFLAGS)
|
||||
$(AR) $(ARFLAGS) $(LIBRARY) $(OBJS_C) $(OBJS_CPP)
|
||||
|
||||
$(OBJS_C): %.o: %.c
|
||||
$(CC) -o $@ $(CFLAGS) $(DFLAGS) -c $<
|
||||
|
||||
$(OBJS_CPP): %.o: %.cpp
|
||||
$(CC) -o $@ $(CFLAGS) $(DFLAGS) -c $<
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* crc32.cpp Copyright (c) Ladislav Zezula 2007 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Implementation of CRC32 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 11.06.07 1.00 Lad The first version of crc32.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
static unsigned long crc32_table[] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||
};
|
||||
|
||||
|
||||
void CRC32_Init(crc32_context * ctx)
|
||||
{
|
||||
ctx->value = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
|
||||
void CRC32_Update(crc32_context * ctx, unsigned char * input, int ilen)
|
||||
{
|
||||
unsigned long value = ctx->value;
|
||||
|
||||
for(int i = 0; i < ilen; i++)
|
||||
{
|
||||
value = (value >> 0x08) ^ crc32_table[(value & 0xFF) ^ *input++];
|
||||
}
|
||||
|
||||
ctx->value = value;
|
||||
}
|
||||
|
||||
void CRC32_Finish(crc32_context * ctx, unsigned long * value)
|
||||
{
|
||||
*value = ctx->value ^ 0xFFFFFFFF;
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* crc32.h Copyright (c) Ladislav Zezula 2007 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 11.06.07 1.00 Lad The first version of crc32.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __CRC32_H__
|
||||
#define __CRC32_H__
|
||||
|
||||
struct crc32_context
|
||||
{
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
void CRC32_Init(crc32_context * ctx);
|
||||
void CRC32_Update(crc32_context * ctx, unsigned char *input, int ilen);
|
||||
void CRC32_Finish(crc32_context * ctx, unsigned long * value);
|
||||
|
||||
#endif // __CRC32_H__
|
||||
@ -1,252 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* md32.cpp Copyright (c) Ladislav Zezula 2007 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Implementation of MD5 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 11.06.07 1.00 Lad The first version of md5.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (little endian)
|
||||
*/
|
||||
#ifndef GET_UINT32_LE
|
||||
#define GET_UINT32_LE(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (unsigned long) (b)[(i) ] ) \
|
||||
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
|
||||
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
|
||||
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
|
||||
}
|
||||
#endif
|
||||
#ifndef PUT_UINT32_LE
|
||||
#define PUT_UINT32_LE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (unsigned char) ( (n) ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void md5_process( md5_context *ctx, unsigned char data[64] )
|
||||
{
|
||||
unsigned long X[16], A, B, C, D;
|
||||
|
||||
GET_UINT32_LE( X[0], data, 0 );
|
||||
GET_UINT32_LE( X[1], data, 4 );
|
||||
GET_UINT32_LE( X[2], data, 8 );
|
||||
GET_UINT32_LE( X[3], data, 12 );
|
||||
GET_UINT32_LE( X[4], data, 16 );
|
||||
GET_UINT32_LE( X[5], data, 20 );
|
||||
GET_UINT32_LE( X[6], data, 24 );
|
||||
GET_UINT32_LE( X[7], data, 28 );
|
||||
GET_UINT32_LE( X[8], data, 32 );
|
||||
GET_UINT32_LE( X[9], data, 36 );
|
||||
GET_UINT32_LE( X[10], data, 40 );
|
||||
GET_UINT32_LE( X[11], data, 44 );
|
||||
GET_UINT32_LE( X[12], data, 48 );
|
||||
GET_UINT32_LE( X[13], data, 52 );
|
||||
GET_UINT32_LE( X[14], data, 56 );
|
||||
GET_UINT32_LE( X[15], data, 60 );
|
||||
|
||||
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define P(a,b,c,d,k,s,t) \
|
||||
{ \
|
||||
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
|
||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||
|
||||
P( A, B, C, D, 0, 7, 0xD76AA478 );
|
||||
P( D, A, B, C, 1, 12, 0xE8C7B756 );
|
||||
P( C, D, A, B, 2, 17, 0x242070DB );
|
||||
P( B, C, D, A, 3, 22, 0xC1BDCEEE );
|
||||
P( A, B, C, D, 4, 7, 0xF57C0FAF );
|
||||
P( D, A, B, C, 5, 12, 0x4787C62A );
|
||||
P( C, D, A, B, 6, 17, 0xA8304613 );
|
||||
P( B, C, D, A, 7, 22, 0xFD469501 );
|
||||
P( A, B, C, D, 8, 7, 0x698098D8 );
|
||||
P( D, A, B, C, 9, 12, 0x8B44F7AF );
|
||||
P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
|
||||
P( B, C, D, A, 11, 22, 0x895CD7BE );
|
||||
P( A, B, C, D, 12, 7, 0x6B901122 );
|
||||
P( D, A, B, C, 13, 12, 0xFD987193 );
|
||||
P( C, D, A, B, 14, 17, 0xA679438E );
|
||||
P( B, C, D, A, 15, 22, 0x49B40821 );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (y ^ (z & (x ^ y)))
|
||||
|
||||
P( A, B, C, D, 1, 5, 0xF61E2562 );
|
||||
P( D, A, B, C, 6, 9, 0xC040B340 );
|
||||
P( C, D, A, B, 11, 14, 0x265E5A51 );
|
||||
P( B, C, D, A, 0, 20, 0xE9B6C7AA );
|
||||
P( A, B, C, D, 5, 5, 0xD62F105D );
|
||||
P( D, A, B, C, 10, 9, 0x02441453 );
|
||||
P( C, D, A, B, 15, 14, 0xD8A1E681 );
|
||||
P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
|
||||
P( A, B, C, D, 9, 5, 0x21E1CDE6 );
|
||||
P( D, A, B, C, 14, 9, 0xC33707D6 );
|
||||
P( C, D, A, B, 3, 14, 0xF4D50D87 );
|
||||
P( B, C, D, A, 8, 20, 0x455A14ED );
|
||||
P( A, B, C, D, 13, 5, 0xA9E3E905 );
|
||||
P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
|
||||
P( C, D, A, B, 7, 14, 0x676F02D9 );
|
||||
P( B, C, D, A, 12, 20, 0x8D2A4C8A );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
|
||||
P( A, B, C, D, 5, 4, 0xFFFA3942 );
|
||||
P( D, A, B, C, 8, 11, 0x8771F681 );
|
||||
P( C, D, A, B, 11, 16, 0x6D9D6122 );
|
||||
P( B, C, D, A, 14, 23, 0xFDE5380C );
|
||||
P( A, B, C, D, 1, 4, 0xA4BEEA44 );
|
||||
P( D, A, B, C, 4, 11, 0x4BDECFA9 );
|
||||
P( C, D, A, B, 7, 16, 0xF6BB4B60 );
|
||||
P( B, C, D, A, 10, 23, 0xBEBFBC70 );
|
||||
P( A, B, C, D, 13, 4, 0x289B7EC6 );
|
||||
P( D, A, B, C, 0, 11, 0xEAA127FA );
|
||||
P( C, D, A, B, 3, 16, 0xD4EF3085 );
|
||||
P( B, C, D, A, 6, 23, 0x04881D05 );
|
||||
P( A, B, C, D, 9, 4, 0xD9D4D039 );
|
||||
P( D, A, B, C, 12, 11, 0xE6DB99E5 );
|
||||
P( C, D, A, B, 15, 16, 0x1FA27CF8 );
|
||||
P( B, C, D, A, 2, 23, 0xC4AC5665 );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (y ^ (x | ~z))
|
||||
|
||||
P( A, B, C, D, 0, 6, 0xF4292244 );
|
||||
P( D, A, B, C, 7, 10, 0x432AFF97 );
|
||||
P( C, D, A, B, 14, 15, 0xAB9423A7 );
|
||||
P( B, C, D, A, 5, 21, 0xFC93A039 );
|
||||
P( A, B, C, D, 12, 6, 0x655B59C3 );
|
||||
P( D, A, B, C, 3, 10, 0x8F0CCC92 );
|
||||
P( C, D, A, B, 10, 15, 0xFFEFF47D );
|
||||
P( B, C, D, A, 1, 21, 0x85845DD1 );
|
||||
P( A, B, C, D, 8, 6, 0x6FA87E4F );
|
||||
P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
|
||||
P( C, D, A, B, 6, 15, 0xA3014314 );
|
||||
P( B, C, D, A, 13, 21, 0x4E0811A1 );
|
||||
P( A, B, C, D, 4, 6, 0xF7537E82 );
|
||||
P( D, A, B, C, 11, 10, 0xBD3AF235 );
|
||||
P( C, D, A, B, 2, 15, 0x2AD7D2BB );
|
||||
P( B, C, D, A, 9, 21, 0xEB86D391 );
|
||||
|
||||
#undef F
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 context setup
|
||||
*/
|
||||
|
||||
void MD5_Init( md5_context *ctx )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 process buffer
|
||||
*/
|
||||
void MD5_Update( md5_context *ctx, unsigned char *input, int ilen )
|
||||
{
|
||||
int fill;
|
||||
unsigned long left;
|
||||
|
||||
if( ilen <= 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (unsigned long) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, fill );
|
||||
md5_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
md5_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, ilen );
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char md5_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* MD5 final digest
|
||||
*/
|
||||
void MD5_Finish( md5_context *ctx, unsigned char output[16] )
|
||||
{
|
||||
unsigned long last, padn;
|
||||
unsigned long high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_LE( low, msglen, 0 );
|
||||
PUT_UINT32_LE( high, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
MD5_Update( ctx, (unsigned char *) md5_padding, padn );
|
||||
MD5_Update( ctx, msglen, 8 );
|
||||
|
||||
PUT_UINT32_LE( ctx->state[0], output, 0 );
|
||||
PUT_UINT32_LE( ctx->state[1], output, 4 );
|
||||
PUT_UINT32_LE( ctx->state[2], output, 8 );
|
||||
PUT_UINT32_LE( ctx->state[3], output, 12 );
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* md5.h Copyright (c) Ladislav Zezula 2007 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 11.06.07 1.00 Lad The first version of md5.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __MD5_H__
|
||||
#define __MD5_H__
|
||||
|
||||
// Functions for MD5
|
||||
struct md5_context
|
||||
{
|
||||
unsigned long total[2]; // number of bytes processed
|
||||
unsigned long state[4]; // intermediate digest state
|
||||
unsigned char buffer[64]; // data block being processed
|
||||
};
|
||||
|
||||
void MD5_Init(md5_context * ctx);
|
||||
void MD5_Update(md5_context * ctx, unsigned char *input, int ilen);
|
||||
void MD5_Finish(md5_context * ctx, unsigned char output[16]);
|
||||
|
||||
#endif // __MD5_H__
|
||||
@ -1,72 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* crc32.c Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Pkware Data Compression Library Version 1.11 */
|
||||
/* Dissassembled method crc32 - cdecl version */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 09.04.03 1.00 Lad The first version of crc32.c */
|
||||
/* 02.05.03 1.00 Lad Stress test done */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "pklib.h"
|
||||
|
||||
static char CopyRight[] = "PKWARE Data Compression Library for Win32\r\n"
|
||||
"Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
|
||||
"Patent No. 5,051,745\r\n"
|
||||
"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
|
||||
"Version 1.11\r\n";
|
||||
|
||||
static unsigned long crc_table[] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||
};
|
||||
|
||||
|
||||
unsigned long PKEXPORT crc32pk(char * buffer, unsigned int * psize, unsigned long * old_crc)
|
||||
{
|
||||
unsigned int size = *psize;
|
||||
unsigned long ch;
|
||||
unsigned long crc_value = *old_crc;
|
||||
|
||||
while(size-- != 0)
|
||||
{
|
||||
ch = *buffer++ ^ (char)crc_value;
|
||||
crc_value >>= 8;
|
||||
|
||||
crc_value = crc_table[ch & 0x0FF] ^ crc_value;
|
||||
}
|
||||
return crc_value;
|
||||
}
|
||||
@ -1,674 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* implode.c Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Implode function of PKWARE Data Compression library */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 11.04.03 1.00 Lad First version of implode.c */
|
||||
/* 02.05.03 1.00 Lad Stress test done */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pklib.h"
|
||||
|
||||
#if ((1200 < _MSC_VER) && (_MSC_VER < 1400))
|
||||
#pragma optimize("", off) // Fucking Microsoft VS.NET 2003 compiler !!!
|
||||
// (_MSC_VER=1310)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define DICT_OFFSET 0x204
|
||||
#define UNCMP_OFFSET (pWork->dsize_bytes + DICT_OFFSET)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tables
|
||||
|
||||
static unsigned char DistBits[] =
|
||||
{
|
||||
0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
|
||||
};
|
||||
|
||||
static unsigned char DistCode[] =
|
||||
{
|
||||
0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
|
||||
0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
|
||||
0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
|
||||
0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
|
||||
};
|
||||
|
||||
static unsigned char ExLenBits[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
|
||||
};
|
||||
|
||||
static unsigned char LenBits[] =
|
||||
{
|
||||
0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
|
||||
};
|
||||
|
||||
static unsigned char LenCode[] =
|
||||
{
|
||||
0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
|
||||
};
|
||||
|
||||
static unsigned char ChBitsAsc[] =
|
||||
{
|
||||
0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
|
||||
0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
|
||||
0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
|
||||
0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
|
||||
0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
|
||||
0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
|
||||
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
|
||||
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
|
||||
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||
0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
|
||||
0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
|
||||
};
|
||||
|
||||
static unsigned short ChCodeAsc[] =
|
||||
{
|
||||
0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
|
||||
0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
|
||||
0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
|
||||
0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
|
||||
0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
|
||||
0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
|
||||
0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
|
||||
0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
|
||||
0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
|
||||
0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
|
||||
0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
|
||||
0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
|
||||
0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
|
||||
0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
|
||||
0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
|
||||
0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
|
||||
0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
|
||||
0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
|
||||
0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
|
||||
0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
|
||||
0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
|
||||
0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
|
||||
0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
|
||||
0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
|
||||
0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
|
||||
0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
|
||||
0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
|
||||
0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
|
||||
0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
|
||||
0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
|
||||
0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
|
||||
0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local variables
|
||||
|
||||
static char Copyright[] = "PKWARE Data Compression Library for Win32\r\n"
|
||||
"Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
|
||||
"Patent No. 5,051,745\r\n"
|
||||
"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
|
||||
"Version 1.11\r\n";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
// Fills memory block with a character
|
||||
static void lmemset(void * buff, int c, size_t count)
|
||||
{
|
||||
memset(buff, c, count);
|
||||
}
|
||||
|
||||
// Copies memory block to another location
|
||||
static void lmemcpy(void * trg, const void * src, size_t count)
|
||||
{
|
||||
memcpy(trg, src, count);
|
||||
}
|
||||
|
||||
static void SortBuffer(TCmpStruct * pWork, unsigned char * uncmp_data, unsigned char * work_end)
|
||||
{
|
||||
unsigned short * pin0DC8;
|
||||
unsigned char * puncmp;
|
||||
unsigned long offs1, offs2;
|
||||
unsigned long ndwords;
|
||||
unsigned int add;
|
||||
|
||||
// Fill 0x480 dwords (0x1200 bytes)
|
||||
ndwords = (unsigned long)((pWork->out_buff - (char *)pWork->offs0DC8 + 1) >> 2);
|
||||
if(ndwords <= 1)
|
||||
ndwords = 1;
|
||||
memset(pWork->offs0DC8, 0, ndwords << 2);
|
||||
|
||||
for(puncmp = uncmp_data; work_end > puncmp; puncmp++)
|
||||
pWork->offs0DC8[(puncmp[0] * 4) + (puncmp[1] * 5)]++;
|
||||
|
||||
add = 0;
|
||||
for(pin0DC8 = pWork->offs0DC8; pin0DC8 < &pWork->offs1FC8; pin0DC8++)
|
||||
{
|
||||
add += *pin0DC8;
|
||||
*pin0DC8 = (unsigned short)add;
|
||||
}
|
||||
|
||||
for(work_end--; work_end >= uncmp_data; work_end--)
|
||||
{
|
||||
offs1 = (work_end[0] * 4) + (work_end[1] * 5); // EAX
|
||||
offs2 = (unsigned long)(work_end - pWork->work_buff); // EDI
|
||||
|
||||
pWork->offs0DC8[offs1]--;
|
||||
pWork->offs49D0[pWork->offs0DC8[offs1]] = (unsigned short)offs2;
|
||||
}
|
||||
}
|
||||
|
||||
static void FlushBuf(TCmpStruct * pWork)
|
||||
{
|
||||
unsigned char save_ch1;
|
||||
unsigned char save_ch2;
|
||||
unsigned int size = 0x800;
|
||||
|
||||
pWork->write_buf(pWork->out_buff, &size, pWork->param);
|
||||
|
||||
save_ch1 = pWork->out_buff[0x800];
|
||||
save_ch2 = pWork->out_buff[pWork->out_bytes];
|
||||
pWork->out_bytes -= 0x800;
|
||||
|
||||
lmemset(pWork->out_buff, 0, 0x802);
|
||||
|
||||
if(pWork->out_bytes != 0)
|
||||
pWork->out_buff[0] = save_ch1;
|
||||
if(pWork->out_bits != 0)
|
||||
pWork->out_buff[pWork->out_bytes] = save_ch2;
|
||||
}
|
||||
|
||||
static void OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)
|
||||
{
|
||||
unsigned int out_bits;
|
||||
|
||||
// If more than 8 bits to output, do recursion
|
||||
if(nbits > 8)
|
||||
{
|
||||
OutputBits(pWork, 8, bit_buff);
|
||||
bit_buff >>= 8;
|
||||
nbits -= 8;
|
||||
}
|
||||
|
||||
// Add bits to the last out byte in out_buff;
|
||||
out_bits = pWork->out_bits;
|
||||
pWork->out_buff[pWork->out_bytes] |= (unsigned char)(bit_buff << out_bits);
|
||||
pWork->out_bits += nbits;
|
||||
|
||||
// If 8 or more bits, increment number of bytes
|
||||
if(pWork->out_bits > 8)
|
||||
{
|
||||
pWork->out_bytes++;
|
||||
bit_buff >>= (8 - out_bits);
|
||||
|
||||
pWork->out_buff[pWork->out_bytes] = (unsigned char)bit_buff;
|
||||
pWork->out_bits &= 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
pWork->out_bits &= 7;
|
||||
if(pWork->out_bits == 0)
|
||||
pWork->out_bytes++;
|
||||
}
|
||||
|
||||
// If there is enough compressed bytes, flush them
|
||||
if(pWork->out_bytes >= 0x800)
|
||||
FlushBuf(pWork);
|
||||
}
|
||||
|
||||
static unsigned long FindRep(TCmpStruct * pWork, unsigned char * srcbuff)
|
||||
{
|
||||
unsigned short esp12;
|
||||
unsigned char * esp14;
|
||||
unsigned short esp18;
|
||||
unsigned char * srcbuff2;
|
||||
unsigned char esp20;
|
||||
|
||||
unsigned char * srcbuff3;
|
||||
unsigned short * pin0DC8;
|
||||
unsigned char * pin27CC;
|
||||
unsigned short * pin49D0;
|
||||
unsigned long nreps = 1; // EAX
|
||||
unsigned long ebx, esi;
|
||||
unsigned short di;
|
||||
|
||||
pin0DC8 = pWork->offs0DC8 + (srcbuff[0] * 4) + (srcbuff[1] * 5);
|
||||
esi = (unsigned long)(srcbuff - pWork->dsize_bytes - pWork->work_buff + 1);
|
||||
esp18 = *pin0DC8;
|
||||
pin49D0 = pWork->offs49D0 + esp18;
|
||||
|
||||
if(*pin49D0 < esi)
|
||||
{
|
||||
while(*pin49D0 < esi)
|
||||
{
|
||||
pin49D0++;
|
||||
esp18++;
|
||||
}
|
||||
*pin0DC8 = esp18;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
srcbuff2 = srcbuff - 1;
|
||||
pin49D0 = pWork->offs49D0 + esp18;
|
||||
pin27CC = pWork->work_buff + *pin49D0;
|
||||
if(srcbuff2 <= pin27CC)
|
||||
return 0;
|
||||
//---------------------------------------------------------------------------
|
||||
srcbuff3 = srcbuff;
|
||||
for(;;)
|
||||
{
|
||||
if(srcbuff3[nreps-1] == pin27CC[nreps-1] && *srcbuff3 == *pin27CC)
|
||||
{
|
||||
//
|
||||
// The following code does not work when compiled with MSVC.NET 2003
|
||||
// optimizing compiler. We have to switch the optimizations off to make it work
|
||||
// I found that in debug version (where the optimizations are off), the value
|
||||
// of "pin27CC" gets incremented twice (once at below, once in the "for" loop)
|
||||
//
|
||||
|
||||
pin27CC++;
|
||||
srcbuff3++;
|
||||
|
||||
for(ebx = 2; ebx < DICT_OFFSET; ebx++)
|
||||
{
|
||||
pin27CC++;
|
||||
srcbuff3++;
|
||||
if(*pin27CC != *srcbuff3)
|
||||
break;
|
||||
}
|
||||
|
||||
srcbuff3 = srcbuff;
|
||||
if(ebx >= nreps)
|
||||
{
|
||||
pWork->offs0000 = (unsigned int)(srcbuff3 - pin27CC + ebx - 1);
|
||||
if((nreps = ebx) > 10)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pin49D0++;
|
||||
esp18++;
|
||||
pin27CC = pWork->work_buff + *pin49D0;
|
||||
|
||||
if(srcbuff2 > pin27CC)
|
||||
continue;
|
||||
|
||||
return (nreps >= 2) ? nreps : 0;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
if(ebx == DICT_OFFSET)
|
||||
{
|
||||
pWork->offs0000--;
|
||||
return ebx;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
pin49D0 = pWork->offs49D0 + esp18;
|
||||
if(pWork->work_buff + pin49D0[1] >= srcbuff2)
|
||||
return nreps;
|
||||
//---------------------------------------------------------------------------
|
||||
di = 0;
|
||||
pWork->offs09BC[0] = 0xFFFF;
|
||||
pWork->offs09BC[1] = di;
|
||||
esp12 = 1;
|
||||
|
||||
do
|
||||
{
|
||||
esi = di;
|
||||
if(srcbuff[esp12] != srcbuff[esi])
|
||||
{
|
||||
di = pWork->offs09BC[esi];
|
||||
if(di != 0xFFFF)
|
||||
continue;
|
||||
}
|
||||
pWork->offs09BC[++esp12] = ++di;
|
||||
}
|
||||
while(esp12 < nreps);
|
||||
//---------------------------------------------------------------------------
|
||||
esi = nreps;
|
||||
pin27CC = pWork->work_buff + pin49D0[0] + nreps;
|
||||
esp14 = pin27CC;
|
||||
|
||||
for(;;) // 0040268B
|
||||
{
|
||||
esi = pWork->offs09BC[esi];
|
||||
if(esi == 0xFFFF)
|
||||
esi = 0;
|
||||
|
||||
pin49D0 = pWork->offs49D0 + esp18;
|
||||
do
|
||||
{
|
||||
pin49D0++;
|
||||
esp18++;
|
||||
pin27CC = pWork->work_buff + pin49D0[0];
|
||||
if(pin27CC >= srcbuff2)
|
||||
return nreps;
|
||||
}
|
||||
while(pin27CC + esi < esp14);
|
||||
//---------------------------------------------------------------------------
|
||||
esp20 = srcbuff[nreps - 2];
|
||||
if(esp20 == pin27CC[nreps - 2])
|
||||
{
|
||||
if(pin27CC + esi != esp14)
|
||||
{
|
||||
esp14 = pin27CC;
|
||||
esi = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pin49D0 = pWork->offs49D0 + esp18;
|
||||
do
|
||||
{
|
||||
pin49D0++;
|
||||
esp18++;
|
||||
pin27CC = pWork->work_buff + pin49D0[0];
|
||||
if(pin27CC >= srcbuff2)
|
||||
return nreps;
|
||||
}
|
||||
while(pin27CC[nreps - 2] != esp20 || pin27CC[0] != *srcbuff);
|
||||
|
||||
esp14 = pin27CC + 2;
|
||||
esi = 2;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
for(; esp14[0] == srcbuff[esi]; esp14++)
|
||||
{
|
||||
if(++esi >= DICT_OFFSET)
|
||||
break;
|
||||
}
|
||||
|
||||
if(esi < nreps)
|
||||
continue;
|
||||
pWork->offs0000 = (unsigned int)(srcbuff - pin27CC - 1);
|
||||
if(esi <= nreps)
|
||||
continue;
|
||||
nreps = esi;
|
||||
if(esi == DICT_OFFSET)
|
||||
return nreps;
|
||||
|
||||
do
|
||||
{
|
||||
if(srcbuff[esp12] != srcbuff[di])
|
||||
{
|
||||
di = pWork->offs09BC[di];
|
||||
if(di != 0xFFFF)
|
||||
continue;
|
||||
}
|
||||
pWork->offs09BC[++esp12] = ++di;
|
||||
}
|
||||
while(esp12 < esi);
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteCmpData(TCmpStruct * pWork)
|
||||
{
|
||||
unsigned int nreps = 0; // ESP+10 : Number of repeats
|
||||
unsigned char * uncmp_end; // ESP+14 : End of uncompressed data
|
||||
unsigned int esp18 = 0; // ESP+18 :
|
||||
unsigned int bytes_required; // ESP+1C : Number of bytes required to read
|
||||
unsigned int esp20 = 0; // ESP+20 :
|
||||
unsigned char * uncmp_begin = pWork->work_buff + UNCMP_OFFSET; // EDI
|
||||
unsigned long nreps1;
|
||||
unsigned long save_offs0000 = 0;
|
||||
|
||||
// Store the compression type and dictionary size
|
||||
pWork->out_buff[0] = (char)pWork->ctype;
|
||||
pWork->out_buff[1] = (char)pWork->dsize_bits;
|
||||
pWork->out_bytes = 2;
|
||||
|
||||
// Reset output buffer to zero
|
||||
lmemset(&pWork->out_buff[2], 0, sizeof(pWork->out_buff) - 2);
|
||||
pWork->out_bits = 0;
|
||||
|
||||
do
|
||||
{
|
||||
int total_loaded = 0;
|
||||
|
||||
for(bytes_required = 0x1000; bytes_required != 0; )
|
||||
{
|
||||
int loaded = pWork->read_buf((char *)pWork->work_buff + UNCMP_OFFSET + total_loaded,
|
||||
&bytes_required, pWork->param);
|
||||
|
||||
if(loaded == 0)
|
||||
{
|
||||
if(total_loaded == 0 && esp20 == 0)
|
||||
goto __Exit;
|
||||
esp18 = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
total_loaded += loaded;
|
||||
bytes_required -= loaded;
|
||||
}
|
||||
}
|
||||
|
||||
uncmp_end = pWork->work_buff + pWork->dsize_bytes + total_loaded;
|
||||
if(esp18 != 0)
|
||||
uncmp_end += DICT_OFFSET;
|
||||
|
||||
//
|
||||
// Warning: Passing "uncmp_end + 1" to the SortBuffer function may cause
|
||||
// the output to be unpredictable in Storm.dll's compression. Because Storm.dll
|
||||
// does not pass the zeroed buffer to the "implode" function, the byte after
|
||||
// uncmp_end contains random data. This causes difference within dictionary
|
||||
// created in SortBuffer function and may also cause different compressed output.
|
||||
// We always zero the data before compression, so this thing never occurs.
|
||||
// Funny is that it is actually not a bug, because if we decompress the data back,
|
||||
// we'll get the identical data with the original input.
|
||||
//
|
||||
switch(esp20)
|
||||
{
|
||||
case 0:
|
||||
SortBuffer(pWork, uncmp_begin, uncmp_end + 1);
|
||||
esp20++;
|
||||
if(pWork->dsize_bytes != 0x1000)
|
||||
esp20++;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes + DICT_OFFSET, uncmp_end + 1);
|
||||
esp20++;
|
||||
break;
|
||||
|
||||
default:
|
||||
SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes, uncmp_end + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
while(uncmp_end > uncmp_begin)
|
||||
{
|
||||
nreps1 = FindRep(pWork, uncmp_begin);
|
||||
while(nreps1 != 0)
|
||||
{
|
||||
if(nreps1 == 2 && pWork->offs0000 >= 0x100)
|
||||
break;
|
||||
|
||||
if(esp18 != 0 && uncmp_begin + nreps1 > uncmp_end)
|
||||
goto _004022DB;
|
||||
|
||||
if(nreps1 >= 8 || uncmp_begin + 1 >= uncmp_end)
|
||||
goto _004022FF;
|
||||
|
||||
save_offs0000 = pWork->offs0000; // ebp
|
||||
nreps = nreps1;
|
||||
nreps1 = FindRep(pWork, uncmp_begin + 1);
|
||||
|
||||
if(nreps >= nreps1)
|
||||
goto _004022F9;
|
||||
|
||||
if(nreps + 1 >= nreps1 && save_offs0000 <= 0x80)
|
||||
goto _004022F9;
|
||||
|
||||
OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
|
||||
uncmp_begin++;
|
||||
}
|
||||
|
||||
_0040222F:
|
||||
OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
|
||||
uncmp_begin++;
|
||||
_00402252:;
|
||||
}
|
||||
|
||||
if(esp18 == 0)
|
||||
{
|
||||
uncmp_begin -= 0x1000;
|
||||
lmemcpy(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + DICT_OFFSET);
|
||||
}
|
||||
}
|
||||
while(esp18 == 0);
|
||||
|
||||
__Exit:
|
||||
OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
|
||||
if(pWork->out_bits != 0)
|
||||
pWork->out_bytes++;
|
||||
pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
|
||||
return;
|
||||
|
||||
_004022DB:
|
||||
nreps1 = (unsigned long)(uncmp_end - uncmp_begin);
|
||||
if(nreps1 < 2)
|
||||
goto _0040222F;
|
||||
|
||||
if(nreps1 != 2 || pWork->offs0000 < 0x100)
|
||||
goto _004022FF;
|
||||
goto _0040222F;
|
||||
|
||||
_004022F9:
|
||||
nreps1 = nreps;
|
||||
pWork->offs0000 = save_offs0000;
|
||||
|
||||
_004022FF:
|
||||
OutputBits(pWork, pWork->nChBits[nreps1 + 0xFE], pWork->nChCodes[nreps1 + 0xFE]);
|
||||
|
||||
if(nreps1 == 2)
|
||||
{
|
||||
OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> 2],
|
||||
pWork->dist_codes[pWork->offs0000 >> 2]);
|
||||
OutputBits(pWork, 2, pWork->offs0000 & 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> pWork->dsize_bits],
|
||||
pWork->dist_codes[pWork->offs0000 >> pWork->dsize_bits]);
|
||||
OutputBits(pWork, pWork->dsize_bits, pWork->dsize_mask & pWork->offs0000);
|
||||
}
|
||||
uncmp_begin += nreps1;
|
||||
goto _00402252;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main imploding function
|
||||
|
||||
unsigned int PKEXPORT implode(
|
||||
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
|
||||
void (*write_buf)(char *buf, unsigned int *size, void *param),
|
||||
char *work_buf,
|
||||
void *param,
|
||||
unsigned int *type,
|
||||
unsigned int *dsize)
|
||||
{
|
||||
TCmpStruct * pWork = (TCmpStruct *)work_buf;
|
||||
unsigned int nChCode;
|
||||
unsigned int nCount;
|
||||
unsigned int i;
|
||||
|
||||
// Initialize the work buffer. This is not in the Pklib,
|
||||
// but it seems to be a bug. Storm always pre-fills the data with zeros,
|
||||
// and always compresses one block only. So the bug will not appear.
|
||||
// But when a larger data block (size > 0x1000) is compressed,
|
||||
// it may fail.
|
||||
memset(pWork, 0, sizeof(TCmpStruct));
|
||||
|
||||
// Fill the work buffer information
|
||||
pWork->read_buf = read_buf;
|
||||
pWork->write_buf = write_buf;
|
||||
pWork->dsize_bytes = *dsize;
|
||||
pWork->ctype = *type;
|
||||
pWork->param = param;
|
||||
pWork->dsize_bits = 4;
|
||||
pWork->dsize_mask = 0x0F;
|
||||
|
||||
// Test dictionary size
|
||||
switch(*dsize)
|
||||
{
|
||||
case 0x1000 :
|
||||
pWork->dsize_bits++;
|
||||
pWork->dsize_mask |= 0x20;
|
||||
// No break here !!!
|
||||
|
||||
case 0x0800 :
|
||||
pWork->dsize_bits++;
|
||||
pWork->dsize_mask |= 0x10;
|
||||
// No break here !!!
|
||||
|
||||
case 0x0400 :
|
||||
break;
|
||||
|
||||
default:
|
||||
return CMP_INVALID_DICTSIZE;
|
||||
}
|
||||
|
||||
// Test the compression type
|
||||
switch(*type)
|
||||
{
|
||||
case CMP_BINARY: // We will compress data with binary compression type
|
||||
for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++)
|
||||
{
|
||||
pWork->nChBits[nCount] = 9;
|
||||
pWork->nChCodes[nCount] = (unsigned short)nChCode;
|
||||
nChCode = (nChCode & 0x0000FFFF) + 2;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case CMP_ASCII: // We will compress data with ASCII compression type
|
||||
for(nCount = 0; nCount < 0x100; nCount++)
|
||||
{
|
||||
pWork->nChBits[nCount] = (unsigned char )(ChBitsAsc[nCount] + 1);
|
||||
pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return CMP_INVALID_MODE;
|
||||
}
|
||||
|
||||
for(i = 0; i < 0x10; i++)
|
||||
{
|
||||
int nCount2 = 0; // EBX
|
||||
|
||||
if((1 << ExLenBits[i]) == 0)
|
||||
continue;
|
||||
|
||||
do
|
||||
{
|
||||
pWork->nChBits[nCount] = (unsigned char)(ExLenBits[i] + LenBits[i] + 1);
|
||||
pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1);
|
||||
|
||||
nCount2++;
|
||||
nCount++;
|
||||
}
|
||||
while((1 << ExLenBits[i]) > nCount2);
|
||||
}
|
||||
|
||||
// Copy the distance codes and distance bits and perform the compression
|
||||
lmemcpy(&pWork->dist_codes, DistCode, sizeof(DistCode));
|
||||
lmemcpy(&pWork->dist_bits, DistBits, sizeof(DistBits));
|
||||
WriteCmpData(pWork);
|
||||
return CMP_NO_ERROR;
|
||||
}
|
||||
@ -1,141 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* pklib.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Header file for PKWARE Data Compression Library */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 31.03.03 1.00 Lad The first version of pkware.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __PKLIB_H__
|
||||
#define __PKLIB_H__
|
||||
|
||||
#include "../StormPort.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define CMP_BINARY 0 // Binary compression
|
||||
#define CMP_ASCII 1 // Ascii compression
|
||||
|
||||
#define CMP_NO_ERROR 0
|
||||
#define CMP_INVALID_DICTSIZE 1
|
||||
#define CMP_INVALID_MODE 2
|
||||
#define CMP_BAD_DATA 3
|
||||
#define CMP_ABORT 4
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Define calling convention
|
||||
|
||||
#ifndef PKEXPORT
|
||||
#ifdef WIN32
|
||||
#define PKEXPORT __cdecl // Use for normal __cdecl calling
|
||||
#else
|
||||
#define PKEXPORT
|
||||
#endif
|
||||
#endif
|
||||
//#define PKEXPORT __stdcall
|
||||
//#define PKEXPORT __fastcall
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Internal structures
|
||||
|
||||
// Compression structure
|
||||
typedef struct
|
||||
{
|
||||
unsigned int offs0000; // 0000 :
|
||||
unsigned int out_bytes; // 0004 : # bytes available in out_buff
|
||||
unsigned int out_bits; // 0008 : # of bits available in the last out byte
|
||||
unsigned int dsize_bits; // 000C : Dict size : 4=0x400, 5=0x800, 6=0x1000
|
||||
unsigned int dsize_mask; // 0010 : Dict size : 0x0F=0x400, 0x1F=0x800, 0x3F=0x1000
|
||||
unsigned int ctype; // 0014 : Compression type (Ascii or binary)
|
||||
unsigned int dsize_bytes; // 0018 : Dictionary size in bytes
|
||||
unsigned char dist_bits[0x40]; // 001C : Distance bits
|
||||
unsigned char dist_codes[0x40]; // 005C : Distance codes
|
||||
unsigned char nChBits[0x306]; // 009C :
|
||||
unsigned short nChCodes[0x306]; // 03A2 :
|
||||
unsigned short offs09AE; // 09AE :
|
||||
|
||||
void * param; // 09B0 : User parameter
|
||||
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 9B4
|
||||
void (*write_buf)(char *buf, unsigned int *size, void *param); // 9B8
|
||||
|
||||
unsigned short offs09BC[0x204]; // 09BC :
|
||||
unsigned long offs0DC4; // 0DC4 :
|
||||
unsigned short offs0DC8[0x900]; // 0DC8 :
|
||||
unsigned short offs1FC8; // 1FC8 :
|
||||
char out_buff[0x802]; // 1FCA : Output (compressed) data
|
||||
unsigned char work_buff[0x2204]; // 27CC : Work buffer
|
||||
// + DICT_OFFSET => Dictionary
|
||||
// + UNCMP_OFFSET => Uncompressed data
|
||||
unsigned short offs49D0[0x2000]; // 49D0 :
|
||||
} TCmpStruct;
|
||||
|
||||
#define CMP_BUFFER_SIZE sizeof(TCmpStruct) // Size of compression buffer
|
||||
|
||||
|
||||
// Decompression structure
|
||||
typedef struct
|
||||
{
|
||||
unsigned long offs0000; // 0000
|
||||
unsigned long ctype; // 0004 - Compression type (CMP_BINARY or CMP_ASCII)
|
||||
unsigned long outputPos; // 0008 - Position in output buffer
|
||||
unsigned long dsize_bits; // 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000)
|
||||
unsigned long dsize_mask; // 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000)
|
||||
unsigned long bit_buff; // 0014 - 16-bit buffer for processing input data
|
||||
unsigned long extra_bits; // 0018 - Number of extra (above 8) bits in bit buffer
|
||||
unsigned int in_pos; // 001C - Position in in_buff
|
||||
unsigned long in_bytes; // 0020 - Number of bytes in input buffer
|
||||
void * param; // 0024 - Custom parameter
|
||||
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 0028
|
||||
void (*write_buf)(char *buf, unsigned int *size, void *param);// 002C
|
||||
unsigned char out_buff[0x2000]; // 0030 - Output circle buffer. Starting position is 0x1000
|
||||
unsigned char offs2030[0x204]; // 2030 - ???
|
||||
unsigned char in_buff[0x800]; // 2234 - Buffer for data to be decompressed
|
||||
unsigned char position1[0x100]; // 2A34 - Positions in buffers
|
||||
unsigned char position2[0x100]; // 2B34 - Positions in buffers
|
||||
unsigned char offs2C34[0x100]; // 2C34 - Buffer for
|
||||
unsigned char offs2D34[0x100]; // 2D34 - Buffer for
|
||||
unsigned char offs2E34[0x80]; // 2EB4 - Buffer for
|
||||
unsigned char offs2EB4[0x100]; // 2EB4 - Buffer for
|
||||
unsigned char ChBitsAsc[0x100]; // 2FB4 - Buffer for
|
||||
unsigned char DistBits[0x40]; // 30B4 - Numbers of bytes to skip copied block length
|
||||
unsigned char LenBits[0x10]; // 30F4 - Numbers of bits for skip copied block length
|
||||
unsigned char ExLenBits[0x10]; // 3104 - Number of valid bits for copied block
|
||||
unsigned short LenBase[0x10]; // 3114 - Buffer for
|
||||
} TDcmpStruct;
|
||||
|
||||
#define EXP_BUFFER_SIZE sizeof(TDcmpStruct) // Size of decompress buffer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
unsigned int PKEXPORT implode(
|
||||
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
|
||||
void (*write_buf)(char *buf, unsigned int *size, void *param),
|
||||
char *work_buf,
|
||||
void *param,
|
||||
unsigned int *type,
|
||||
unsigned int *dsize);
|
||||
|
||||
|
||||
unsigned int PKEXPORT explode(
|
||||
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
|
||||
void (*write_buf)(char *buf, unsigned int *size, void *param),
|
||||
char *work_buf,
|
||||
void *param);
|
||||
|
||||
// The original name "crc32" was changed to "crc32pk" due
|
||||
// to compatibility with zlib
|
||||
unsigned long PKEXPORT crc32pk(char *buffer, unsigned int *size, unsigned long *old_crc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // End of 'extern "C"' declaration
|
||||
#endif
|
||||
|
||||
#endif // __PKLIB_H__
|
||||
1860
src/dep/src/StormLib/src/FileStream.cpp
Normal file
1860
src/dep/src/StormLib/src/FileStream.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1616
src/dep/src/StormLib/src/SBaseCommon.cpp
Normal file
1616
src/dep/src/StormLib/src/SBaseCommon.cpp
Normal file
File diff suppressed because it is too large
Load Diff
144
src/dep/src/StormLib/src/SBaseDumpData.cpp
Normal file
144
src/dep/src/StormLib/src/SBaseDumpData.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/*****************************************************************************/
|
||||
/* SBaseDumpData.cpp Copyright (c) Ladislav Zezula 2011 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 26.01.11 1.00 Lad The first version of SBaseDumpData.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
#ifdef __STORMLIB_DUMP_DATA__
|
||||
|
||||
void DumpMpqHeader(TMPQHeader * pHeader)
|
||||
{
|
||||
printf("== MPQ Header =================================\n");
|
||||
printf("DWORD dwID = %08lX\n", pHeader->dwID);
|
||||
printf("DWORD dwHeaderSize = %08lX\n", pHeader->dwHeaderSize);
|
||||
printf("DWORD dwArchiveSize = %08lX\n", pHeader->dwArchiveSize);
|
||||
printf("USHORT wFormatVersion = %04lX\n", pHeader->wFormatVersion);
|
||||
printf("USHORT wSectorSize = %04lX\n", pHeader->wSectorSize);
|
||||
printf("DWORD dwHashTablePos = %08lX\n", pHeader->dwHashTablePos);
|
||||
printf("DWORD dwBlockTablePos = %08lX\n", pHeader->dwBlockTablePos);
|
||||
printf("DWORD dwHashTableSize = %08lX\n", pHeader->dwHashTableSize);
|
||||
printf("DWORD dwBlockTableSize = %08lX\n", pHeader->dwBlockTableSize);
|
||||
printf("ULONGLONG HiBlockTablePos64 = %016llX\n", pHeader->HiBlockTablePos64);
|
||||
printf("USHORT wHashTablePosHi = %04lX\n", pHeader->wHashTablePosHi);
|
||||
printf("USHORT wBlockTablePosHi = %04lX\n", pHeader->wBlockTablePosHi);
|
||||
printf("ULONGLONG ArchiveSize64 = %016llX\n", pHeader->ArchiveSize64);
|
||||
printf("ULONGLONG BetTablePos64 = %016llX\n", pHeader->BetTablePos64);
|
||||
printf("ULONGLONG HetTablePos64 = %016llX\n", pHeader->HetTablePos64);
|
||||
printf("ULONGLONG HashTableSize64 = %016llX\n", pHeader->HashTableSize64);
|
||||
printf("ULONGLONG BlockTableSize64 = %016llX\n", pHeader->BlockTableSize64);
|
||||
printf("ULONGLONG HiBlockTableSize64 = %016llX\n", pHeader->HiBlockTableSize64);
|
||||
printf("ULONGLONG HetTableSize64 = %016llX\n", pHeader->HetTableSize64);
|
||||
printf("ULONGLONG BetTableSize64 = %016llX\n", pHeader->BetTableSize64);
|
||||
printf("DWORD dwRawChunkSize = %08lX\n", pHeader->dwRawChunkSize);
|
||||
printf("-----------------------------------------------\n\n");
|
||||
}
|
||||
|
||||
void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if(pHetTable == NULL || pBetTable == NULL)
|
||||
return;
|
||||
|
||||
printf("== HET Header =================================\n");
|
||||
printf("ULONGLONG AndMask64 = %016llX\n", pHetTable->AndMask64);
|
||||
printf("ULONGLONG OrMask64 = %016llX\n", pHetTable->OrMask64);
|
||||
printf("DWORD dwIndexSizeTotal = %08lX\n", pHetTable->dwIndexSizeTotal);
|
||||
printf("DWORD dwIndexSizeExtra = %08lX\n", pHetTable->dwIndexSizeExtra);
|
||||
printf("DWORD dwIndexSize = %08lX\n", pHetTable->dwIndexSize);
|
||||
printf("DWORD dwMaxFileCount = %08lX\n", pHetTable->dwMaxFileCount);
|
||||
printf("DWORD dwHashTableSize = %08lX\n", pHetTable->dwHashTableSize);
|
||||
printf("DWORD dwHashBitSize = %08lX\n", pHetTable->dwHashBitSize);
|
||||
printf("-----------------------------------------------\n\n");
|
||||
|
||||
printf("== BET Header =================================\n");
|
||||
printf("DWORD dwTableEntrySize = %08lX\n", pBetTable->dwTableEntrySize);
|
||||
printf("DWORD dwBitIndex_FilePos = %08lX\n", pBetTable->dwBitIndex_FilePos);
|
||||
printf("DWORD dwBitIndex_FileSize = %08lX\n", pBetTable->dwBitIndex_FileSize);
|
||||
printf("DWORD dwBitIndex_CmpSize = %08lX\n", pBetTable->dwBitIndex_CmpSize);
|
||||
printf("DWORD dwBitIndex_FlagIndex = %08lX\n", pBetTable->dwBitIndex_FlagIndex);
|
||||
printf("DWORD dwBitIndex_Unknown = %08lX\n", pBetTable->dwBitIndex_Unknown);
|
||||
printf("DWORD dwBitCount_FilePos = %08lX\n", pBetTable->dwBitCount_FilePos);
|
||||
printf("DWORD dwBitCount_FileSize = %08lX\n", pBetTable->dwBitCount_FileSize);
|
||||
printf("DWORD dwBitCount_CmpSize = %08lX\n", pBetTable->dwBitCount_CmpSize);
|
||||
printf("DWORD dwBitCount_FlagIndex = %08lX\n", pBetTable->dwBitCount_FlagIndex);
|
||||
printf("DWORD dwBitCount_Unknown = %08lX\n", pBetTable->dwBitCount_Unknown);
|
||||
printf("DWORD dwBetHashSizeTotal = %08lX\n", pBetTable->dwBetHashSizeTotal);
|
||||
printf("DWORD dwBetHashSizeExtra = %08lX\n", pBetTable->dwBetHashSizeExtra);
|
||||
printf("DWORD dwBetHashSize = %08lX\n", pBetTable->dwBetHashSize);
|
||||
printf("DWORD dwMaxFileCount = %08lX\n", pBetTable->dwMaxFileCount);
|
||||
printf("DWORD dwFlagCount = %08lX\n", pBetTable->dwFlagCount);
|
||||
printf("-----------------------------------------------\n\n");
|
||||
|
||||
printf("== HET & Bet Table ======================================================================\n\n");
|
||||
printf("HetIdx HetHash BetIdx BetHash ByteOffset FileSize CmpSize FlgIdx Flags \n");
|
||||
printf("------ ------- ------ ---------------- ---------------- -------- -------- ------ --------\n");
|
||||
for(i = 0; i < pHetTable->dwHashTableSize; i++)
|
||||
{
|
||||
ULONGLONG ByteOffset = 0;
|
||||
ULONGLONG BetHash = 0;
|
||||
DWORD dwFileSize = 0;
|
||||
DWORD dwCmpSize = 0;
|
||||
DWORD dwFlagIndex = 0;
|
||||
DWORD dwFlags = 0;
|
||||
DWORD dwBetIndex = 0;
|
||||
|
||||
pHetTable->pBetIndexes->GetBits(i * pHetTable->dwIndexSizeTotal,
|
||||
pHetTable->dwIndexSize,
|
||||
&dwBetIndex,
|
||||
4);
|
||||
|
||||
if(dwBetIndex < pHetTable->dwMaxFileCount)
|
||||
{
|
||||
DWORD dwEntryIndex = pBetTable->dwTableEntrySize * dwBetIndex;
|
||||
|
||||
pBetTable->pBetHashes->GetBits(dwBetIndex * pBetTable->dwBetHashSizeTotal,
|
||||
pBetTable->dwBetHashSize,
|
||||
&BetHash,
|
||||
8);
|
||||
|
||||
pBetTable->pFileTable->GetBits(dwEntryIndex + pBetTable->dwBitIndex_FilePos,
|
||||
pBetTable->dwBitCount_FilePos,
|
||||
&ByteOffset,
|
||||
8);
|
||||
|
||||
pBetTable->pFileTable->GetBits(dwEntryIndex + pBetTable->dwBitIndex_FileSize,
|
||||
pBetTable->dwBitCount_FileSize,
|
||||
&dwFileSize,
|
||||
4);
|
||||
|
||||
pBetTable->pFileTable->GetBits(dwEntryIndex + pBetTable->dwBitIndex_CmpSize,
|
||||
pBetTable->dwBitCount_CmpSize,
|
||||
&dwCmpSize,
|
||||
4);
|
||||
|
||||
pBetTable->pFileTable->GetBits(dwEntryIndex + pBetTable->dwBitIndex_FlagIndex,
|
||||
pBetTable->dwBitCount_FlagIndex,
|
||||
&dwFlagIndex,
|
||||
4);
|
||||
|
||||
dwFlags = pBetTable->pFileFlags[dwFlagIndex];
|
||||
}
|
||||
|
||||
printf(" %04lX %02lX %04lX %016llX %016llX %08lX %08lX %04lX %08lX\n", i,
|
||||
pHetTable->pHetHashes[i],
|
||||
dwBetIndex,
|
||||
BetHash,
|
||||
ByteOffset,
|
||||
dwFileSize,
|
||||
dwCmpSize,
|
||||
dwFlagIndex,
|
||||
dwFlags);
|
||||
}
|
||||
printf("-----------------------------------------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
#endif // __STORMLIB_DUMP_DATA__
|
||||
2466
src/dep/src/StormLib/src/SBaseFileTable.cpp
Normal file
2466
src/dep/src/StormLib/src/SBaseFileTable.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1050
src/dep/src/StormLib/src/SCompression.cpp
Normal file
1050
src/dep/src/StormLib/src/SCompression.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1211
src/dep/src/StormLib/src/SFileAddFile.cpp
Normal file
1211
src/dep/src/StormLib/src/SFileAddFile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
392
src/dep/src/StormLib/src/SFileAttributes.cpp
Normal file
392
src/dep/src/StormLib/src/SFileAttributes.cpp
Normal file
@ -0,0 +1,392 @@
|
||||
/*****************************************************************************/
|
||||
/* SAttrFile.cpp Copyright (c) Ladislav Zezula 2007 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 12.06.04 1.00 Lad The first version of SAttrFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local structures
|
||||
|
||||
typedef struct _MPQ_ATTRIBUTES_HEADER
|
||||
{
|
||||
DWORD dwVersion; // Version of the (attributes) file. Must be 100 (0x64)
|
||||
DWORD dwFlags; // See MPQ_ATTRIBUTE_XXXX
|
||||
|
||||
// Followed by an array of CRC32
|
||||
// Followed by an array of file times
|
||||
// Followed by an array of MD5
|
||||
} MPQ_ATTRIBUTES_HEADER, *PMPQ_ATTRIBUTES_HEADER;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions (internal use by StormLib)
|
||||
|
||||
int SAttrLoadAttributes(TMPQArchive * ha)
|
||||
{
|
||||
MPQ_ATTRIBUTES_HEADER AttrHeader;
|
||||
TMPQFile * hf;
|
||||
HANDLE hFile = NULL;
|
||||
DWORD dwBlockTableSize = ha->pHeader->dwBlockTableSize;
|
||||
DWORD dwArraySize;
|
||||
DWORD dwBytesRead;
|
||||
DWORD i;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// File table must be initialized
|
||||
assert(ha->pFileTable != NULL);
|
||||
|
||||
// Attempt to open the "(attributes)" file.
|
||||
// If it's not there, then the archive doesn't support attributes
|
||||
if(SFileOpenFileEx((HANDLE)ha, ATTRIBUTES_NAME, SFILE_OPEN_ANY_LOCALE, &hFile))
|
||||
{
|
||||
// Remember the flags for (attributes)
|
||||
hf = (TMPQFile *)hFile;
|
||||
ha->dwFileFlags2 = hf->pFileEntry->dwFlags;
|
||||
|
||||
// Load the content of the attributes file
|
||||
SFileReadFile(hFile, &AttrHeader, sizeof(MPQ_ATTRIBUTES_HEADER), &dwBytesRead, NULL);
|
||||
AttrHeader.dwVersion = BSWAP_INT32_UNSIGNED(AttrHeader.dwVersion);
|
||||
AttrHeader.dwFlags = BSWAP_INT32_UNSIGNED(AttrHeader.dwFlags);
|
||||
ha->dwAttrFlags = AttrHeader.dwFlags;
|
||||
if(dwBytesRead != sizeof(MPQ_ATTRIBUTES_HEADER))
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
// Verify format of the attributes
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(AttrHeader.dwVersion > MPQ_ATTRIBUTES_V1)
|
||||
nError = ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Load the CRC32 (if any)
|
||||
if(nError == ERROR_SUCCESS && (AttrHeader.dwFlags & MPQ_ATTRIBUTE_CRC32))
|
||||
{
|
||||
LPDWORD pArrayCRC32 = ALLOCMEM(DWORD, dwBlockTableSize);
|
||||
|
||||
if(pArrayCRC32 != NULL)
|
||||
{
|
||||
dwArraySize = dwBlockTableSize * sizeof(DWORD);
|
||||
SFileReadFile(hFile, pArrayCRC32, dwArraySize, &dwBytesRead, NULL);
|
||||
if(dwBytesRead == dwArraySize)
|
||||
{
|
||||
for(i = 0; i < dwBlockTableSize; i++)
|
||||
ha->pFileTable[i].dwCrc32 = BSWAP_INT32_UNSIGNED(pArrayCRC32[i]);
|
||||
}
|
||||
else
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
FREEMEM(pArrayCRC32);
|
||||
}
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Read the array of file times
|
||||
if(nError == ERROR_SUCCESS && (AttrHeader.dwFlags & MPQ_ATTRIBUTE_FILETIME))
|
||||
{
|
||||
ULONGLONG * pArrayFileTime = ALLOCMEM(ULONGLONG, dwBlockTableSize);
|
||||
|
||||
if(pArrayFileTime != NULL)
|
||||
{
|
||||
dwArraySize = dwBlockTableSize * sizeof(ULONGLONG);
|
||||
SFileReadFile(hFile, pArrayFileTime, dwArraySize, &dwBytesRead, NULL);
|
||||
if(dwBytesRead == dwArraySize)
|
||||
{
|
||||
for(i = 0; i < dwBlockTableSize; i++)
|
||||
ha->pFileTable[i].FileTime = BSWAP_INT64_UNSIGNED(pArrayFileTime[i]);
|
||||
}
|
||||
else
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
FREEMEM(pArrayFileTime);
|
||||
}
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Read the MD5 (if any)
|
||||
// Note: MD5 array can be incomplete, if it's the last array in the (attributes)
|
||||
if(nError == ERROR_SUCCESS && (AttrHeader.dwFlags & MPQ_ATTRIBUTE_MD5))
|
||||
{
|
||||
unsigned char * pArrayMD5 = ALLOCMEM(unsigned char, (dwBlockTableSize * MD5_DIGEST_SIZE));
|
||||
unsigned char * md5;
|
||||
|
||||
if(pArrayMD5 != NULL)
|
||||
{
|
||||
dwArraySize = dwBlockTableSize * MD5_DIGEST_SIZE;
|
||||
SFileReadFile(hFile, pArrayMD5, dwArraySize, &dwBytesRead, NULL);
|
||||
if(dwBytesRead == dwArraySize)
|
||||
{
|
||||
md5 = pArrayMD5;
|
||||
for(i = 0; i < dwBlockTableSize; i++)
|
||||
{
|
||||
memcpy(ha->pFileTable[i].md5, md5, MD5_DIGEST_SIZE);
|
||||
md5 += MD5_DIGEST_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
FREEMEM(pArrayMD5);
|
||||
}
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
//
|
||||
// Note: Version 7.00 of StormLib saved the (attributes) incorrectly.
|
||||
// Sometimes, number of entries in the (attributes) was 1 item less
|
||||
// than block table size.
|
||||
// If we encounter such table, we will zero all three arrays
|
||||
//
|
||||
|
||||
if(nError != ERROR_SUCCESS)
|
||||
ha->dwAttrFlags = 0;
|
||||
|
||||
// Cleanup & exit
|
||||
SFileCloseFile(hFile);
|
||||
}
|
||||
return nError;
|
||||
}
|
||||
|
||||
int SAttrFileSaveToMpq(TMPQArchive * ha)
|
||||
{
|
||||
MPQ_ATTRIBUTES_HEADER AttrHeader;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQFile * hf = NULL;
|
||||
DWORD dwFinalBlockTableSize = ha->dwFileTableSize;
|
||||
DWORD dwFileSize = 0;
|
||||
DWORD dwToWrite;
|
||||
DWORD i;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// If the (attributes) is not in the file table yet,
|
||||
// we have to increase the final block table size
|
||||
pFileEntry = GetFileEntryExact(ha, ATTRIBUTES_NAME, LANG_NEUTRAL);
|
||||
if(pFileEntry != NULL)
|
||||
{
|
||||
// If "(attributes)" file exists, and it's set to 0, then remove it
|
||||
if(ha->dwAttrFlags == 0)
|
||||
{
|
||||
FreeFileEntry(ha, pFileEntry);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we don't want to create file atributes, do nothing
|
||||
if(ha->dwAttrFlags == 0)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// Check where the file entry is going to be allocated.
|
||||
// If at the end of the file table, we have to increment
|
||||
// the expected size of the (attributes) file.
|
||||
pFileEntry = FindFreeFileEntry(ha);
|
||||
if(pFileEntry == ha->pFileTable + ha->dwFileTableSize)
|
||||
dwFinalBlockTableSize++;
|
||||
}
|
||||
|
||||
// Calculate the size of the attributes file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
dwFileSize = sizeof(MPQ_ATTRIBUTES_HEADER); // Header
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_CRC32)
|
||||
dwFileSize += dwFinalBlockTableSize * sizeof(DWORD);
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_FILETIME)
|
||||
dwFileSize += dwFinalBlockTableSize * sizeof(ULONGLONG);
|
||||
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_MD5)
|
||||
dwFileSize += dwFinalBlockTableSize * MD5_DIGEST_SIZE;
|
||||
}
|
||||
|
||||
// Create the attributes file in the MPQ
|
||||
assert(ha->dwFileFlags2 != 0);
|
||||
nError = SFileAddFile_Init(ha, ATTRIBUTES_NAME,
|
||||
0,
|
||||
dwFileSize,
|
||||
LANG_NEUTRAL,
|
||||
ha->dwFileFlags2,
|
||||
&hf);
|
||||
|
||||
// Write all parts of the (attributes) file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
assert(ha->dwFileTableSize == dwFinalBlockTableSize);
|
||||
|
||||
AttrHeader.dwVersion = BSWAP_INT32_UNSIGNED(100);
|
||||
AttrHeader.dwFlags = BSWAP_INT32_UNSIGNED(ha->dwAttrFlags);
|
||||
dwToWrite = sizeof(MPQ_ATTRIBUTES_HEADER);
|
||||
nError = SFileAddFile_Write(hf, &AttrHeader, dwToWrite, MPQ_COMPRESSION_ZLIB);
|
||||
}
|
||||
|
||||
// Write the array of CRC32
|
||||
if(nError == ERROR_SUCCESS && (ha->dwAttrFlags & MPQ_ATTRIBUTE_CRC32))
|
||||
{
|
||||
LPDWORD pArrayCRC32 = ALLOCMEM(DWORD, dwFinalBlockTableSize);
|
||||
|
||||
if(pArrayCRC32 != NULL)
|
||||
{
|
||||
// Copy from file table
|
||||
for(i = 0; i < ha->dwFileTableSize; i++)
|
||||
pArrayCRC32[i] = BSWAP_INT32_UNSIGNED(ha->pFileTable[i].dwCrc32);
|
||||
|
||||
dwToWrite = ha->dwFileTableSize * sizeof(DWORD);
|
||||
nError = SFileAddFile_Write(hf, pArrayCRC32, dwToWrite, MPQ_COMPRESSION_ZLIB);
|
||||
FREEMEM(pArrayCRC32);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the array of file time
|
||||
if(nError == ERROR_SUCCESS && (ha->dwAttrFlags & MPQ_ATTRIBUTE_FILETIME))
|
||||
{
|
||||
ULONGLONG * pArrayFileTime = ALLOCMEM(ULONGLONG, ha->dwFileTableSize);
|
||||
|
||||
if(pArrayFileTime != NULL)
|
||||
{
|
||||
// Copy from file table
|
||||
for(i = 0; i < ha->dwFileTableSize; i++)
|
||||
pArrayFileTime[i] = BSWAP_INT64_UNSIGNED(ha->pFileTable[i].FileTime);
|
||||
|
||||
dwToWrite = ha->dwFileTableSize * sizeof(ULONGLONG);
|
||||
nError = SFileAddFile_Write(hf, pArrayFileTime, dwToWrite, MPQ_COMPRESSION_ZLIB);
|
||||
FREEMEM(pArrayFileTime);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the array of MD5s
|
||||
if(nError == ERROR_SUCCESS && (ha->dwAttrFlags & MPQ_ATTRIBUTE_MD5))
|
||||
{
|
||||
char * pArrayMD5 = ALLOCMEM(char, ha->dwFileTableSize * MD5_DIGEST_SIZE);
|
||||
|
||||
if(pArrayMD5 != NULL)
|
||||
{
|
||||
// Copy from file table
|
||||
for(i = 0; i < ha->dwFileTableSize; i++)
|
||||
memcpy(&pArrayMD5[i * MD5_DIGEST_SIZE], ha->pFileTable[i].md5, MD5_DIGEST_SIZE);
|
||||
|
||||
dwToWrite = ha->dwFileTableSize * MD5_DIGEST_SIZE;
|
||||
nError = SFileAddFile_Write(hf, pArrayMD5, dwToWrite, MPQ_COMPRESSION_ZLIB);
|
||||
FREEMEM(pArrayMD5);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the file in the archive
|
||||
if(hf != NULL)
|
||||
{
|
||||
SFileAddFile_Finish(hf);
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
ha->dwFlags &= ~MPQ_FLAG_INV_ATTRIBUTES;
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
DWORD WINAPI SFileGetAttributes(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
// Verify the parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return SFILE_INVALID_ATTRIBUTES;
|
||||
}
|
||||
|
||||
return ha->dwAttrFlags;
|
||||
}
|
||||
|
||||
bool WINAPI SFileSetAttributes(HANDLE hMpq, DWORD dwFlags)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
// Verify the parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not allowed when the archive is read-only
|
||||
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
|
||||
{
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the attributes
|
||||
InvalidateInternalFiles(ha);
|
||||
ha->dwAttrFlags = (dwFlags & MPQ_ATTRIBUTE_ALL);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WINAPI SFileUpdateFileAttributes(HANDLE hMpq, const char * szFileName)
|
||||
{
|
||||
hash_state md5_state;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TMPQFile * hf;
|
||||
BYTE Buffer[0x1000];
|
||||
HANDLE hFile = NULL;
|
||||
DWORD dwTotalBytes = 0;
|
||||
DWORD dwBytesRead;
|
||||
DWORD dwCrc32;
|
||||
|
||||
// Verify the parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not allowed when the archive is read-only
|
||||
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
|
||||
{
|
||||
SetLastError(ERROR_ACCESS_DENIED);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to open the file
|
||||
if(!SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_FROM_MPQ, &hFile))
|
||||
return false;
|
||||
|
||||
// Get the file size
|
||||
hf = (TMPQFile *)hFile;
|
||||
SFileGetFileInfo(hFile, SFILE_INFO_FILE_SIZE, &dwTotalBytes, sizeof(DWORD));
|
||||
|
||||
// Initialize the CRC32 and MD5 contexts
|
||||
md5_init(&md5_state);
|
||||
dwCrc32 = crc32(0, Z_NULL, 0);
|
||||
|
||||
// Go through entire file and calculate both CRC32 and MD5
|
||||
while(dwTotalBytes != 0)
|
||||
{
|
||||
// Read data from file
|
||||
SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
|
||||
if(dwBytesRead == 0)
|
||||
break;
|
||||
|
||||
// Update CRC32 and MD5
|
||||
dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead);
|
||||
md5_process(&md5_state, Buffer, dwBytesRead);
|
||||
|
||||
// Decrement the total size
|
||||
dwTotalBytes -= dwBytesRead;
|
||||
}
|
||||
|
||||
// Update both CRC32 and MD5
|
||||
hf->pFileEntry->dwCrc32 = dwCrc32;
|
||||
md5_done(&md5_state, hf->pFileEntry->md5);
|
||||
|
||||
// Remember that we need to save the MPQ tables
|
||||
InvalidateInternalFiles(ha);
|
||||
SFileCloseFile(hFile);
|
||||
return true;
|
||||
}
|
||||
735
src/dep/src/StormLib/src/SFileCompactArchive.cpp
Normal file
735
src/dep/src/StormLib/src/SFileCompactArchive.cpp
Normal file
@ -0,0 +1,735 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileCompactArchive.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Archive compacting function */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 14.04.03 1.00 Lad Splitted from SFileCreateArchiveEx.cpp */
|
||||
/* 19.11.03 1.01 Dan Big endian handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local variables */
|
||||
/*****************************************************************************/
|
||||
|
||||
static SFILE_COMPACT_CALLBACK CompactCB = NULL;
|
||||
static ULONGLONG CompactBytesProcessed = 0;
|
||||
static ULONGLONG CompactTotalBytes = 0;
|
||||
static void * pvUserData = NULL;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
static int CheckIfAllFilesKnown(TMPQArchive * ha, const char * szListFile, LPDWORD pFileKeys)
|
||||
{
|
||||
TFileEntry * pFileTableEnd;
|
||||
TFileEntry * pFileEntry;
|
||||
DWORD dwBlockIndex = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Add the listfile to the MPQ
|
||||
if(nError == ERROR_SUCCESS && szListFile != NULL)
|
||||
{
|
||||
// Notify the user
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(pvUserData, CCB_CHECKING_FILES, CompactBytesProcessed, CompactTotalBytes);
|
||||
|
||||
nError = SFileAddListFile((HANDLE)ha, szListFile);
|
||||
}
|
||||
|
||||
// Verify the file table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++, dwBlockIndex++)
|
||||
{
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
|
||||
{
|
||||
if(pFileEntry->szFileName != NULL && !IsPseudoFileName(pFileEntry->szFileName, NULL))
|
||||
{
|
||||
DWORD dwFileKey = 0;
|
||||
|
||||
// Resolve the file key. Use plain file name for it
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
dwFileKey = DecryptFileKey(pFileEntry->szFileName,
|
||||
pFileEntry->ByteOffset,
|
||||
pFileEntry->dwFileSize,
|
||||
pFileEntry->dwFlags);
|
||||
}
|
||||
|
||||
// Give the key to the caller
|
||||
if(pFileKeys != NULL)
|
||||
pFileKeys[dwBlockIndex] = dwFileKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
static int CopyNonMpqData(
|
||||
TFileStream * pSrcStream,
|
||||
TFileStream * pTrgStream,
|
||||
ULONGLONG & ByteOffset,
|
||||
ULONGLONG & ByteCount)
|
||||
{
|
||||
ULONGLONG DataSize = ByteCount;
|
||||
DWORD dwToRead;
|
||||
char DataBuffer[0x1000];
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Copy the data
|
||||
while(DataSize > 0)
|
||||
{
|
||||
// Get the proper size of data
|
||||
dwToRead = sizeof(DataBuffer);
|
||||
if(DataSize < dwToRead)
|
||||
dwToRead = (DWORD)DataSize;
|
||||
|
||||
// Read from the source stream
|
||||
if(!FileStream_Read(pSrcStream, &ByteOffset, DataBuffer, dwToRead))
|
||||
{
|
||||
nError = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Write to the target stream
|
||||
if(!FileStream_Write(pTrgStream, NULL, DataBuffer, dwToRead))
|
||||
{
|
||||
nError = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Update the progress
|
||||
if(CompactCB != NULL)
|
||||
{
|
||||
CompactBytesProcessed += dwToRead;
|
||||
CompactCB(pvUserData, CCB_COPYING_NON_MPQ_DATA, CompactBytesProcessed, CompactTotalBytes);
|
||||
}
|
||||
|
||||
// Decrement the number of data to be copied
|
||||
ByteOffset += dwToRead;
|
||||
DataSize -= dwToRead;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// Copies all file sectors into another archive.
|
||||
static int CopyMpqFileSectors(
|
||||
TMPQArchive * ha,
|
||||
TMPQFile * hf,
|
||||
TFileStream * pNewStream)
|
||||
{
|
||||
TFileEntry * pFileEntry = hf->pFileEntry;
|
||||
ULONGLONG RawFilePos; // Used for calculating sector offset in the old MPQ archive
|
||||
ULONGLONG MpqFilePos; // MPQ file position in the new archive
|
||||
DWORD dwBytesToCopy = pFileEntry->dwCmpSize;
|
||||
DWORD dwPatchSize = 0; // Size of patch header
|
||||
DWORD dwFileKey1 = 0; // File key used for decryption
|
||||
DWORD dwFileKey2 = 0; // File key used for encryption
|
||||
DWORD dwCmpSize = 0; // Compressed file size, including patch header
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Remember the position in the destination file
|
||||
FileStream_GetPos(pNewStream, MpqFilePos);
|
||||
MpqFilePos -= ha->MpqPos;
|
||||
|
||||
// Resolve decryption keys. Note that the file key given
|
||||
// in the TMPQFile structure also includes the key adjustment
|
||||
if(nError == ERROR_SUCCESS && (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED))
|
||||
{
|
||||
dwFileKey2 = dwFileKey1 = hf->dwFileKey;
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_FIX_KEY)
|
||||
{
|
||||
dwFileKey2 = (dwFileKey1 ^ pFileEntry->dwFileSize) - (DWORD)pFileEntry->ByteOffset;
|
||||
dwFileKey2 = (dwFileKey2 + (DWORD)MpqFilePos) ^ pFileEntry->dwFileSize;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have to save patch header, do it
|
||||
if(nError == ERROR_SUCCESS && hf->pPatchInfo != NULL)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED(hf->pPatchInfo, sizeof(DWORD) * 3);
|
||||
if(!FileStream_Write(pNewStream, NULL, hf->pPatchInfo, hf->pPatchInfo->dwLength))
|
||||
nError = GetLastError();
|
||||
|
||||
// Save the size of the patch info
|
||||
dwPatchSize = hf->pPatchInfo->dwLength;
|
||||
}
|
||||
|
||||
// If we have to save sector offset table, do it.
|
||||
if(nError == ERROR_SUCCESS && hf->SectorOffsets != NULL)
|
||||
{
|
||||
DWORD * SectorOffsetsCopy = (DWORD *)ALLOCMEM(BYTE, hf->SectorOffsets[0]);
|
||||
DWORD dwSectorOffsLen = hf->SectorOffsets[0];
|
||||
|
||||
assert((pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) == 0);
|
||||
assert(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED);
|
||||
|
||||
if(SectorOffsetsCopy == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Encrypt the secondary sector offset table and write it to the target file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memcpy(SectorOffsetsCopy, hf->SectorOffsets, dwSectorOffsLen);
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
EncryptMpqBlock(SectorOffsetsCopy, dwSectorOffsLen, dwFileKey2 - 1);
|
||||
|
||||
BSWAP_ARRAY32_UNSIGNED(SectorOffsetsCopy, dwSectorOffsLen);
|
||||
if(!FileStream_Write(pNewStream, NULL, SectorOffsetsCopy, dwSectorOffsLen))
|
||||
nError = GetLastError();
|
||||
|
||||
dwCmpSize += dwSectorOffsLen;
|
||||
}
|
||||
|
||||
// Update compact progress
|
||||
if(CompactCB != NULL)
|
||||
{
|
||||
CompactBytesProcessed += dwSectorOffsLen;
|
||||
CompactCB(pvUserData, CCB_COMPACTING_FILES, CompactBytesProcessed, CompactTotalBytes);
|
||||
}
|
||||
|
||||
FREEMEM(SectorOffsetsCopy);
|
||||
}
|
||||
|
||||
// Now we have to copy all file sectors. We do it without
|
||||
// recompression, because recompression is not necessary in this case
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
for(DWORD dwSector = 0; dwSector < hf->dwSectorCount; dwSector++)
|
||||
{
|
||||
DWORD dwRawDataInSector = hf->dwSectorSize;
|
||||
DWORD dwRawByteOffset = dwSector * hf->dwSectorSize;
|
||||
|
||||
// Last sector: If there is not enough bytes remaining in the file, cut the raw size
|
||||
if(dwRawDataInSector > dwBytesToCopy)
|
||||
dwRawDataInSector = dwBytesToCopy;
|
||||
|
||||
// Fix the raw data length if the file is compressed
|
||||
if(hf->SectorOffsets != NULL)
|
||||
{
|
||||
dwRawDataInSector = hf->SectorOffsets[dwSector+1] - hf->SectorOffsets[dwSector];
|
||||
dwRawByteOffset = hf->SectorOffsets[dwSector];
|
||||
}
|
||||
|
||||
// Calculate the raw file offset of the file sector
|
||||
CalculateRawSectorOffset(RawFilePos, hf, dwRawByteOffset);
|
||||
|
||||
// Read the file sector
|
||||
if(!FileStream_Read(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector))
|
||||
{
|
||||
nError = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// If necessary, re-encrypt the sector
|
||||
// Note: Recompression is not necessary here. Unlike encryption,
|
||||
// the compression does not depend on the position of the file in MPQ.
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) && dwFileKey1 != dwFileKey2)
|
||||
{
|
||||
BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector);
|
||||
DecryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwFileKey1 + dwSector);
|
||||
EncryptMpqBlock(hf->pbFileSector, dwRawDataInSector, dwFileKey2 + dwSector);
|
||||
BSWAP_ARRAY32_UNSIGNED(hf->pbFileSector, dwRawDataInSector);
|
||||
}
|
||||
|
||||
// Now write the sector back to the file
|
||||
if(!FileStream_Write(pNewStream, NULL, hf->pbFileSector, dwRawDataInSector))
|
||||
{
|
||||
nError = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Update compact progress
|
||||
if(CompactCB != NULL)
|
||||
{
|
||||
CompactBytesProcessed += dwRawDataInSector;
|
||||
CompactCB(pvUserData, CCB_COMPACTING_FILES, CompactBytesProcessed, CompactTotalBytes);
|
||||
}
|
||||
|
||||
// Adjust byte counts
|
||||
dwBytesToCopy -= hf->dwSectorSize;
|
||||
dwCmpSize += dwRawDataInSector;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the sector CRCs, if any
|
||||
// Sector CRCs are always compressed (not imploded) and unencrypted
|
||||
if(nError == ERROR_SUCCESS && hf->SectorOffsets != NULL && hf->SectorChksums != NULL)
|
||||
{
|
||||
DWORD dwCrcLength;
|
||||
|
||||
dwCrcLength = hf->SectorOffsets[hf->dwSectorCount + 1] - hf->SectorOffsets[hf->dwSectorCount];
|
||||
if(dwCrcLength != 0)
|
||||
{
|
||||
if(!FileStream_Read(ha->pStream, NULL, hf->SectorChksums, dwCrcLength))
|
||||
nError = GetLastError();
|
||||
|
||||
if(!FileStream_Write(pNewStream, NULL, hf->SectorChksums, dwCrcLength))
|
||||
nError = GetLastError();
|
||||
|
||||
// Update compact progress
|
||||
if(CompactCB != NULL)
|
||||
{
|
||||
CompactBytesProcessed += dwCrcLength;
|
||||
CompactCB(pvUserData, CCB_COMPACTING_FILES, CompactBytesProcessed, CompactTotalBytes);
|
||||
}
|
||||
|
||||
// Size of the CRC block is also included in the compressed file size
|
||||
dwCmpSize += dwCrcLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the MD5's of the raw file data, if needed
|
||||
if(nError == ERROR_SUCCESS && ha->pHeader->dwRawChunkSize != 0)
|
||||
{
|
||||
nError = WriteMpqDataMD5(pNewStream,
|
||||
ha->MpqPos + MpqFilePos,
|
||||
pFileEntry->dwCmpSize,
|
||||
ha->pHeader->dwRawChunkSize);
|
||||
}
|
||||
|
||||
// Update file position in the block table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// At this point, number of bytes written should be exactly
|
||||
// the same like the compressed file size. If it isn't,
|
||||
// there's something wrong (an unknown archive version, MPQ protection, ...)
|
||||
//
|
||||
// Note: Diablo savegames have very weird layout, and the file "hero"
|
||||
// seems to have improper compressed size. Instead of real compressed size,
|
||||
// the "dwCmpSize" member of the block table entry contains
|
||||
// uncompressed size of file data + size of the sector table.
|
||||
// If we compact the archive, Diablo will refuse to load the game
|
||||
// Seems like some sort of protection to me.
|
||||
//
|
||||
// Note: Some patch files in WOW patches don't count the patch header
|
||||
// into compressed size
|
||||
//
|
||||
|
||||
if(dwCmpSize <= pFileEntry->dwCmpSize && pFileEntry->dwCmpSize <= dwCmpSize + dwPatchSize)
|
||||
{
|
||||
// Note: DO NOT update the compressed size in the file entry, no matter how bad it is.
|
||||
pFileEntry->ByteOffset = MpqFilePos;
|
||||
}
|
||||
else
|
||||
{
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
static int CopyMpqFiles(TMPQArchive * ha, LPDWORD pFileKeys, TFileStream * pNewStream)
|
||||
{
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQFile * hf = NULL;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Walk through all files and write them to the destination MPQ archive
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
// Copy all the file sectors
|
||||
// Only do that when the file has nonzero size
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && pFileEntry->dwFileSize != 0)
|
||||
{
|
||||
// Allocate structure for the MPQ file
|
||||
hf = CreateMpqFile(ha);
|
||||
if(hf == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Store file entry
|
||||
hf->pFileEntry = pFileEntry;
|
||||
|
||||
// Set the raw file position
|
||||
hf->MpqFilePos = pFileEntry->ByteOffset;
|
||||
hf->RawFilePos = ha->MpqPos + hf->MpqFilePos;
|
||||
|
||||
// Set the file decryption key
|
||||
hf->dwFileKey = pFileKeys[pFileEntry - ha->pFileTable];
|
||||
hf->dwDataSize = pFileEntry->dwFileSize;
|
||||
|
||||
// If the file is a patch file, load the patch header
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
|
||||
{
|
||||
nError = AllocatePatchInfo(hf, true);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
// Allocate buffers for file sector and sector offset table
|
||||
nError = AllocateSectorBuffer(hf);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Also allocate sector offset table and sector checksum table
|
||||
nError = AllocateSectorOffsets(hf, true);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Also load sector checksums, if any
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC)
|
||||
{
|
||||
nError = AllocateSectorChecksums(hf, false);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy all file sectors
|
||||
nError = CopyMpqFileSectors(ha, hf, pNewStream);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Free buffers. This also sets "hf" to NULL.
|
||||
FreeMPQFile(hf);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup and exit
|
||||
if(hf != NULL)
|
||||
FreeMPQFile(hf);
|
||||
return nError;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
bool WINAPI SFileSetCompactCallback(HANDLE /* hMpq */, SFILE_COMPACT_CALLBACK aCompactCB, void * pvData)
|
||||
{
|
||||
CompactCB = aCompactCB;
|
||||
pvUserData = pvData;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Archive compacting
|
||||
|
||||
bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile, bool /* bReserved */)
|
||||
{
|
||||
TFileStream * pTempStream = NULL;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
ULONGLONG ByteOffset;
|
||||
ULONGLONG ByteCount;
|
||||
LPDWORD pFileKeys = NULL;
|
||||
TCHAR szTempFile[MAX_PATH] = _T("");
|
||||
TCHAR * szTemp = NULL;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Test the valid parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
nError = ERROR_INVALID_HANDLE;
|
||||
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
|
||||
nError = ERROR_ACCESS_DENIED;
|
||||
|
||||
// If the MPQ is changed at this moment, we have to flush the archive
|
||||
if(nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_CHANGED))
|
||||
{
|
||||
SFileFlushArchive(hMpq);
|
||||
}
|
||||
|
||||
// Create the table with file keys
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((pFileKeys = ALLOCMEM(DWORD, ha->dwFileTableSize)) != NULL)
|
||||
memset(pFileKeys, 0, sizeof(DWORD) * ha->dwFileTableSize);
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// First of all, we have to check of we are able to decrypt all files.
|
||||
// If not, sorry, but the archive cannot be compacted.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Initialize the progress variables for compact callback
|
||||
FileStream_GetSize(ha->pStream, CompactTotalBytes);
|
||||
CompactBytesProcessed = 0;
|
||||
nError = CheckIfAllFilesKnown(ha, szListFile, pFileKeys);
|
||||
}
|
||||
|
||||
// Get the temporary file name and create it
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
_tcscpy(szTempFile, ha->pStream->szFileName);
|
||||
if((szTemp = _tcsrchr(szTempFile, '.')) != NULL)
|
||||
_tcscpy(szTemp + 1, _T("mp_"));
|
||||
else
|
||||
_tcscat(szTempFile, _T("_"));
|
||||
|
||||
pTempStream = FileStream_CreateFile(szTempFile);
|
||||
if(pTempStream == NULL)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Write the data before MPQ user data (if any)
|
||||
if(nError == ERROR_SUCCESS && ha->UserDataPos != 0)
|
||||
{
|
||||
// Inform the application about the progress
|
||||
if(CompactCB != NULL)
|
||||
CompactCB(pvUserData, CCB_COPYING_NON_MPQ_DATA, CompactBytesProcessed, CompactTotalBytes);
|
||||
|
||||
ByteOffset = 0;
|
||||
ByteCount = ha->UserDataPos;
|
||||
nError = CopyNonMpqData(ha->pStream, pTempStream, ByteOffset, ByteCount);
|
||||
}
|
||||
|
||||
// Write the MPQ user data (if any)
|
||||
if(nError == ERROR_SUCCESS && ha->MpqPos > ha->UserDataPos)
|
||||
{
|
||||
// At this point, we assume that the user data size is equal
|
||||
// to pUserData->dwHeaderOffs.
|
||||
// If this assumption doesn't work, then we have an unknown version of MPQ
|
||||
ByteOffset = ha->UserDataPos;
|
||||
ByteCount = ha->MpqPos - ha->UserDataPos;
|
||||
|
||||
assert(ha->pUserData != NULL);
|
||||
assert(ha->pUserData->dwHeaderOffs == ByteCount);
|
||||
nError = CopyNonMpqData(ha->pStream, pTempStream, ByteOffset, ByteCount);
|
||||
}
|
||||
|
||||
// Write the MPQ header
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Remember the header size before swapping
|
||||
DWORD dwBytesToWrite = ha->pHeader->dwHeaderSize;
|
||||
|
||||
BSWAP_TMPQHEADER(ha->pHeader);
|
||||
if(!FileStream_Write(pTempStream, NULL, ha->pHeader, dwBytesToWrite))
|
||||
nError = GetLastError();
|
||||
BSWAP_TMPQHEADER(ha->pHeader);
|
||||
|
||||
// Update the progress
|
||||
CompactBytesProcessed += ha->pHeader->dwHeaderSize;
|
||||
}
|
||||
|
||||
// Now copy all files
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nError = CopyMpqFiles(ha, pFileKeys, pTempStream);
|
||||
ha->dwFlags |= MPQ_FLAG_CHANGED;
|
||||
}
|
||||
|
||||
// If succeeded, switch the streams
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(FileStream_MoveFile(ha->pStream, pTempStream))
|
||||
pTempStream = NULL;
|
||||
else
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
// If all succeeded, save the MPQ tables
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
//
|
||||
// Note: We don't recalculate position of the MPQ tables at this point.
|
||||
// SaveMPQTables does it automatically.
|
||||
//
|
||||
|
||||
nError = SaveMPQTables(ha);
|
||||
if(nError == ERROR_SUCCESS && CompactCB != NULL)
|
||||
{
|
||||
CompactBytesProcessed += (ha->pHeader->dwHashTableSize * sizeof(TMPQHash));
|
||||
CompactBytesProcessed += (ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock));
|
||||
CompactCB(pvUserData, CCB_CLOSING_ARCHIVE, CompactBytesProcessed, CompactTotalBytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate the compact callback
|
||||
pvUserData = NULL;
|
||||
CompactCB = NULL;
|
||||
|
||||
// Cleanup and return
|
||||
if(pTempStream != NULL)
|
||||
FileStream_Close(pTempStream);
|
||||
if(pFileKeys != NULL)
|
||||
FREEMEM(pFileKeys);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Changing hash table size
|
||||
|
||||
DWORD WINAPI SFileGetMaxFileCount(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
return ha->dwMaxFileCount;
|
||||
}
|
||||
|
||||
bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount)
|
||||
{
|
||||
TMPQHetTable * pOldHetTable = NULL;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TFileEntry * pOldFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
TFileEntry * pOldFileTable = NULL;
|
||||
TFileEntry * pOldFileEntry;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQHash * pOldHashTable = NULL;
|
||||
DWORD dwOldHashTableSize = 0;
|
||||
DWORD dwOldFileTableSize = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Test the valid parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
nError = ERROR_INVALID_HANDLE;
|
||||
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
|
||||
nError = ERROR_ACCESS_DENIED;
|
||||
|
||||
// The new limit must not be lower than the index of the last file entry in the table
|
||||
if(nError == ERROR_SUCCESS && ha->dwFileTableSize > dwMaxFileCount)
|
||||
nError = ERROR_DISK_FULL;
|
||||
|
||||
// ALL file names must be known in order to be able
|
||||
// to rebuild hash table size
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nError = CheckIfAllFilesKnown(ha, NULL, NULL);
|
||||
}
|
||||
|
||||
// If the MPQ has a hash table, then we relocate the hash table
|
||||
if(nError == ERROR_SUCCESS && ha->pHashTable != NULL)
|
||||
{
|
||||
// Save parameters for the current hash table
|
||||
dwOldHashTableSize = ha->pHeader->dwHashTableSize;
|
||||
pOldHashTable = ha->pHashTable;
|
||||
|
||||
// Allocate new hash table
|
||||
ha->pHeader->dwHashTableSize = GetHashTableSizeForFileCount(dwMaxFileCount);
|
||||
ha->pHashTable = ALLOCMEM(TMPQHash, ha->pHeader->dwHashTableSize);
|
||||
if(ha->pHashTable != NULL)
|
||||
memset(ha->pHashTable, 0xFF, ha->pHeader->dwHashTableSize * sizeof(TMPQHash));
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// If the MPQ has HET table, allocate new one as well
|
||||
if(nError == ERROR_SUCCESS && ha->pHetTable != NULL)
|
||||
{
|
||||
// Save the original HET table
|
||||
pOldHetTable = ha->pHetTable;
|
||||
|
||||
// Create new one
|
||||
ha->pHetTable = CreateHetTable(dwMaxFileCount, 0x40, true);
|
||||
if(ha->pHetTable == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Now reallocate the file table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Save the current file table
|
||||
dwOldFileTableSize = ha->dwFileTableSize;
|
||||
pOldFileTable = ha->pFileTable;
|
||||
|
||||
// Create new one
|
||||
ha->pFileTable = ALLOCMEM(TFileEntry, dwMaxFileCount);
|
||||
if(ha->pFileTable != NULL)
|
||||
memset(ha->pFileTable, 0, dwMaxFileCount * sizeof(TFileEntry));
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Now we have to build both classic hash table and HET table.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD dwFileIndex = 0;
|
||||
DWORD dwHashIndex = 0;
|
||||
|
||||
// Create new hash and HET entry for each file
|
||||
pFileEntry = ha->pFileTable;
|
||||
for(pOldFileEntry = pOldFileTable; pOldFileEntry < pOldFileTableEnd; pOldFileEntry++)
|
||||
{
|
||||
if(pOldFileEntry->dwFlags & MPQ_FILE_EXISTS)
|
||||
{
|
||||
// Copy the old file entry to the new one
|
||||
memcpy(pFileEntry, pOldFileEntry, sizeof(TFileEntry));
|
||||
assert(pFileEntry->szFileName != NULL);
|
||||
|
||||
// Create new entry in the hash table
|
||||
if(ha->pHashTable != NULL)
|
||||
{
|
||||
dwHashIndex = AllocateHashEntry(ha, pFileEntry);
|
||||
if(dwHashIndex == HASH_ENTRY_FREE)
|
||||
{
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new entry in the HET table, if needed
|
||||
if(ha->pHetTable != NULL)
|
||||
{
|
||||
dwHashIndex = AllocateHetEntry(ha, pFileEntry);
|
||||
if(dwHashIndex == HASH_ENTRY_FREE)
|
||||
{
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to the next file entry in the new table
|
||||
pFileEntry++;
|
||||
dwFileIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the archive as changed
|
||||
// Note: We always have to rebuild the (attributes) file due to file table change
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
ha->dwMaxFileCount = dwMaxFileCount;
|
||||
InvalidateInternalFiles(ha);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Revert the hash table
|
||||
if(ha->pHashTable != NULL && pOldHashTable != NULL)
|
||||
{
|
||||
FREEMEM(ha->pHashTable);
|
||||
ha->pHeader->dwHashTableSize = dwOldHashTableSize;
|
||||
ha->pHashTable = pOldHashTable;
|
||||
}
|
||||
|
||||
// Revert the HET table
|
||||
if(ha->pHetTable != NULL && pOldHetTable != NULL)
|
||||
{
|
||||
FreeHetTable(ha->pHetTable);
|
||||
ha->pHetTable = pOldHetTable;
|
||||
}
|
||||
|
||||
// Revert the file table
|
||||
if(pOldFileTable != NULL)
|
||||
{
|
||||
FREEMEM(ha->pFileTable);
|
||||
ha->pFileTable = pOldFileTable;
|
||||
}
|
||||
|
||||
SetLastError(nError);
|
||||
}
|
||||
|
||||
// Return the result
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
234
src/dep/src/StormLib/src/SFileCreateArchive.cpp
Normal file
234
src/dep/src/StormLib/src/SFileCreateArchive.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileCreateArchive.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* MPQ Editing functions */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 24.03.03 1.00 Lad Splitted from SFileOpenArchive.cpp */
|
||||
/* 08.06.10 1.00 Lad Renamed to SFileCreateArchive.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local variables
|
||||
|
||||
static const DWORD MpqHeaderSizes[] =
|
||||
{
|
||||
MPQ_HEADER_SIZE_V1,
|
||||
MPQ_HEADER_SIZE_V2,
|
||||
MPQ_HEADER_SIZE_V3,
|
||||
MPQ_HEADER_SIZE_V4
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static USHORT GetSectorSizeShift(DWORD dwSectorSize)
|
||||
{
|
||||
USHORT wSectorSizeShift = 0;
|
||||
|
||||
while(dwSectorSize > 0x200)
|
||||
{
|
||||
dwSectorSize >>= 1;
|
||||
wSectorSizeShift++;
|
||||
}
|
||||
|
||||
return wSectorSizeShift;
|
||||
}
|
||||
|
||||
static int WriteNakedMPQHeader(TMPQArchive * ha)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
TMPQHeader Header;
|
||||
DWORD dwBytesToWrite = pHeader->dwHeaderSize;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Prepare the naked MPQ header
|
||||
memset(&Header, 0, sizeof(TMPQHeader));
|
||||
Header.dwID = pHeader->dwID;
|
||||
Header.dwHeaderSize = pHeader->dwHeaderSize;
|
||||
Header.dwArchiveSize = pHeader->dwHeaderSize;
|
||||
Header.wFormatVersion = pHeader->wFormatVersion;
|
||||
Header.wSectorSize = pHeader->wSectorSize;
|
||||
|
||||
// Write it to the file
|
||||
BSWAP_TMPQHEADER(&Header);
|
||||
if(!FileStream_Write(ha->pStream, &ha->MpqPos, &Header, dwBytesToWrite))
|
||||
nError = GetLastError();
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates a new MPQ archive.
|
||||
|
||||
bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwMaxFileCount, HANDLE * phMpq)
|
||||
{
|
||||
TFileStream * pStream = NULL; // File stream
|
||||
TMPQArchive * ha = NULL; // MPQ archive handle
|
||||
ULONGLONG MpqPos = 0; // Position of MPQ header in the file
|
||||
HANDLE hMpq = NULL;
|
||||
USHORT wFormatVersion = MPQ_FORMAT_VERSION_1;
|
||||
DWORD dwBlockTableSize = 0; // Initial block table size
|
||||
DWORD dwHashTableSize = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Check the parameters, if they are valid
|
||||
if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// One time initialization of MPQ cryptography
|
||||
InitializeMpqCryptography();
|
||||
|
||||
// We verify if the file already exists and if it's a MPQ archive.
|
||||
// If yes, we won't allow to overwrite it.
|
||||
if(SFileOpenArchive(szMpqName, 0, dwFlags, &hMpq))
|
||||
{
|
||||
SFileCloseArchive(hMpq);
|
||||
SetLastError(ERROR_ALREADY_EXISTS);
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// At this point, we have to create the archive.
|
||||
// - If the file exists, convert it to MPQ archive.
|
||||
// - If the file doesn't exist, create new empty file
|
||||
//
|
||||
|
||||
pStream = FileStream_OpenFile(szMpqName, true);
|
||||
if(pStream == NULL)
|
||||
{
|
||||
pStream = FileStream_CreateFile(szMpqName);
|
||||
if(pStream == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decide what format to use
|
||||
wFormatVersion = (USHORT)((dwFlags & MPQ_CREATE_ARCHIVE_VMASK) >> 16);
|
||||
if(wFormatVersion > MPQ_FORMAT_VERSION_4)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Increment the maximum amount of files to have space
|
||||
// for listfile and attributes file
|
||||
if(dwFlags & MPQ_CREATE_ATTRIBUTES)
|
||||
dwMaxFileCount++;
|
||||
dwMaxFileCount++;
|
||||
|
||||
// If file count is not zero, initialize the hash table size
|
||||
dwHashTableSize = GetHashTableSizeForFileCount(dwMaxFileCount);
|
||||
|
||||
// Retrieve the file size and round it up to 0x200 bytes
|
||||
FileStream_GetSize(pStream, MpqPos);
|
||||
MpqPos = (MpqPos + 0x1FF) & (ULONGLONG)0xFFFFFFFFFFFFFE00ULL;
|
||||
if(!FileStream_SetSize(pStream, MpqPos))
|
||||
nError = GetLastError();
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Debug code, used for testing StormLib
|
||||
// dwBlockTableSize = dwHashTableSize * 2;
|
||||
#endif
|
||||
|
||||
// Create the archive handle
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Fill the MPQ archive handle structure
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(ha, 0, sizeof(TMPQArchive));
|
||||
ha->pStream = pStream;
|
||||
ha->dwSectorSize = (wFormatVersion >= MPQ_FORMAT_VERSION_3) ? 0x4000 : 0x1000;
|
||||
ha->UserDataPos = MpqPos;
|
||||
ha->MpqPos = MpqPos;
|
||||
ha->pHeader = (TMPQHeader *)ha->HeaderData;
|
||||
ha->dwMaxFileCount = dwMaxFileCount;
|
||||
ha->dwFileTableSize = 0;
|
||||
ha->dwFileFlags1 = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING;
|
||||
ha->dwFileFlags2 = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING;
|
||||
ha->dwFlags = 0;
|
||||
|
||||
// Setup the attributes
|
||||
if(dwFlags & MPQ_CREATE_ATTRIBUTES)
|
||||
ha->dwAttrFlags = MPQ_ATTRIBUTE_CRC32 | MPQ_ATTRIBUTE_FILETIME | MPQ_ATTRIBUTE_MD5;
|
||||
pStream = NULL;
|
||||
}
|
||||
|
||||
// Fill the MPQ header
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
|
||||
// Fill the MPQ header
|
||||
memset(pHeader, 0, sizeof(ha->HeaderData));
|
||||
pHeader->dwID = ID_MPQ;
|
||||
pHeader->dwHeaderSize = MpqHeaderSizes[wFormatVersion];
|
||||
pHeader->dwArchiveSize = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash);
|
||||
pHeader->wFormatVersion = wFormatVersion;
|
||||
pHeader->wSectorSize = GetSectorSizeShift(ha->dwSectorSize);
|
||||
pHeader->dwHashTablePos = pHeader->dwHeaderSize;
|
||||
pHeader->dwHashTableSize = dwHashTableSize;
|
||||
pHeader->dwBlockTablePos = pHeader->dwHashTablePos + dwHashTableSize * sizeof(TMPQHash);
|
||||
pHeader->dwBlockTableSize = dwBlockTableSize;
|
||||
|
||||
// For MPQs version 4 and higher, we set the size of raw data block
|
||||
// for calculating MD5
|
||||
if(wFormatVersion >= MPQ_FORMAT_VERSION_4)
|
||||
pHeader->dwRawChunkSize = 0x4000;
|
||||
|
||||
// Write the naked MPQ header
|
||||
nError = WriteNakedMPQHeader(ha);
|
||||
|
||||
// Remember that the (listfile) and (attributes) need to be saved
|
||||
ha->dwFlags |= MPQ_FLAG_CHANGED | MPQ_FLAG_INV_LISTFILE | MPQ_FLAG_INV_ATTRIBUTES;
|
||||
}
|
||||
|
||||
// Create initial HET table, if the caller required an MPQ format 3.0 or newer
|
||||
if(nError == ERROR_SUCCESS && wFormatVersion >= MPQ_FORMAT_VERSION_3)
|
||||
{
|
||||
ha->pHetTable = CreateHetTable(ha->dwMaxFileCount, 0x40, true);
|
||||
if(ha->pHetTable == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Create initial hash table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nError = CreateHashTable(ha, dwHashTableSize);
|
||||
}
|
||||
|
||||
// Create initial file table
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
ha->pFileTable = ALLOCMEM(TFileEntry, ha->dwMaxFileCount);
|
||||
if(ha->pFileTable != NULL)
|
||||
memset(ha->pFileTable, 0x00, sizeof(TFileEntry) * ha->dwMaxFileCount);
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Cleanup : If an error, delete all buffers and return
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
FileStream_Close(pStream);
|
||||
FreeMPQArchive(ha);
|
||||
SetLastError(nError);
|
||||
ha = NULL;
|
||||
}
|
||||
|
||||
// Return the values
|
||||
*phMpq = (HANDLE)ha;
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
@ -1,72 +1,67 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileExtractFile.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Simple extracting utility */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 20.06.03 1.00 Lad The first version of SFileExtractFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "SCommon.h"
|
||||
|
||||
BOOL WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const char * szExtracted)
|
||||
{
|
||||
HANDLE hLocalFile = INVALID_HANDLE_VALUE;
|
||||
HANDLE hMpqFile = NULL;
|
||||
DWORD dwSearchScope = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// Open the MPQ file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((DWORD_PTR)szToExtract <= 0x10000)
|
||||
dwSearchScope = SFILE_OPEN_BY_INDEX;
|
||||
if(!SFileOpenFileEx(hMpq, szToExtract, dwSearchScope, &hMpqFile))
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Create the local file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
hLocalFile = CreateFile(szExtracted, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(hLocalFile == INVALID_HANDLE_VALUE)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Copy the file's content
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
char szBuffer[0x1000];
|
||||
DWORD dwTransferred;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// dwTransferred is only set to nonzero if something has been read.
|
||||
// nError can be ERROR_SUCCESS or ERROR_HANDLE_EOF
|
||||
if(!SFileReadFile(hMpqFile, szBuffer, sizeof(szBuffer), &dwTransferred, NULL))
|
||||
nError = GetLastError();
|
||||
if(nError == ERROR_HANDLE_EOF)
|
||||
nError = ERROR_SUCCESS;
|
||||
if(dwTransferred == 0)
|
||||
break;
|
||||
|
||||
// If something has been actually read, write it
|
||||
WriteFile(hLocalFile, szBuffer, dwTransferred, &dwTransferred, NULL);
|
||||
if(dwTransferred == 0)
|
||||
nError = ERROR_DISK_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the files
|
||||
if(hMpqFile != NULL)
|
||||
SFileCloseFile(hMpqFile);
|
||||
if(hLocalFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hLocalFile);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return (BOOL)(nError == ERROR_SUCCESS);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/* SFileExtractFile.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Simple extracting utility */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 20.06.03 1.00 Lad The first version of SFileExtractFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope)
|
||||
{
|
||||
TFileStream * pLocalFile = NULL;
|
||||
HANDLE hMpqFile = NULL;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Open the MPQ file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!SFileOpenFileEx(hMpq, szToExtract, dwSearchScope, &hMpqFile))
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Create the local file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pLocalFile = FileStream_CreateFile(szExtracted);
|
||||
if(pLocalFile == NULL)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Copy the file's content
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
char szBuffer[0x1000];
|
||||
DWORD dwTransferred;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// dwTransferred is only set to nonzero if something has been read.
|
||||
// nError can be ERROR_SUCCESS or ERROR_HANDLE_EOF
|
||||
if(!SFileReadFile(hMpqFile, szBuffer, sizeof(szBuffer), &dwTransferred, NULL))
|
||||
nError = GetLastError();
|
||||
if(nError == ERROR_HANDLE_EOF)
|
||||
nError = ERROR_SUCCESS;
|
||||
if(dwTransferred == 0)
|
||||
break;
|
||||
|
||||
// If something has been actually read, write it
|
||||
if(!FileStream_Write(pLocalFile, NULL, szBuffer, dwTransferred))
|
||||
nError = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
// Close the files
|
||||
if(hMpqFile != NULL)
|
||||
SFileCloseFile(hMpqFile);
|
||||
if(pLocalFile != NULL)
|
||||
FileStream_Close(pLocalFile);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
446
src/dep/src/StormLib/src/SFileFindFile.cpp
Normal file
446
src/dep/src/StormLib/src/SFileFindFile.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* A module for file searching within MPQs */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define LISTFILE_CACHE_SIZE 0x1000
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Private structure used for file search (search handle)
|
||||
|
||||
struct TMPQSearch;
|
||||
typedef int (*MPQSEARCH)(TMPQSearch *, SFILE_FIND_DATA *);
|
||||
|
||||
// Used by searching in MPQ archives
|
||||
struct TMPQSearch
|
||||
{
|
||||
TMPQArchive * ha; // Handle to MPQ, where the search runs
|
||||
TFileEntry ** pSearchTable; // Table for files that have been already found
|
||||
DWORD dwSearchTableItems; // Number of items in the search table
|
||||
DWORD dwNextIndex; // Next file index to be checked
|
||||
DWORD dwFlagMask; // For checking flag mask
|
||||
char szSearchMask[1]; // Search mask (variable length)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static bool IsValidSearchHandle(TMPQSearch * hs)
|
||||
{
|
||||
if(hs == NULL)
|
||||
return false;
|
||||
|
||||
return IsValidMpqHandle(hs->ha);
|
||||
}
|
||||
|
||||
bool CheckWildCard(const char * szString, const char * szWildCard)
|
||||
{
|
||||
const char * szSubString;
|
||||
int nSubStringLength;
|
||||
int nMatchCount = 0;
|
||||
|
||||
// When the mask is empty, it never matches
|
||||
if(szWildCard == NULL || *szWildCard == 0)
|
||||
return false;
|
||||
|
||||
// If the wildcard contains just "*", then it always matches
|
||||
if(szWildCard[0] == '*' && szWildCard[1] == 0)
|
||||
return true;
|
||||
|
||||
// Do normal test
|
||||
for(;;)
|
||||
{
|
||||
// If there is '?' in the wildcard, we skip one char
|
||||
while(*szWildCard == '?')
|
||||
{
|
||||
szWildCard++;
|
||||
szString++;
|
||||
}
|
||||
|
||||
// If there is '*', means zero or more chars. We have to
|
||||
// find the sequence after '*'
|
||||
if(*szWildCard == '*')
|
||||
{
|
||||
// More stars is equal to one star
|
||||
while(*szWildCard == '*' || *szWildCard == '?')
|
||||
szWildCard++;
|
||||
|
||||
// If we found end of the wildcard, it's a match
|
||||
if(*szWildCard == 0)
|
||||
return true;
|
||||
|
||||
// Determine the length of the substring in szWildCard
|
||||
szSubString = szWildCard;
|
||||
while(*szSubString != 0 && *szSubString != '?' && *szSubString != '*')
|
||||
szSubString++;
|
||||
nSubStringLength = (int)(szSubString - szWildCard);
|
||||
nMatchCount = 0;
|
||||
|
||||
// Now we have to find a substring in szString,
|
||||
// that matches the substring in szWildCard
|
||||
while(*szString != 0)
|
||||
{
|
||||
// Calculate match count
|
||||
while(nMatchCount < nSubStringLength)
|
||||
{
|
||||
if(toupper(szString[nMatchCount]) != toupper(szWildCard[nMatchCount]))
|
||||
break;
|
||||
if(szString[nMatchCount] == 0)
|
||||
break;
|
||||
nMatchCount++;
|
||||
}
|
||||
|
||||
// If the match count has reached substring length, we found a match
|
||||
if(nMatchCount == nSubStringLength)
|
||||
{
|
||||
szWildCard += nMatchCount;
|
||||
szString += nMatchCount;
|
||||
break;
|
||||
}
|
||||
|
||||
// No match, move to the next char in szString
|
||||
nMatchCount = 0;
|
||||
szString++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we came to the end of the string, compare it to the wildcard
|
||||
if(toupper(*szString) != toupper(*szWildCard))
|
||||
return false;
|
||||
|
||||
// If we arrived to the end of the string, it's a match
|
||||
if(*szString == 0)
|
||||
return true;
|
||||
|
||||
// Otherwise, continue in comparing
|
||||
szWildCard++;
|
||||
szString++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD GetSearchTableItems(TMPQArchive * ha)
|
||||
{
|
||||
DWORD dwMergeItems = 0;
|
||||
|
||||
// Loop over all patches
|
||||
while(ha != NULL)
|
||||
{
|
||||
// Append the number of files
|
||||
dwMergeItems += (ha->pHetTable != NULL) ? ha->pHetTable->dwMaxFileCount
|
||||
: ha->pHeader->dwBlockTableSize;
|
||||
// Move to the patched archive
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
// Return the double size of number of items
|
||||
return (dwMergeItems | 1);
|
||||
}
|
||||
|
||||
static bool FileWasFoundBefore(
|
||||
TMPQArchive * ha,
|
||||
TMPQSearch * hs,
|
||||
TFileEntry * pFileEntry)
|
||||
{
|
||||
TFileEntry * pEntry;
|
||||
char * szRealFileName = pFileEntry->szFileName;
|
||||
DWORD dwStartIndex;
|
||||
DWORD dwNameHash;
|
||||
DWORD dwIndex;
|
||||
|
||||
if(hs->pSearchTable != NULL && szRealFileName != NULL)
|
||||
{
|
||||
// If we are in patch MPQ, we check if patch prefix matches
|
||||
// and then trim the patch prefix
|
||||
if(ha->cchPatchPrefix != 0)
|
||||
{
|
||||
// If the patch prefix doesn't fit, we pretend that the file
|
||||
// was there before and it will be skipped
|
||||
if(_strnicmp(szRealFileName, ha->szPatchPrefix, ha->cchPatchPrefix))
|
||||
return true;
|
||||
|
||||
szRealFileName += ha->cchPatchPrefix;
|
||||
}
|
||||
|
||||
// Calculate the hash to the table
|
||||
dwNameHash = HashString(szRealFileName, MPQ_HASH_NAME_A);
|
||||
dwStartIndex = dwIndex = (dwNameHash % hs->dwSearchTableItems);
|
||||
|
||||
// The file might have been found before
|
||||
// only if this is not the first MPQ being searched
|
||||
if(ha->haBase != NULL)
|
||||
{
|
||||
// Enumerate all entries in the search table
|
||||
for(;;)
|
||||
{
|
||||
// Get the file entry at that position
|
||||
pEntry = hs->pSearchTable[dwIndex];
|
||||
if(pEntry == NULL)
|
||||
break;
|
||||
|
||||
if(pEntry->szFileName != NULL)
|
||||
{
|
||||
// Does the name match?
|
||||
if(!_stricmp(pEntry->szFileName, szRealFileName))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Move to the next entry
|
||||
dwIndex = (dwIndex + 1) % hs->dwSearchTableItems;
|
||||
if(dwIndex == dwStartIndex)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Put the entry to the table for later use
|
||||
hs->pSearchTable[dwIndex] = pFileEntry;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TFileEntry * FindPatchEntry(TMPQArchive * ha, TFileEntry * pFileEntry)
|
||||
{
|
||||
TFileEntry * pPatchEntry = NULL;
|
||||
TFileEntry * pTempEntry;
|
||||
char szFileName[MAX_PATH];
|
||||
LCID lcLocale = pFileEntry->lcLocale;
|
||||
|
||||
// Go while there are patches
|
||||
while(ha->haPatch != NULL)
|
||||
{
|
||||
// Move to the patch archive
|
||||
ha = ha->haPatch;
|
||||
|
||||
// Prepare the prefix for the file name
|
||||
strcpy(szFileName, ha->szPatchPrefix);
|
||||
strcat(szFileName, pFileEntry->szFileName);
|
||||
|
||||
// Try to find the file there
|
||||
pTempEntry = GetFileEntryExact(ha, szFileName, lcLocale);
|
||||
if(pTempEntry != NULL)
|
||||
pPatchEntry = pTempEntry;
|
||||
}
|
||||
|
||||
// Return the found patch entry
|
||||
return pPatchEntry;
|
||||
}
|
||||
|
||||
// Performs one MPQ search
|
||||
static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TMPQArchive * ha = hs->ha;
|
||||
TFileEntry * pFileTableEnd;
|
||||
TFileEntry * pPatchEntry;
|
||||
TFileEntry * pFileEntry;
|
||||
const char * szFileName;
|
||||
HANDLE hFile;
|
||||
char szPseudoName[20];
|
||||
DWORD dwBlockIndex;
|
||||
size_t nPrefixLength;
|
||||
|
||||
// Start searching with base MPQ
|
||||
while(ha != NULL)
|
||||
{
|
||||
// Now parse the file entry table in order to get all files.
|
||||
pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
pFileEntry = ha->pFileTable + hs->dwNextIndex;
|
||||
|
||||
// Get the start and end of the hash table
|
||||
nPrefixLength = strlen(ha->szPatchPrefix);
|
||||
|
||||
// Parse the file table
|
||||
while(pFileEntry < pFileTableEnd)
|
||||
{
|
||||
// Increment the next index for subsequent search
|
||||
hs->dwNextIndex++;
|
||||
|
||||
// Is it a file and not a patch file?
|
||||
if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
|
||||
{
|
||||
// Now we have to check if this file was not enumerated before
|
||||
if(!FileWasFoundBefore(ha, hs, pFileEntry))
|
||||
{
|
||||
// Find a patch to this file
|
||||
pPatchEntry = FindPatchEntry(ha, pFileEntry);
|
||||
if(pPatchEntry == NULL)
|
||||
pPatchEntry = pFileEntry;
|
||||
|
||||
// Prepare the block index
|
||||
dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
|
||||
|
||||
// Get the file name. If it's not known, we will create pseudo-name
|
||||
szFileName = pFileEntry->szFileName;
|
||||
if(szFileName == NULL)
|
||||
{
|
||||
// Open the file by its pseudo-name.
|
||||
// This also generates the file name with a proper extension
|
||||
sprintf(szPseudoName, "File%08u.xxx", dwBlockIndex);
|
||||
if(SFileOpenFileEx((HANDLE)hs->ha, szPseudoName, SFILE_OPEN_FROM_MPQ, &hFile))
|
||||
{
|
||||
szFileName = (pFileEntry->szFileName != NULL) ? pFileEntry->szFileName : szPseudoName;
|
||||
SFileCloseFile(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the file name against the wildcard
|
||||
if(CheckWildCard(szFileName, hs->szSearchMask))
|
||||
{
|
||||
// Fill the found entry
|
||||
lpFindFileData->dwHashIndex = pPatchEntry->dwHashIndex;
|
||||
lpFindFileData->dwBlockIndex = dwBlockIndex;
|
||||
lpFindFileData->dwFileSize = pPatchEntry->dwFileSize;
|
||||
lpFindFileData->dwFileFlags = pPatchEntry->dwFlags;
|
||||
lpFindFileData->dwCompSize = pPatchEntry->dwCmpSize;
|
||||
lpFindFileData->lcLocale = pPatchEntry->lcLocale;
|
||||
|
||||
// Fill the filetime
|
||||
lpFindFileData->dwFileTimeHi = (DWORD)(pPatchEntry->FileTime >> 32);
|
||||
lpFindFileData->dwFileTimeLo = (DWORD)(pPatchEntry->FileTime);
|
||||
|
||||
// Fill the file name and plain file name
|
||||
strcpy(lpFindFileData->cFileName, szFileName + nPrefixLength);
|
||||
lpFindFileData->szPlainName = (char *)GetPlainFileNameA(lpFindFileData->cFileName);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pFileEntry++;
|
||||
}
|
||||
|
||||
// Move to the next patch in the patch chain
|
||||
hs->ha = ha = ha->haPatch;
|
||||
hs->dwNextIndex = 0;
|
||||
}
|
||||
|
||||
// No more files found, return error
|
||||
return ERROR_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
static void FreeMPQSearch(TMPQSearch *& hs)
|
||||
{
|
||||
if(hs != NULL)
|
||||
{
|
||||
if(hs->pSearchTable != NULL)
|
||||
FREEMEM(hs->pSearchTable);
|
||||
FREEMEM(hs);
|
||||
hs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TMPQSearch * hs = NULL;
|
||||
size_t nSize = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Check for the valid parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
nError = ERROR_INVALID_HANDLE;
|
||||
if(szMask == NULL || lpFindFileData == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Include the listfile into the MPQ's internal listfile
|
||||
// Note that if the listfile name is NULL, do nothing because the
|
||||
// internal listfile is always included.
|
||||
if(nError == ERROR_SUCCESS && szListFile != NULL && *szListFile != 0)
|
||||
nError = SFileAddListFile((HANDLE)ha, szListFile);
|
||||
|
||||
// Allocate the structure for MPQ search
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nSize = sizeof(TMPQSearch) + strlen(szMask) + 1;
|
||||
if((hs = (TMPQSearch *)ALLOCMEM(char, nSize)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Perform the first search
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(hs, 0, sizeof(TMPQSearch));
|
||||
strcpy(hs->szSearchMask, szMask);
|
||||
hs->dwFlagMask = MPQ_FILE_EXISTS;
|
||||
hs->ha = ha;
|
||||
|
||||
// If the archive is patched archive, we have to create a merge table
|
||||
// to prevent files being repeated
|
||||
if(ha->haPatch != NULL)
|
||||
{
|
||||
hs->dwSearchTableItems = GetSearchTableItems(ha);
|
||||
hs->pSearchTable = ALLOCMEM(TFileEntry *, hs->dwSearchTableItems);
|
||||
hs->dwFlagMask = MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE;
|
||||
if(hs->pSearchTable != NULL)
|
||||
memset(hs->pSearchTable, 0, hs->dwSearchTableItems * sizeof(TFileEntry *));
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform first item searching
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nError = DoMPQSearch(hs, lpFindFileData);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
FreeMPQSearch(hs);
|
||||
SetLastError(nError);
|
||||
}
|
||||
|
||||
// Return the result value
|
||||
return (HANDLE)hs;
|
||||
}
|
||||
|
||||
bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TMPQSearch * hs = (TMPQSearch *)hFind;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Check the parameters
|
||||
if(!IsValidSearchHandle(hs))
|
||||
nError = ERROR_INVALID_HANDLE;
|
||||
if(lpFindFileData == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
nError = DoMPQSearch(hs, lpFindFileData);
|
||||
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
bool WINAPI SFileFindClose(HANDLE hFind)
|
||||
{
|
||||
TMPQSearch * hs = (TMPQSearch *)hFind;
|
||||
|
||||
// Check the parameters
|
||||
if(!IsValidSearchHandle(hs))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
FreeMPQSearch(hs);
|
||||
return true;
|
||||
}
|
||||
554
src/dep/src/StormLib/src/SFileListFile.cpp
Normal file
554
src/dep/src/StormLib/src/SFileListFile.cpp
Normal file
@ -0,0 +1,554 @@
|
||||
/*****************************************************************************/
|
||||
/* SListFile.cpp Copyright (c) Ladislav Zezula 2004 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 12.06.04 1.00 Lad The first version of SListFile.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
#include <assert.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Listfile entry structure
|
||||
|
||||
#define CACHE_BUFFER_SIZE 0x1000 // Size of the cache buffer
|
||||
|
||||
struct TListFileCache
|
||||
{
|
||||
HANDLE hFile; // Stormlib file handle
|
||||
char * szMask; // File mask
|
||||
DWORD dwFileSize; // Total size of the cached file
|
||||
DWORD dwFilePos; // Position of the cache in the file
|
||||
BYTE * pBegin; // The begin of the listfile cache
|
||||
BYTE * pPos;
|
||||
BYTE * pEnd; // The last character in the file cache
|
||||
|
||||
BYTE Buffer[CACHE_BUFFER_SIZE]; // Listfile cache itself
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions (cache)
|
||||
|
||||
static TListFileCache * CreateListFileCache(HANDLE hMpq, const char * szListFile)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
HANDLE hListFile = NULL;
|
||||
DWORD dwSearchScope = SFILE_OPEN_LOCAL_FILE;
|
||||
DWORD dwBytesRead = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// If the szListFile is NULL, it means we have to open internal listfile
|
||||
if(szListFile == NULL)
|
||||
{
|
||||
// Use SFILE_OPEN_ANY_LOCALE for listfile. This will allow us to load
|
||||
// the listfile even if there is only non-neutral version of the listfile in the MPQ
|
||||
dwSearchScope = SFILE_OPEN_ANY_LOCALE;
|
||||
szListFile = LISTFILE_NAME;
|
||||
}
|
||||
|
||||
// Open the local/internal listfile
|
||||
if(SFileOpenFileEx(hMpq, szListFile, dwSearchScope, &hListFile))
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TMPQFile * hf = (TMPQFile *)hListFile;
|
||||
|
||||
// Remember flags for (listfile)
|
||||
if(hf->pFileEntry != NULL)
|
||||
ha->dwFileFlags1 = hf->pFileEntry->dwFlags;
|
||||
}
|
||||
else
|
||||
nError = GetLastError();
|
||||
|
||||
// Allocate cache for one file block
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pCache = (TListFileCache *)ALLOCMEM(TListFileCache, 1);
|
||||
if(pCache == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Initialize the file cache
|
||||
memset(pCache, 0, sizeof(TListFileCache));
|
||||
pCache->dwFileSize = SFileGetFileSize(hListFile, NULL);
|
||||
pCache->hFile = hListFile;
|
||||
|
||||
// Fill the cache
|
||||
SFileReadFile(hListFile, pCache->Buffer, CACHE_BUFFER_SIZE, &dwBytesRead, NULL);
|
||||
if(dwBytesRead == 0)
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Initialize the pointers
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
pCache->pBegin =
|
||||
pCache->pPos = &pCache->Buffer[0];
|
||||
pCache->pEnd = pCache->pBegin + dwBytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
SListFileFindClose((HANDLE)pCache);
|
||||
SetLastError(nError);
|
||||
pCache = NULL;
|
||||
}
|
||||
|
||||
// Return the cache
|
||||
return pCache;
|
||||
}
|
||||
|
||||
// Reloads the cache. Returns number of characters
|
||||
// that has been loaded into the cache.
|
||||
static DWORD ReloadListFileCache(TListFileCache * pCache)
|
||||
{
|
||||
DWORD dwBytesToRead;
|
||||
DWORD dwBytesRead = 0;
|
||||
|
||||
// Only do something if the cache is empty
|
||||
if(pCache->pPos >= pCache->pEnd)
|
||||
{
|
||||
// __TryReadBlock:
|
||||
|
||||
// Move the file position forward
|
||||
pCache->dwFilePos += CACHE_BUFFER_SIZE;
|
||||
if(pCache->dwFilePos >= pCache->dwFileSize)
|
||||
return 0;
|
||||
|
||||
// Get the number of bytes remaining
|
||||
dwBytesToRead = pCache->dwFileSize - pCache->dwFilePos;
|
||||
if(dwBytesToRead > CACHE_BUFFER_SIZE)
|
||||
dwBytesToRead = CACHE_BUFFER_SIZE;
|
||||
|
||||
// Load the next data chunk to the cache
|
||||
SFileSetFilePointer(pCache->hFile, pCache->dwFilePos, NULL, FILE_BEGIN);
|
||||
SFileReadFile(pCache->hFile, pCache->Buffer, CACHE_BUFFER_SIZE, &dwBytesRead, NULL);
|
||||
|
||||
// If we didn't read anything, it might mean that the block
|
||||
// of the file is not available (in case of partial MPQs).
|
||||
// We stop reading the file at this point, because the rest
|
||||
// of the listfile is unreliable
|
||||
if(dwBytesRead == 0)
|
||||
return 0;
|
||||
|
||||
// Set the buffer pointers
|
||||
pCache->pBegin =
|
||||
pCache->pPos = &pCache->Buffer[0];
|
||||
pCache->pEnd = pCache->pBegin + dwBytesRead;
|
||||
}
|
||||
|
||||
return dwBytesRead;
|
||||
}
|
||||
|
||||
static size_t ReadListFileLine(TListFileCache * pCache, char * szLine, int nMaxChars)
|
||||
{
|
||||
char * szLineBegin = szLine;
|
||||
char * szLineEnd = szLine + nMaxChars - 1;
|
||||
char * szExtraString = NULL;
|
||||
|
||||
// Skip newlines, spaces, tabs and another non-printable stuff
|
||||
for(;;)
|
||||
{
|
||||
// If we need to reload the cache, do it
|
||||
if(pCache->pPos == pCache->pEnd)
|
||||
{
|
||||
if(ReloadListFileCache(pCache) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// If we found a non-whitespace character, stop
|
||||
if(*pCache->pPos > 0x20)
|
||||
break;
|
||||
|
||||
// Skip the character
|
||||
pCache->pPos++;
|
||||
}
|
||||
|
||||
// Copy the remaining characters
|
||||
while(szLine < szLineEnd)
|
||||
{
|
||||
// If we need to reload the cache, do it now and resume copying
|
||||
if(pCache->pPos == pCache->pEnd)
|
||||
{
|
||||
if(ReloadListFileCache(pCache) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// If we have found a newline, stop loading
|
||||
if(*pCache->pPos == 0x0D || *pCache->pPos == 0x0A)
|
||||
break;
|
||||
|
||||
// Blizzard listfiles can also contain information about patch:
|
||||
// Pass1\Files\MacOS\unconditional\user\Background Downloader.app\Contents\Info.plist~Patch(Data#frFR#base-frFR,1326)
|
||||
if(*pCache->pPos == '~')
|
||||
szExtraString = szLine;
|
||||
|
||||
// Copy the character
|
||||
*szLine++ = *pCache->pPos++;
|
||||
}
|
||||
|
||||
// Terminate line with zero
|
||||
*szLine = 0;
|
||||
|
||||
// If there was extra string after the file name, clear it
|
||||
if(szExtraString != NULL)
|
||||
{
|
||||
if(szExtraString[0] == '~' && szExtraString[1] == 'P')
|
||||
{
|
||||
szLine = szExtraString;
|
||||
*szExtraString = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the length of the line
|
||||
return (szLine - szLineBegin);
|
||||
}
|
||||
|
||||
static int CompareFileNodes(const void * p1, const void * p2)
|
||||
{
|
||||
char * szFileName1 = *(char **)p1;
|
||||
char * szFileName2 = *(char **)p2;
|
||||
|
||||
return _stricmp(szFileName1, szFileName2);
|
||||
}
|
||||
|
||||
static int WriteListFileLine(
|
||||
TMPQFile * hf,
|
||||
const char * szLine)
|
||||
{
|
||||
char szNewLine[2] = {0x0D, 0x0A};
|
||||
size_t nLength = strlen(szLine);
|
||||
int nError;
|
||||
|
||||
nError = SFileAddFile_Write(hf, szLine, (DWORD)nLength, MPQ_COMPRESSION_ZLIB);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
return nError;
|
||||
|
||||
return SFileAddFile_Write(hf, szNewLine, sizeof(szNewLine), MPQ_COMPRESSION_ZLIB);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions (listfile nodes)
|
||||
|
||||
// Adds a name into the list of all names. For each locale in the MPQ,
|
||||
// one entry will be created
|
||||
// If the file name is already there, does nothing.
|
||||
int SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szFileName)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQHash * pFirstHash;
|
||||
TMPQHash * pHash;
|
||||
bool bNameEntryCreated = false;
|
||||
|
||||
// If we have HET table, use that one
|
||||
if(ha->pHetTable != NULL)
|
||||
{
|
||||
pFileEntry = GetFileEntryAny(ha, szFileName);
|
||||
if(pFileEntry != NULL)
|
||||
{
|
||||
// Allocate file name for the file entry
|
||||
AllocateFileName(pFileEntry, szFileName);
|
||||
bNameEntryCreated = true;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// If we have hash table, we use it
|
||||
if(bNameEntryCreated == false && ha->pHashTable != NULL)
|
||||
{
|
||||
// Look for the first hash table entry for the file
|
||||
pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
|
||||
|
||||
// Go while we found something
|
||||
while(pHash != NULL)
|
||||
{
|
||||
// Is it a valid file table index ?
|
||||
if(pHash->dwBlockIndex < pHeader->dwBlockTableSize)
|
||||
{
|
||||
// Allocate file name for the file entry
|
||||
AllocateFileName(ha->pFileTable + pHash->dwBlockIndex, szFileName);
|
||||
bNameEntryCreated = true;
|
||||
}
|
||||
|
||||
// Now find the next language version of the file
|
||||
pHash = GetNextHashEntry(ha, pFirstHash, pHash);
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
// Saves the whole listfile into the MPQ.
|
||||
int SListFileSaveToMpq(TMPQArchive * ha)
|
||||
{
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQFile * hf = NULL;
|
||||
char * szPrevItem;
|
||||
char ** SortTable = NULL;
|
||||
DWORD dwFileSize = 0;
|
||||
size_t nFileNodes = 0;
|
||||
size_t i;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Allocate the table for sorting listfile
|
||||
SortTable = ALLOCMEM(char*, ha->dwFileTableSize);
|
||||
if(SortTable == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Construct the sort table
|
||||
// Note: in MPQs with multiple locale versions of the same file,
|
||||
// this code causes adding multiple listfile entries.
|
||||
// Since those MPQs were last time used in Starcraft,
|
||||
// we leave it as it is.
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
// Only take existing items
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && pFileEntry->szFileName != NULL)
|
||||
{
|
||||
// Ignore pseudo-names
|
||||
if(!IsPseudoFileName(pFileEntry->szFileName, NULL) && !IsInternalMpqFileName(pFileEntry->szFileName))
|
||||
{
|
||||
SortTable[nFileNodes++] = pFileEntry->szFileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the table
|
||||
qsort(SortTable, nFileNodes, sizeof(char *), CompareFileNodes);
|
||||
|
||||
// Now parse the table of file names again - remove duplicates
|
||||
// and count file size.
|
||||
if(nFileNodes != 0)
|
||||
{
|
||||
// Count the 0-th item
|
||||
dwFileSize += (DWORD)strlen(SortTable[0]) + 2;
|
||||
szPrevItem = SortTable[0];
|
||||
|
||||
// Count all next items
|
||||
for(i = 1; i < nFileNodes; i++)
|
||||
{
|
||||
// If the item is the same like the last one, skip it
|
||||
if(_stricmp(SortTable[i], szPrevItem))
|
||||
{
|
||||
dwFileSize += (DWORD)strlen(SortTable[i]) + 2;
|
||||
szPrevItem = SortTable[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Create the listfile in the MPQ
|
||||
assert(ha->dwFileFlags1 != 0);
|
||||
nError = SFileAddFile_Init(ha, LISTFILE_NAME,
|
||||
0,
|
||||
dwFileSize,
|
||||
LANG_NEUTRAL,
|
||||
ha->dwFileFlags1,
|
||||
&hf);
|
||||
// Add all file names
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Each name is followed by newline ("\x0D\x0A")
|
||||
szPrevItem = SortTable[0];
|
||||
nError = WriteListFileLine(hf, SortTable[0]);
|
||||
|
||||
// Count all next items
|
||||
for(i = 1; i < nFileNodes; i++)
|
||||
{
|
||||
// If the item is the same like the last one, skip it
|
||||
if(_stricmp(SortTable[i], szPrevItem))
|
||||
{
|
||||
WriteListFileLine(hf, SortTable[i]);
|
||||
szPrevItem = SortTable[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create the listfile in the MPQ
|
||||
dwFileSize = (DWORD)strlen(LISTFILE_NAME) + 2;
|
||||
nError = SFileAddFile_Init(ha, LISTFILE_NAME,
|
||||
0,
|
||||
dwFileSize,
|
||||
LANG_NEUTRAL,
|
||||
MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING,
|
||||
&hf);
|
||||
|
||||
// Just add "(listfile)" there
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
WriteListFileLine(hf, LISTFILE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the file in the MPQ
|
||||
if(hf != NULL)
|
||||
{
|
||||
SFileAddFile_Finish(hf);
|
||||
}
|
||||
|
||||
// Free buffers
|
||||
if(nError == ERROR_SUCCESS)
|
||||
ha->dwFlags &= ~MPQ_FLAG_INV_LISTFILE;
|
||||
if(SortTable != NULL)
|
||||
FREEMEM(SortTable);
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File functions
|
||||
|
||||
// Adds a listfile into the MPQ archive.
|
||||
// Note that the function does not remove the
|
||||
int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
char szFileName[MAX_PATH];
|
||||
size_t nLength = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Add the listfile for each MPQ in the patch chain
|
||||
while(ha != NULL)
|
||||
{
|
||||
// Load the listfile to cache
|
||||
pCache = CreateListFileCache(hMpq, szListFile);
|
||||
if(pCache == NULL)
|
||||
{
|
||||
nError = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Load the node list. Add the node for every locale in the archive
|
||||
while((nLength = ReadListFileLine(pCache, szFileName, sizeof(szFileName))) > 0)
|
||||
SListFileCreateNodeForAllLocales(ha, szFileName);
|
||||
|
||||
// Also, add three special files to the listfile:
|
||||
// (listfile) itself, (attributes) and (signature)
|
||||
SListFileCreateNodeForAllLocales(ha, LISTFILE_NAME);
|
||||
SListFileCreateNodeForAllLocales(ha, SIGNATURE_NAME);
|
||||
SListFileCreateNodeForAllLocales(ha, ATTRIBUTES_NAME);
|
||||
|
||||
// Delete the cache
|
||||
SListFileFindClose((HANDLE)pCache);
|
||||
|
||||
// Move to the next archive in the chain
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Passing through the listfile
|
||||
|
||||
HANDLE WINAPI SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TListFileCache * pCache = NULL;
|
||||
size_t nLength = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Initialize the structure with zeros
|
||||
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
|
||||
|
||||
// Load the listfile to cache
|
||||
pCache = CreateListFileCache(hMpq, szListFile);
|
||||
if(pCache == NULL)
|
||||
nError = GetLastError();
|
||||
|
||||
// Allocate file mask
|
||||
if(nError == ERROR_SUCCESS && szMask != NULL)
|
||||
{
|
||||
pCache->szMask = ALLOCMEM(char, strlen(szMask) + 1);
|
||||
if(pCache->szMask != NULL)
|
||||
strcpy(pCache->szMask, szMask);
|
||||
else
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Perform file search
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
// Read the (next) line
|
||||
nLength = ReadListFileLine(pCache, lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName));
|
||||
if(nLength == 0)
|
||||
{
|
||||
nError = ERROR_NO_MORE_FILES;
|
||||
break;
|
||||
}
|
||||
|
||||
// If some mask entered, check it
|
||||
if(CheckWildCard(lpFindFileData->cFileName, pCache->szMask))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup & exit
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
|
||||
SListFileFindClose((HANDLE)pCache);
|
||||
pCache = NULL;
|
||||
|
||||
SetLastError(nError);
|
||||
}
|
||||
return (HANDLE)pCache;
|
||||
}
|
||||
|
||||
bool WINAPI SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
|
||||
{
|
||||
TListFileCache * pCache = (TListFileCache *)hFind;
|
||||
size_t nLength;
|
||||
bool bResult = false;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// Read the (next) line
|
||||
nLength = ReadListFileLine(pCache, lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName));
|
||||
if(nLength == 0)
|
||||
{
|
||||
nError = ERROR_NO_MORE_FILES;
|
||||
break;
|
||||
}
|
||||
|
||||
// If some mask entered, check it
|
||||
if(CheckWildCard(lpFindFileData->cFileName, pCache->szMask))
|
||||
{
|
||||
bResult = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool WINAPI SListFileFindClose(HANDLE hFind)
|
||||
{
|
||||
TListFileCache * pCache = (TListFileCache *)hFind;
|
||||
|
||||
if(pCache != NULL)
|
||||
{
|
||||
if(pCache->hFile != NULL)
|
||||
SFileCloseFile(pCache->hFile);
|
||||
if(pCache->szMask != NULL)
|
||||
FREEMEM(pCache->szMask);
|
||||
|
||||
FREEMEM(pCache);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
439
src/dep/src/StormLib/src/SFileOpenArchive.cpp
Normal file
439
src/dep/src/StormLib/src/SFileOpenArchive.cpp
Normal file
@ -0,0 +1,439 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileOpenArchive.cpp Copyright Ladislav Zezula 1999 */
|
||||
/* */
|
||||
/* Author : Ladislav Zezula */
|
||||
/* E-mail : ladik@zezula.net */
|
||||
/* WWW : www.zezula.net */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Archive functions of Storm.dll */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */
|
||||
/* 19.11.03 1.01 Dan Big endian handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
static bool IsAviFile(void * pvFileBegin)
|
||||
{
|
||||
LPDWORD AviHeader = (DWORD *)pvFileBegin;
|
||||
DWORD DwordValue0 = BSWAP_INT32_UNSIGNED(AviHeader[0]);
|
||||
DWORD DwordValue2 = BSWAP_INT32_UNSIGNED(AviHeader[2]);
|
||||
DWORD DwordValue3 = BSWAP_INT32_UNSIGNED(AviHeader[3]);
|
||||
|
||||
// Test for 'RIFF', 'AVI ' or 'LIST'
|
||||
return (DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C);
|
||||
}
|
||||
|
||||
// This function gets the right positions of the hash table and the block table.
|
||||
static int VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
ULONGLONG ByteOffset;
|
||||
|
||||
// Check the begin of HET table
|
||||
if(pHeader->HetTablePos64)
|
||||
{
|
||||
ByteOffset = ha->MpqPos + pHeader->HetTablePos64;
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Check the begin of BET table
|
||||
if(pHeader->BetTablePos64)
|
||||
{
|
||||
ByteOffset = ha->MpqPos + pHeader->BetTablePos64;
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Check the begin of hash table
|
||||
if(pHeader->wHashTablePosHi || pHeader->dwHashTablePos)
|
||||
{
|
||||
ByteOffset = ha->MpqPos + MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Check the begin of block table
|
||||
if(pHeader->wBlockTablePosHi || pHeader->dwBlockTablePos)
|
||||
{
|
||||
ByteOffset = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Check the begin of hi-block table
|
||||
if(pHeader->HiBlockTablePos64 != 0)
|
||||
{
|
||||
ByteOffset = ha->MpqPos + pHeader->HiBlockTablePos64;
|
||||
if(ByteOffset > FileSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// All OK.
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileGetLocale and SFileSetLocale
|
||||
// Set the locale for all newly opened files
|
||||
|
||||
DWORD WINAPI SFileGetGlobalFlags()
|
||||
{
|
||||
return dwGlobalFlags;
|
||||
}
|
||||
|
||||
DWORD WINAPI SFileSetGlobalFlags(DWORD dwNewFlags)
|
||||
{
|
||||
DWORD dwOldFlags = dwGlobalFlags;
|
||||
|
||||
dwGlobalFlags = dwNewFlags;
|
||||
return dwOldFlags;
|
||||
}
|
||||
|
||||
LCID WINAPI SFileGetLocale()
|
||||
{
|
||||
return lcFileLocale;
|
||||
}
|
||||
|
||||
LCID WINAPI SFileSetLocale(LCID lcNewLocale)
|
||||
{
|
||||
lcFileLocale = lcNewLocale;
|
||||
return lcFileLocale;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileOpenArchive
|
||||
//
|
||||
// szFileName - MPQ archive file name to open
|
||||
// dwPriority - When SFileOpenFileEx called, this contains the search priority for searched archives
|
||||
// dwFlags - See MPQ_OPEN_XXX in StormLib.h
|
||||
// phMpq - Pointer to store open archive handle
|
||||
|
||||
bool WINAPI SFileOpenArchive(
|
||||
const TCHAR * szMpqName,
|
||||
DWORD dwPriority,
|
||||
DWORD dwFlags,
|
||||
HANDLE * phMpq)
|
||||
{
|
||||
TFileStream * pStream = NULL; // Open file stream
|
||||
TMPQArchive * ha = NULL; // Archive handle
|
||||
ULONGLONG FileSize = 0; // Size of the file
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Verify the parameters
|
||||
if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// One time initialization of MPQ cryptography
|
||||
InitializeMpqCryptography();
|
||||
dwPriority = dwPriority;
|
||||
|
||||
// Open the MPQ archive file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!(dwFlags & MPQ_OPEN_ENCRYPTED))
|
||||
{
|
||||
pStream = FileStream_OpenFile(szMpqName, (dwFlags & MPQ_OPEN_READ_ONLY) ? false : true);
|
||||
if(pStream == NULL)
|
||||
nError = GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
pStream = FileStream_OpenEncrypted(szMpqName);
|
||||
if(pStream == NULL)
|
||||
nError = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the MPQhandle
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
FileStream_GetSize(pStream, FileSize);
|
||||
if((ha = ALLOCMEM(TMPQArchive, 1)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Initialize handle structure and allocate structure for MPQ header
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(ha, 0, sizeof(TMPQArchive));
|
||||
ha->pStream = pStream;
|
||||
pStream = NULL;
|
||||
|
||||
// Remember if the archive is open for write
|
||||
if(ha->pStream->StreamFlags & (STREAM_FLAG_READ_ONLY | STREAM_FLAG_ENCRYPTED_FILE))
|
||||
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
|
||||
|
||||
// Also remember if we shall check sector CRCs when reading file
|
||||
if(dwFlags & MPQ_OPEN_CHECK_SECTOR_CRC)
|
||||
ha->dwFlags |= MPQ_FLAG_CHECK_SECTOR_CRC;
|
||||
}
|
||||
|
||||
// Find the offset of MPQ header within the file
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
ULONGLONG SearchPos = 0;
|
||||
DWORD dwHeaderID;
|
||||
|
||||
while(SearchPos < FileSize)
|
||||
{
|
||||
DWORD dwBytesAvailable = MPQ_HEADER_SIZE_V4;
|
||||
|
||||
// Cut the bytes available, if needed
|
||||
if((FileSize - SearchPos) < MPQ_HEADER_SIZE_V4)
|
||||
dwBytesAvailable = (DWORD)(FileSize - SearchPos);
|
||||
|
||||
// Read the eventual MPQ header
|
||||
if(!FileStream_Read(ha->pStream, &SearchPos, ha->HeaderData, dwBytesAvailable))
|
||||
{
|
||||
nError = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// There are AVI files from Warcraft III with 'MPQ' extension.
|
||||
if(SearchPos == 0 && IsAviFile(ha->HeaderData))
|
||||
{
|
||||
nError = ERROR_AVI_FILE;
|
||||
break;
|
||||
}
|
||||
|
||||
// If there is the MPQ user data signature, process it
|
||||
dwHeaderID = BSWAP_INT32_UNSIGNED(*(LPDWORD)ha->HeaderData);
|
||||
if(dwHeaderID == ID_MPQ_USERDATA && ha->pUserData == NULL)
|
||||
{
|
||||
// Ignore the MPQ user data completely if the caller wants to open the MPQ as V1.0
|
||||
if((dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0)
|
||||
{
|
||||
// Fill the user data header
|
||||
ha->pUserData = &ha->UserData;
|
||||
memcpy(ha->pUserData, ha->HeaderData, sizeof(TMPQUserData));
|
||||
BSWAP_TMPQUSERDATA(ha->pUserData);
|
||||
|
||||
// Remember the position of the user data and continue search
|
||||
ha->UserDataPos = SearchPos;
|
||||
SearchPos += ha->pUserData->dwHeaderOffs;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// There must be MPQ header signature
|
||||
if(dwHeaderID == ID_MPQ)
|
||||
{
|
||||
// Save the position where the MPQ header has been found
|
||||
if(ha->pUserData == NULL)
|
||||
ha->UserDataPos = SearchPos;
|
||||
ha->pHeader = (TMPQHeader *)ha->HeaderData;
|
||||
ha->MpqPos = SearchPos;
|
||||
|
||||
// Now convert the header to version 4
|
||||
BSWAP_TMPQHEADER(ha->pHeader);
|
||||
ConvertMpqHeaderToFormat4(ha, FileSize, dwFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
// Move to the next possible offset
|
||||
SearchPos += 0x200;
|
||||
}
|
||||
|
||||
// If we haven't found MPQ header in the file, it's an error
|
||||
if(ha->pHeader == NULL)
|
||||
nError = ERROR_BAD_FORMAT;
|
||||
}
|
||||
|
||||
// Fix table positions according to format
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Dump the header
|
||||
// DumpMpqHeader(ha->pHeader);
|
||||
|
||||
// W3x Map Protectors use the fact that War3's Storm.dll ignores the MPQ user data,
|
||||
// and probably ignores the MPQ format version as well. The trick is to
|
||||
// fake MPQ format 2, with an improper hi-word position of hash table and block table
|
||||
// We can overcome such protectors by forcing opening the archive as MPQ v 1.0
|
||||
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
|
||||
{
|
||||
ha->pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
|
||||
ha->pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
|
||||
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
|
||||
ha->pUserData = NULL;
|
||||
}
|
||||
|
||||
// Both MPQ_OPEN_NO_LISTFILE or MPQ_OPEN_NO_ATTRIBUTES trigger read only mode
|
||||
if(dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES))
|
||||
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
|
||||
|
||||
// Set the default file flags for (listfile) and (attributes)
|
||||
ha->dwFileFlags1 =
|
||||
ha->dwFileFlags2 = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING;
|
||||
|
||||
// Set the size of file sector
|
||||
ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize);
|
||||
|
||||
// Verify if any of the tables doesn't start beyond the end of the file
|
||||
nError = VerifyMpqTablePositions(ha, FileSize);
|
||||
}
|
||||
|
||||
// Read the hash table. Ignore the result, as hash table is no longer required
|
||||
// Read HET table. Ignore the result, as HET table is no longer required
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nError = LoadAnyHashTable(ha);
|
||||
}
|
||||
|
||||
// Now, build the file table. It will be built by combining
|
||||
// the block table, BET table, hi-block table, (attributes) and (listfile).
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
nError = BuildFileTable(ha, FileSize);
|
||||
}
|
||||
|
||||
// Verify the file table, if no kind of protection was detected
|
||||
if(nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_PROTECTED) == 0)
|
||||
{
|
||||
TFileEntry * pFileTableEnd = ha->pFileTable + ha->pHeader->dwBlockTableSize;
|
||||
TFileEntry * pFileEntry = ha->pFileTable;
|
||||
// ULONGLONG ArchiveSize = 0;
|
||||
ULONGLONG RawFilePos;
|
||||
|
||||
// Parse all file entries
|
||||
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
|
||||
{
|
||||
// If that file entry is valid, check the file position
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
|
||||
{
|
||||
// Get the 64-bit file position,
|
||||
// relative to the begin of the file
|
||||
RawFilePos = ha->MpqPos + pFileEntry->ByteOffset;
|
||||
|
||||
// Begin of the file must be within range
|
||||
if(RawFilePos > FileSize)
|
||||
{
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
break;
|
||||
}
|
||||
|
||||
// End of the file must be within range
|
||||
RawFilePos += pFileEntry->dwCmpSize;
|
||||
if(RawFilePos > FileSize)
|
||||
{
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Also, we remember end of the file
|
||||
// if(RawFilePos > ArchiveSize)
|
||||
// ArchiveSize = RawFilePos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the internal listfile and include it to the file table
|
||||
if(nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_LISTFILE) == 0)
|
||||
{
|
||||
// Ignore result of the operation. (listfile) is optional.
|
||||
SFileAddListFile((HANDLE)ha, NULL);
|
||||
}
|
||||
|
||||
// Load the "(attributes)" file and merge it to the file table
|
||||
if(nError == ERROR_SUCCESS && (dwFlags & MPQ_OPEN_NO_ATTRIBUTES) == 0)
|
||||
{
|
||||
// Ignore result of the operation. (attributes) is optional.
|
||||
SAttrLoadAttributes(ha);
|
||||
}
|
||||
|
||||
// Cleanup and exit
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
FileStream_Close(pStream);
|
||||
FreeMPQArchive(ha);
|
||||
SetLastError(nError);
|
||||
ha = NULL;
|
||||
}
|
||||
|
||||
*phMpq = ha;
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bool SFileFlushArchive(HANDLE hMpq)
|
||||
//
|
||||
// Saves all dirty data into MPQ archive.
|
||||
// Has similar effect like SFileCloseArchive, but the archive is not closed.
|
||||
// Use on clients who keep MPQ archive open even for write operations,
|
||||
// and terminating without calling SFileCloseArchive might corrupt the archive.
|
||||
//
|
||||
|
||||
bool WINAPI SFileFlushArchive(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
int nResultError = ERROR_SUCCESS;
|
||||
int nError;
|
||||
|
||||
// Do nothing if 'hMpq' is bad parameter
|
||||
if(!IsValidMpqHandle(ha))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the (listfile) has been invalidated, save it
|
||||
if(ha->dwFlags & MPQ_FLAG_INV_LISTFILE)
|
||||
{
|
||||
nError = SListFileSaveToMpq(ha);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
nResultError = nError;
|
||||
}
|
||||
|
||||
// If the (attributes) has been invalidated, save it
|
||||
if(ha->dwFlags & MPQ_FLAG_INV_ATTRIBUTES)
|
||||
{
|
||||
nError = SAttrFileSaveToMpq(ha);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
nResultError = nError;
|
||||
}
|
||||
|
||||
// Save HET table, BET table, hash table, block table, hi-block table
|
||||
if(ha->dwFlags & MPQ_FLAG_CHANGED)
|
||||
{
|
||||
nError = SaveMPQTables(ha);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
nResultError = nError;
|
||||
}
|
||||
|
||||
// Return the error
|
||||
if(nResultError != ERROR_SUCCESS)
|
||||
SetLastError(nResultError);
|
||||
return (nResultError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bool SFileCloseArchive(HANDLE hMpq);
|
||||
//
|
||||
|
||||
bool WINAPI SFileCloseArchive(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
bool bResult;
|
||||
|
||||
// Flush all unsaved data to the storage
|
||||
bResult = SFileFlushArchive(hMpq);
|
||||
|
||||
// Free all memory used by MPQ archive
|
||||
FreeMPQArchive(ha);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
449
src/dep/src/StormLib/src/SFileOpenFileEx.cpp
Normal file
449
src/dep/src/StormLib/src/SFileOpenFileEx.cpp
Normal file
@ -0,0 +1,449 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileOpenFileEx.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.99 1.00 Lad The first version of SFileOpenFileEx.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Local functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
static bool OpenLocalFile(const char * szFileName, HANDLE * phFile)
|
||||
{
|
||||
TFileStream * pStream;
|
||||
TMPQFile * hf = NULL;
|
||||
|
||||
// We have to convert the local file name to UNICODE, if needed
|
||||
#ifdef _UNICODE
|
||||
TCHAR szFileNameT[MAX_PATH];
|
||||
int i;
|
||||
|
||||
for(i = 0; szFileName[i] != 0; i++)
|
||||
szFileNameT[i] = szFileName[i];
|
||||
szFileNameT[i] = 0;
|
||||
pStream = FileStream_OpenFile(szFileNameT, false);
|
||||
|
||||
#else
|
||||
pStream = FileStream_OpenFile(szFileName, false);
|
||||
#endif
|
||||
|
||||
if(pStream != NULL)
|
||||
{
|
||||
// Allocate and initialize file handle
|
||||
hf = CreateMpqFile(NULL);
|
||||
if(hf != NULL)
|
||||
{
|
||||
hf->pStream = pStream;
|
||||
*phFile = hf;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileStream_Close(pStream);
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
}
|
||||
}
|
||||
*phFile = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, DWORD dwReserved, HANDLE * phFile)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TMPQFile * hfPatch; // Pointer to patch file
|
||||
TMPQFile * hfBase = NULL; // Pointer to base open file
|
||||
TMPQFile * hfLast = NULL; // The highest file in the chain that is not patch file
|
||||
TMPQFile * hf = NULL;
|
||||
HANDLE hPatchFile;
|
||||
char szPatchFileName[MAX_PATH];
|
||||
|
||||
// Keep this flag here for future updates
|
||||
dwReserved = dwReserved;
|
||||
|
||||
// First of all, try to open the original version of the file in any of the patch chain
|
||||
while(ha != NULL)
|
||||
{
|
||||
// Construct the name of the patch file
|
||||
strcpy(szPatchFileName, ha->szPatchPrefix);
|
||||
strcat(szPatchFileName, szFileName);
|
||||
if(SFileOpenFileEx((HANDLE)ha, szPatchFileName, SFILE_OPEN_FROM_MPQ, (HANDLE *)&hfBase))
|
||||
{
|
||||
// The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE
|
||||
if((hfBase->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
|
||||
{
|
||||
hf = hfLast = hfBase;
|
||||
break;
|
||||
}
|
||||
|
||||
SFileCloseFile((HANDLE)hfBase);
|
||||
}
|
||||
|
||||
// Move to the next file in the patch chain
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
// If we couldn't find the file in any of the patches, it doesn't exist
|
||||
if(hf == NULL)
|
||||
{
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now keep going in the patch chain and open every patch file that is there
|
||||
for(ha = ha->haPatch; ha != NULL; ha = ha->haPatch)
|
||||
{
|
||||
// Construct patch file name
|
||||
strcpy(szPatchFileName, ha->szPatchPrefix);
|
||||
strcat(szPatchFileName, szFileName);
|
||||
if(SFileOpenFileEx((HANDLE)ha, szPatchFileName, SFILE_OPEN_FROM_MPQ, &hPatchFile))
|
||||
{
|
||||
// Remember the new version
|
||||
hfPatch = (TMPQFile *)hPatchFile;
|
||||
|
||||
// If we encountered a full replacement of the file,
|
||||
// we have to remember the highest full file
|
||||
if((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
|
||||
hfLast = hfPatch;
|
||||
|
||||
// Set current patch to base file and move on
|
||||
hf->hfPatchFile = hfPatch;
|
||||
hf = hfPatch;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we need to free all files that are below the highest unpatched version
|
||||
while(hfBase != hfLast)
|
||||
{
|
||||
TMPQFile * hfNext = hfBase->hfPatchFile;
|
||||
|
||||
// Free the file below
|
||||
hfBase->hfPatchFile = NULL;
|
||||
FreeMPQFile(hfBase);
|
||||
|
||||
// Move the base to the next file
|
||||
hfBase = hfNext;
|
||||
}
|
||||
|
||||
// Give the updated base MPQ
|
||||
if(phFile != NULL)
|
||||
*phFile = (HANDLE)hfBase;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileEnumLocales enums all locale versions within MPQ.
|
||||
// Functions fills all available language identifiers on a file into the buffer
|
||||
// pointed by plcLocales. There must be enough entries to copy the localed,
|
||||
// otherwise the function returns ERROR_INSUFFICIENT_BUFFER.
|
||||
|
||||
int WINAPI SFileEnumLocales(
|
||||
HANDLE hMpq,
|
||||
const char * szFileName,
|
||||
LCID * plcLocales,
|
||||
LPDWORD pdwMaxLocales,
|
||||
DWORD dwSearchScope)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQHash * pFirstHash;
|
||||
TMPQHash * pHash;
|
||||
DWORD dwFileIndex = 0;
|
||||
DWORD dwLocales = 0;
|
||||
|
||||
// Test the parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
return ERROR_INVALID_HANDLE;
|
||||
if(szFileName == NULL || *szFileName == 0)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
if(pdwMaxLocales == NULL)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Keep compiler happy
|
||||
dwSearchScope = dwSearchScope;
|
||||
|
||||
// Parse hash table entries for all locales
|
||||
if(!IsPseudoFileName(szFileName, &dwFileIndex))
|
||||
{
|
||||
// Calculate the number of locales
|
||||
pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
|
||||
while(pHash != NULL)
|
||||
{
|
||||
dwLocales++;
|
||||
pHash = GetNextHashEntry(ha, pFirstHash, pHash);
|
||||
}
|
||||
|
||||
// Test if there is enough space to copy the locales
|
||||
if(*pdwMaxLocales < dwLocales)
|
||||
{
|
||||
*pdwMaxLocales = dwLocales;
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
// Enum the locales
|
||||
pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
|
||||
while(pHash != NULL)
|
||||
{
|
||||
*plcLocales++ = pHash->lcLocale;
|
||||
pHash = GetNextHashEntry(ha, pFirstHash, pHash);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There must be space for 1 locale
|
||||
if(*pdwMaxLocales < 1)
|
||||
{
|
||||
*pdwMaxLocales = 1;
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
// For nameless access, always return 1 locale
|
||||
pFileEntry = GetFileEntryByIndex(ha, dwFileIndex);
|
||||
pHash = ha->pHashTable + pFileEntry->dwHashIndex;
|
||||
*plcLocales = pHash->lcLocale;
|
||||
dwLocales = 1;
|
||||
}
|
||||
|
||||
// Give the caller the total number of found locales
|
||||
*pdwMaxLocales = dwLocales;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileHasFile
|
||||
//
|
||||
// hMpq - Handle of opened MPQ archive
|
||||
// szFileName - Name of file to look for
|
||||
|
||||
bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
DWORD dwFileIndex = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
if(!IsValidMpqHandle(ha))
|
||||
nError = ERROR_INVALID_HANDLE;
|
||||
if(szFileName == NULL || *szFileName == 0)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Prepare the file opening
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!IsPseudoFileName(szFileName, &dwFileIndex))
|
||||
{
|
||||
if(GetFileEntryLocale(ha, szFileName, lcFileLocale) == NULL)
|
||||
{
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GetFileEntryByIndex(ha, dwFileIndex) == NULL)
|
||||
{
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if(nError != ERROR_SUCCESS)
|
||||
SetLastError(nError);
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SFileOpenFileEx
|
||||
//
|
||||
// hMpq - Handle of opened MPQ archive
|
||||
// szFileName - Name of file to open
|
||||
// dwSearchScope - Where to search
|
||||
// phFile - Pointer to store opened file handle
|
||||
|
||||
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TFileEntry * pFileEntry = NULL;
|
||||
TMPQFile * hf = NULL;
|
||||
DWORD dwFileIndex = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Don't accept NULL pointer to file handle
|
||||
if(phFile == NULL)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Prepare the file opening
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
switch(dwSearchScope)
|
||||
{
|
||||
case SFILE_OPEN_PATCHED_FILE:
|
||||
|
||||
// We want to open the updated version of the file
|
||||
return OpenPatchedFile(hMpq, szFileName, 0, phFile);
|
||||
|
||||
case SFILE_OPEN_FROM_MPQ:
|
||||
|
||||
if(!IsValidMpqHandle(ha))
|
||||
{
|
||||
nError = ERROR_INVALID_HANDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
if(szFileName == NULL || *szFileName == 0)
|
||||
{
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
// First of all, check the name as-is
|
||||
if(!IsPseudoFileName(szFileName, &dwFileIndex))
|
||||
{
|
||||
pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale);
|
||||
if(pFileEntry == NULL)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
pFileEntry = GetFileEntryByIndex(ha, dwFileIndex);
|
||||
if(pFileEntry == NULL)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
break;
|
||||
|
||||
case SFILE_OPEN_ANY_LOCALE:
|
||||
|
||||
// This open option is reserved for opening MPQ internal listfile.
|
||||
// No argument validation. Tries to open file with neutral locale first,
|
||||
// then any other available.
|
||||
dwSearchScope = SFILE_OPEN_FROM_MPQ;
|
||||
pFileEntry = GetFileEntryAny(ha, szFileName);
|
||||
if(pFileEntry == NULL)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
|
||||
case SFILE_OPEN_LOCAL_FILE:
|
||||
|
||||
if(szFileName == NULL || *szFileName == 0)
|
||||
{
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return OpenLocalFile(szFileName, phFile);
|
||||
|
||||
default:
|
||||
|
||||
// Don't accept any other value
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
// Quick return if something failed
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError(nError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Test if the file was not already deleted.
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
|
||||
nError = ERROR_FILE_NOT_FOUND;
|
||||
if(pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
|
||||
nError = ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Allocate file handle
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((hf = ALLOCMEM(TMPQFile, 1)) == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Initialize file handle
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
memset(hf, 0, sizeof(TMPQFile));
|
||||
hf->pFileEntry = pFileEntry;
|
||||
hf->dwMagic = ID_MPQ_FILE;
|
||||
hf->ha = ha;
|
||||
|
||||
hf->MpqFilePos = pFileEntry->ByteOffset;
|
||||
hf->RawFilePos = ha->MpqPos + hf->MpqFilePos;
|
||||
hf->dwDataSize = pFileEntry->dwFileSize;
|
||||
|
||||
// If the MPQ has sector CRC enabled, enable if for the file
|
||||
if(ha->dwFlags & MPQ_FLAG_CHECK_SECTOR_CRC)
|
||||
hf->bCheckSectorCRCs = true;
|
||||
|
||||
// Decrypt file key. Cannot be used if the file is given by index
|
||||
if(pFileEntry->szFileName != NULL)
|
||||
{
|
||||
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
|
||||
{
|
||||
if(!IsPseudoFileName(szFileName, NULL))
|
||||
{
|
||||
hf->dwFileKey = DecryptFileKey(szFileName,
|
||||
pFileEntry->ByteOffset,
|
||||
pFileEntry->dwFileSize,
|
||||
pFileEntry->dwFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to auto-detect the file name
|
||||
if(!SFileGetFileName(hf, NULL))
|
||||
nError = GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
// If the file is actually a patch file, we have to load the patch file header
|
||||
if(nError == ERROR_SUCCESS && pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE)
|
||||
{
|
||||
assert(hf->pPatchInfo == NULL);
|
||||
nError = AllocatePatchInfo(hf, true);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if(nError != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError(nError);
|
||||
FreeMPQFile(hf);
|
||||
}
|
||||
|
||||
*phFile = hf;
|
||||
return (nError == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// bool WINAPI SFileCloseFile(HANDLE hFile);
|
||||
|
||||
bool WINAPI SFileCloseFile(HANDLE hFile)
|
||||
{
|
||||
TMPQFile * hf = (TMPQFile *)hFile;
|
||||
|
||||
if(!IsValidFileHandle(hf))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Free the structure
|
||||
FreeMPQFile(hf);
|
||||
return true;
|
||||
}
|
||||
632
src/dep/src/StormLib/src/SFilePatchArchives.cpp
Normal file
632
src/dep/src/StormLib/src/SFilePatchArchives.cpp
Normal file
@ -0,0 +1,632 @@
|
||||
/*****************************************************************************/
|
||||
/* SFilePatchArchives.cpp Copyright (c) Ladislav Zezula 2010 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 18.08.10 1.00 Lad The first version of SFilePatchArchives.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local structures
|
||||
|
||||
typedef struct _BLIZZARD_BSDIFF40_FILE
|
||||
{
|
||||
ULONGLONG Signature;
|
||||
ULONGLONG CtrlBlockSize;
|
||||
ULONGLONG DataBlockSize;
|
||||
ULONGLONG NewFileSize;
|
||||
} BLIZZARD_BSDIFF40_FILE, *PBLIZZARD_BSDIFF40_FILE;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static bool CompareNameMask(const TCHAR * szMpqName, const TCHAR * szNameMask)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
// Compare character
|
||||
switch(*szNameMask)
|
||||
{
|
||||
case 0: // End of the mask
|
||||
return (*szMpqName == 0) ? true : false;
|
||||
|
||||
case _T('#'): // We are expecting a number
|
||||
while('0' <= *szMpqName && *szMpqName <= '9')
|
||||
szMpqName++;
|
||||
szNameMask++;
|
||||
break;
|
||||
|
||||
default:
|
||||
if(toupper(*szMpqName++) != toupper(*szNameMask++))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool GetDefaultPatchPrefix(
|
||||
const TCHAR * szBaseMpqName,
|
||||
const TCHAR * szPatchMpqName,
|
||||
char * szBuffer)
|
||||
{
|
||||
const TCHAR * szExtension;
|
||||
const TCHAR * szDash;
|
||||
|
||||
// Ensure that both names are plain names
|
||||
szPatchMpqName = GetPlainFileNameT(szPatchMpqName);
|
||||
szBaseMpqName = GetPlainFileNameT(szBaseMpqName);
|
||||
|
||||
// For files like "wow-update-13164.MPQ", the patch prefix
|
||||
// is based on the base MPQ name
|
||||
if(CompareNameMask(szPatchMpqName, _T("wow-update-#.mpq")))
|
||||
{
|
||||
// Patch prefix is for the Cataclysm MPQs, whose names
|
||||
// are like "locale-enGB.MPQ" or "speech-enGB.MPQ"
|
||||
szExtension = _tcsrchr(szBaseMpqName, _T('.'));
|
||||
szDash = _tcsrchr(szBaseMpqName, _T('-'));
|
||||
strcpy(szBuffer, "Base");
|
||||
|
||||
// If the length of the prefix doesn't match, use default one
|
||||
if(szExtension != NULL && szDash != NULL && (szExtension - szDash) == 5)
|
||||
{
|
||||
// Copy the prefix
|
||||
szBuffer[0] = (char)szDash[1];
|
||||
szBuffer[1] = (char)szDash[2];
|
||||
szBuffer[2] = (char)szDash[3];
|
||||
szBuffer[3] = (char)szDash[4];
|
||||
szBuffer[4] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Note: Diablo 3 MPQs have name of "d3-update-####.mpq,
|
||||
// but they don't use patch prefixes
|
||||
//
|
||||
|
||||
// No patch prefix
|
||||
*szBuffer = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Decompress_RLE(LPBYTE pbDecompressed, DWORD cbDecompressed, LPBYTE pbCompressed, DWORD cbCompressed)
|
||||
{
|
||||
LPBYTE pbDecompressedEnd = pbDecompressed + cbDecompressed;
|
||||
LPBYTE pbCompressedEnd = pbCompressed + cbCompressed;
|
||||
BYTE RepeatCount;
|
||||
BYTE OneByte;
|
||||
|
||||
// Cut the initial DWORD from the compressed chunk
|
||||
pbCompressed += sizeof(DWORD);
|
||||
cbCompressed -= sizeof(DWORD);
|
||||
|
||||
// Pre-fill decompressed buffer with zeros
|
||||
memset(pbDecompressed, 0, cbDecompressed);
|
||||
|
||||
// Unpack
|
||||
while(pbCompressed < pbCompressedEnd && pbDecompressed < pbDecompressedEnd)
|
||||
{
|
||||
OneByte = *pbCompressed++;
|
||||
|
||||
// Is it a repetition byte ?
|
||||
if(OneByte & 0x80)
|
||||
{
|
||||
RepeatCount = (OneByte & 0x7F) + 1;
|
||||
for(BYTE i = 0; i < RepeatCount; i++)
|
||||
{
|
||||
if(pbDecompressed == pbDecompressedEnd || pbCompressed == pbCompressedEnd)
|
||||
break;
|
||||
|
||||
*pbDecompressed++ = *pbCompressed++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pbDecompressed += (OneByte + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int LoadMpqPatch_COPY(TMPQFile * hf, TPatchHeader * pPatchHeader)
|
||||
{
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Allocate space for patch header and compressed data
|
||||
hf->pPatchHeader = (TPatchHeader *)ALLOCMEM(BYTE, pPatchHeader->dwSizeOfPatchData);
|
||||
if(hf->pPatchHeader == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Load the patch data and decide if they are compressed or not
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
LPBYTE pbPatchFile = (LPBYTE)hf->pPatchHeader;
|
||||
|
||||
// Copy the patch header itself
|
||||
memcpy(pbPatchFile, pPatchHeader, sizeof(TPatchHeader));
|
||||
pbPatchFile += sizeof(TPatchHeader);
|
||||
|
||||
// Load the rest of the patch
|
||||
if(!SFileReadFile((HANDLE)hf, pbPatchFile, pPatchHeader->dwSizeOfPatchData - sizeof(TPatchHeader)))
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
static int LoadMpqPatch_BSD0(TMPQFile * hf, TPatchHeader * pPatchHeader)
|
||||
{
|
||||
LPBYTE pbDecompressed = NULL;
|
||||
LPBYTE pbCompressed = NULL;
|
||||
DWORD cbDecompressed = 0;
|
||||
DWORD cbCompressed = 0;
|
||||
DWORD dwBytesRead = 0;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Allocate space for compressed data
|
||||
cbCompressed = pPatchHeader->dwXfrmBlockSize - SIZE_OF_XFRM_HEADER;
|
||||
pbCompressed = ALLOCMEM(BYTE, cbCompressed);
|
||||
if(pbCompressed == NULL)
|
||||
nError = ERROR_SUCCESS;
|
||||
|
||||
// Read the compressed patch data
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Load the rest of the header
|
||||
SFileReadFile((HANDLE)hf, pbCompressed, cbCompressed, &dwBytesRead);
|
||||
if(dwBytesRead != cbCompressed)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Get the uncompressed size of the patch
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
cbDecompressed = pPatchHeader->dwSizeOfPatchData - sizeof(TPatchHeader);
|
||||
hf->pPatchHeader = (TPatchHeader *)ALLOCMEM(BYTE, pPatchHeader->dwSizeOfPatchData);
|
||||
if(hf->pPatchHeader == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
// Now decompress the patch data
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Copy the patch header
|
||||
memcpy(hf->pPatchHeader, pPatchHeader, sizeof(TPatchHeader));
|
||||
pbDecompressed = (LPBYTE)hf->pPatchHeader + sizeof(TPatchHeader);
|
||||
|
||||
// Uncompress or copy the patch data
|
||||
if(cbCompressed < cbDecompressed)
|
||||
{
|
||||
Decompress_RLE(pbDecompressed, cbDecompressed, pbCompressed, cbCompressed);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(cbCompressed == cbDecompressed);
|
||||
memcpy(pbDecompressed, pbCompressed, cbCompressed);
|
||||
}
|
||||
}
|
||||
|
||||
// Free buffers and exit
|
||||
if(pbCompressed != NULL)
|
||||
FREEMEM(pbCompressed);
|
||||
return nError;
|
||||
}
|
||||
|
||||
static int ApplyMpqPatch_COPY(
|
||||
TMPQFile * hf,
|
||||
TPatchHeader * pPatchHeader)
|
||||
{
|
||||
LPBYTE pbNewFileData;
|
||||
DWORD cbNewFileData;
|
||||
|
||||
// Allocate space for new file data
|
||||
cbNewFileData = pPatchHeader->dwXfrmBlockSize - SIZE_OF_XFRM_HEADER;
|
||||
pbNewFileData = ALLOCMEM(BYTE, cbNewFileData);
|
||||
if(pbNewFileData == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Copy the patch data as-is
|
||||
memcpy(pbNewFileData, (LPBYTE)pPatchHeader + sizeof(TPatchHeader), cbNewFileData);
|
||||
|
||||
// Free the old file data
|
||||
FREEMEM(hf->pbFileData);
|
||||
|
||||
// Put the new file data there
|
||||
hf->pbFileData = pbNewFileData;
|
||||
hf->cbFileData = cbNewFileData;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static int ApplyMpqPatch_BSD0(
|
||||
TMPQFile * hf,
|
||||
TPatchHeader * pPatchHeader)
|
||||
{
|
||||
PBLIZZARD_BSDIFF40_FILE pBsdiff;
|
||||
LPDWORD pCtrlBlock;
|
||||
LPBYTE pbPatchData = (LPBYTE)pPatchHeader + sizeof(TPatchHeader);
|
||||
LPBYTE pDataBlock;
|
||||
LPBYTE pExtraBlock;
|
||||
LPBYTE pbNewData = NULL;
|
||||
LPBYTE pbOldData = (LPBYTE)hf->pbFileData;
|
||||
DWORD dwNewOffset = 0; // Current position to patch
|
||||
DWORD dwOldOffset = 0; // Current source position
|
||||
DWORD dwNewSize; // Patched file size
|
||||
DWORD dwOldSize = hf->cbFileData; // File size before patch
|
||||
|
||||
// Get pointer to the patch header
|
||||
// Format of BSDIFF header corresponds to original BSDIFF, which is:
|
||||
// 0000 8 bytes signature "BSDIFF40"
|
||||
// 0008 8 bytes size of the control block
|
||||
// 0010 8 bytes size of the data block
|
||||
// 0018 8 bytes new size of the patched file
|
||||
pBsdiff = (PBLIZZARD_BSDIFF40_FILE)pbPatchData;
|
||||
pbPatchData += sizeof(BLIZZARD_BSDIFF40_FILE);
|
||||
|
||||
// Get pointer to the 32-bit BSDIFF control block
|
||||
// The control block follows immediately after the BSDIFF header
|
||||
// and consists of three 32-bit integers
|
||||
// 0000 4 bytes Length to copy from the BSDIFF data block the new file
|
||||
// 0004 4 bytes Length to copy from the BSDIFF extra block
|
||||
// 0008 4 bytes Size to increment source file offset
|
||||
pCtrlBlock = (LPDWORD)pbPatchData;
|
||||
pbPatchData += (size_t)BSWAP_INT64_UNSIGNED(pBsdiff->CtrlBlockSize);
|
||||
|
||||
// Get the pointer to the data block
|
||||
pDataBlock = (LPBYTE)pbPatchData;
|
||||
pbPatchData += (size_t)BSWAP_INT64_UNSIGNED(pBsdiff->DataBlockSize);
|
||||
|
||||
// Get the pointer to the extra block
|
||||
pExtraBlock = (LPBYTE)pbPatchData;
|
||||
dwNewSize = (DWORD)BSWAP_INT64_UNSIGNED(pBsdiff->NewFileSize);
|
||||
|
||||
// Allocate new buffer
|
||||
pbNewData = ALLOCMEM(BYTE, dwNewSize);
|
||||
if(pbNewData == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Now patch the file
|
||||
while(dwNewOffset < dwNewSize)
|
||||
{
|
||||
DWORD dwAddDataLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[0]);
|
||||
DWORD dwMovDataLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[1]);
|
||||
DWORD dwOldMoveLength = BSWAP_INT32_UNSIGNED(pCtrlBlock[2]);
|
||||
DWORD i;
|
||||
|
||||
// Sanity check
|
||||
if((dwNewOffset + dwAddDataLength) > dwNewSize)
|
||||
{
|
||||
FREEMEM(pbNewData);
|
||||
return ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Read the diff string to the target buffer
|
||||
memcpy(pbNewData + dwNewOffset, pDataBlock, dwAddDataLength);
|
||||
pDataBlock += dwAddDataLength;
|
||||
|
||||
// Now combine the patch data with the original file
|
||||
for(i = 0; i < dwAddDataLength; i++)
|
||||
{
|
||||
if(dwOldOffset < dwOldSize)
|
||||
pbNewData[dwNewOffset] = pbNewData[dwNewOffset] + pbOldData[dwOldOffset];
|
||||
|
||||
dwNewOffset++;
|
||||
dwOldOffset++;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if((dwNewOffset + dwMovDataLength) > dwNewSize)
|
||||
{
|
||||
FREEMEM(pbNewData);
|
||||
return ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Copy the data from the extra block in BSDIFF patch
|
||||
memcpy(pbNewData + dwNewOffset, pExtraBlock, dwMovDataLength);
|
||||
pExtraBlock += dwMovDataLength;
|
||||
dwNewOffset += dwMovDataLength;
|
||||
|
||||
// Move the old offset
|
||||
if(dwOldMoveLength & 0x80000000)
|
||||
dwOldMoveLength = 0x80000000 - dwOldMoveLength;
|
||||
dwOldOffset += dwOldMoveLength;
|
||||
pCtrlBlock += 3;
|
||||
}
|
||||
|
||||
// Free the old file data
|
||||
FREEMEM(hf->pbFileData);
|
||||
|
||||
// Put the new data to the fil structure
|
||||
hf->pbFileData = pbNewData;
|
||||
hf->cbFileData = dwNewSize;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int LoadMpqPatch(TMPQFile * hf)
|
||||
{
|
||||
TPatchHeader PatchHeader;
|
||||
DWORD dwBytesRead;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Read the patch header
|
||||
SFileReadFile((HANDLE)hf, &PatchHeader, sizeof(TPatchHeader), &dwBytesRead);
|
||||
if(dwBytesRead != sizeof(TPatchHeader))
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
|
||||
// Verify the signatures in the patch header
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// BSWAP the entire header, if needed
|
||||
BSWAP_ARRAY32_UNSIGNED(&PatchHeader, sizeof(DWORD) * 6);
|
||||
PatchHeader.dwXFRM = BSWAP_INT32_UNSIGNED(PatchHeader.dwXFRM);
|
||||
PatchHeader.dwXfrmBlockSize = BSWAP_INT32_UNSIGNED(PatchHeader.dwXfrmBlockSize);
|
||||
PatchHeader.dwPatchType = BSWAP_INT32_UNSIGNED(PatchHeader.dwPatchType);
|
||||
|
||||
if(PatchHeader.dwSignature != 0x48435450 || PatchHeader.dwMD5 != 0x5f35444d || PatchHeader.dwXFRM != 0x4d524658)
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Read the patch, depending on patch type
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
switch(PatchHeader.dwPatchType)
|
||||
{
|
||||
case 0x59504f43: // 'COPY'
|
||||
nError = LoadMpqPatch_COPY(hf, &PatchHeader);
|
||||
break;
|
||||
|
||||
case 0x30445342: // 'BSD0'
|
||||
nError = LoadMpqPatch_BSD0(hf, &PatchHeader);
|
||||
break;
|
||||
|
||||
default:
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
static int ApplyMpqPatch(
|
||||
TMPQFile * hf,
|
||||
TPatchHeader * pPatchHeader)
|
||||
{
|
||||
unsigned char md5_digest[MD5_DIGEST_SIZE];
|
||||
hash_state md5_state;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Verify the original file before patching
|
||||
if(pPatchHeader->dwSizeBeforePatch != 0)
|
||||
{
|
||||
md5_init(&md5_state);
|
||||
md5_process(&md5_state, hf->pbFileData, hf->cbFileData);
|
||||
md5_done(&md5_state, md5_digest);
|
||||
if(memcmp(pPatchHeader->md5_before_patch, md5_digest, MD5_DIGEST_SIZE))
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Apply the patch
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
switch(pPatchHeader->dwPatchType)
|
||||
{
|
||||
case 0x59504f43: // 'COPY'
|
||||
nError = ApplyMpqPatch_COPY(hf, pPatchHeader);
|
||||
break;
|
||||
|
||||
case 0x30445342: // 'BSD0'
|
||||
nError = ApplyMpqPatch_BSD0(hf, pPatchHeader);
|
||||
break;
|
||||
|
||||
default:
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify MD5 after patch
|
||||
if(nError == ERROR_SUCCESS && pPatchHeader->dwSizeAfterPatch != 0)
|
||||
{
|
||||
// Verify the patched file
|
||||
md5_init(&md5_state);
|
||||
md5_process(&md5_state, hf->pbFileData, hf->cbFileData);
|
||||
md5_done(&md5_state, md5_digest);
|
||||
if(memcmp(pPatchHeader->md5_after_patch, md5_digest, MD5_DIGEST_SIZE))
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions (StormLib internals)
|
||||
|
||||
bool IsPatchData(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize)
|
||||
{
|
||||
TPatchHeader * pPatchHeader = (TPatchHeader *)pvData;
|
||||
BLIZZARD_BSDIFF40_FILE DiffFile;
|
||||
DWORD dwPatchType;
|
||||
|
||||
if(cbData >= sizeof(TPatchHeader) + sizeof(BLIZZARD_BSDIFF40_FILE))
|
||||
{
|
||||
dwPatchType = BSWAP_INT32_UNSIGNED(pPatchHeader->dwPatchType);
|
||||
if(dwPatchType == 0x30445342)
|
||||
{
|
||||
// Give the caller the patch file size
|
||||
if(pdwPatchedFileSize != NULL)
|
||||
{
|
||||
Decompress_RLE((LPBYTE)&DiffFile, sizeof(BLIZZARD_BSDIFF40_FILE), (LPBYTE)(pPatchHeader + 1), sizeof(BLIZZARD_BSDIFF40_FILE));
|
||||
DiffFile.NewFileSize = BSWAP_INT64_UNSIGNED(DiffFile.NewFileSize);
|
||||
*pdwPatchedFileSize = (DWORD)DiffFile.NewFileSize;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int PatchFileData(TMPQFile * hf)
|
||||
{
|
||||
TMPQFile * hfBase = hf;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Move to the first patch
|
||||
hf = hf->hfPatchFile;
|
||||
|
||||
// Now go through all patches and patch the original data
|
||||
while(hf != NULL)
|
||||
{
|
||||
// This must be true
|
||||
assert(hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE);
|
||||
|
||||
// Make sure that the patch data is loaded
|
||||
nError = LoadMpqPatch(hf);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Apply the patch
|
||||
nError = ApplyMpqPatch(hfBase, hf->pPatchHeader);
|
||||
if(nError != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Move to the next patch
|
||||
hf = hf->hfPatchFile;
|
||||
}
|
||||
|
||||
return nError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
//
|
||||
// Patch prefix is the path subdirectory where the patched files are within MPQ.
|
||||
//
|
||||
// Example 1:
|
||||
// Main MPQ: locale-enGB.MPQ
|
||||
// Patch MPQ: wow-update-12694.MPQ
|
||||
// File in main MPQ: DBFilesClient\Achievement.dbc
|
||||
// File in patch MPQ: enGB\DBFilesClient\Achievement.dbc
|
||||
// Path prefix: enGB
|
||||
//
|
||||
// Example 2:
|
||||
// Main MPQ: expansion1.MPQ
|
||||
// Patch MPQ: wow-update-12694.MPQ
|
||||
// File in main MPQ: DBFilesClient\Achievement.dbc
|
||||
// File in patch MPQ: Base\DBFilesClient\Achievement.dbc
|
||||
// Path prefix: Base
|
||||
//
|
||||
|
||||
bool WINAPI SFileOpenPatchArchive(
|
||||
HANDLE hMpq,
|
||||
const TCHAR * szPatchMpqName,
|
||||
const char * szPatchPathPrefix,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
TMPQArchive * haPatch;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
HANDLE hPatchMpq = NULL;
|
||||
size_t nLength = 0;
|
||||
char szPatchPrefixBuff[MPQ_PATCH_PREFIX_LEN];
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Keep compiler happy
|
||||
dwFlags = dwFlags;
|
||||
|
||||
// Verify input parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
nError = ERROR_INVALID_HANDLE;
|
||||
if(szPatchMpqName == NULL || *szPatchMpqName == 0)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
// If the user didn't give the patch prefix, get default one
|
||||
if(szPatchPathPrefix == NULL)
|
||||
{
|
||||
// Get the default patch prefix from the base MPQ
|
||||
GetDefaultPatchPrefix(ha->pStream->szFileName, szPatchMpqName, szPatchPrefixBuff);
|
||||
szPatchPathPrefix = szPatchPrefixBuff;
|
||||
}
|
||||
|
||||
// Save length of the patch prefix
|
||||
nLength = strlen(szPatchPathPrefix);
|
||||
if(nLength > MPQ_PATCH_PREFIX_LEN - 2)
|
||||
nError = ERROR_INVALID_PARAMETER;
|
||||
|
||||
//
|
||||
// We don't allow adding patches to archives that have been open for write
|
||||
//
|
||||
// Error scenario:
|
||||
//
|
||||
// 1) Open archive for writing
|
||||
// 2) Modify or replace a file
|
||||
// 3) Add patch archive to the opened MPQ
|
||||
// 4) Read patched file
|
||||
// 5) Now what ?
|
||||
//
|
||||
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if((ha->pStream->StreamFlags & STREAM_FLAG_READ_ONLY) == 0)
|
||||
nError = ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
// Open the archive like it is normal archive
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
if(!SFileOpenArchive(szPatchMpqName, 0, MPQ_OPEN_READ_ONLY, &hPatchMpq))
|
||||
return false;
|
||||
haPatch = (TMPQArchive *)hPatchMpq;
|
||||
|
||||
// Save the prefix for patch file names.
|
||||
// Make sure that there is backslash after it
|
||||
if(nLength > 0)
|
||||
{
|
||||
strcpy(haPatch->szPatchPrefix, szPatchPathPrefix);
|
||||
if(haPatch->szPatchPrefix[nLength - 1] != '\\')
|
||||
{
|
||||
haPatch->szPatchPrefix[nLength++] = '\\';
|
||||
haPatch->szPatchPrefix[nLength] = 0;
|
||||
}
|
||||
haPatch->cchPatchPrefix = nLength;
|
||||
}
|
||||
|
||||
// Now add the patch archive to the list of patches to the original MPQ
|
||||
while(ha != NULL)
|
||||
{
|
||||
if(ha->haPatch == NULL)
|
||||
{
|
||||
haPatch->haBase = ha;
|
||||
ha->haPatch = haPatch;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Move to the next archive
|
||||
ha = ha->haPatch;
|
||||
}
|
||||
|
||||
// Should never happen
|
||||
nError = ERROR_CAN_NOT_COMPLETE;
|
||||
}
|
||||
|
||||
SetLastError(nError);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WINAPI SFileIsPatchedArchive(HANDLE hMpq)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
// Verify input parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
return false;
|
||||
|
||||
return (ha->haPatch != NULL);
|
||||
}
|
||||
1211
src/dep/src/StormLib/src/SFileReadFile.cpp
Normal file
1211
src/dep/src/StormLib/src/SFileReadFile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
929
src/dep/src/StormLib/src/SFileVerify.cpp
Normal file
929
src/dep/src/StormLib/src/SFileVerify.cpp
Normal file
@ -0,0 +1,929 @@
|
||||
/*****************************************************************************/
|
||||
/* SFileVerify.cpp Copyright (c) Ladislav Zezula 2010 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* MPQ files and MPQ archives verification. */
|
||||
/* */
|
||||
/* The MPQ signature verification has been written by Jean-Francois Roy */
|
||||
/* <bahamut@macstorm.org> and Justin Olbrantz (Quantam). */
|
||||
/* The MPQ public keys have been created by MPQKit, using OpenSSL library. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 04.05.10 1.00 Lad The first version of SFileVerify.cpp */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define __STORMLIB_SELF__
|
||||
#include "StormLib.h"
|
||||
#include "StormCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local defines
|
||||
|
||||
#define SIGNATURE_TYPE_NONE 0
|
||||
#define SIGNATURE_TYPE_WEAK 1
|
||||
#define SIGNATURE_TYPE_STRONG 2
|
||||
|
||||
#define MPQ_DIGEST_UNIT_SIZE 0x10000
|
||||
|
||||
typedef struct _MPQ_SIGNATURE_INFO
|
||||
{
|
||||
ULONGLONG BeginMpqData; // File offset where the hashing starts
|
||||
ULONGLONG BeginExclude; // Begin of the excluded area (used for (signature) file)
|
||||
ULONGLONG EndExclude; // End of the excluded area (used for (signature) file)
|
||||
ULONGLONG EndMpqData; // File offset where the hashing ends
|
||||
ULONGLONG EndOfFile; // Size of the entire file
|
||||
BYTE Signature[MPQ_STRONG_SIGNATURE_SIZE + 0x10];
|
||||
DWORD cbSignatureSize; // Length of the signature
|
||||
int nSignatureType; // See SIGNATURE_TYPE_XXX
|
||||
|
||||
} MPQ_SIGNATURE_INFO, *PMPQ_SIGNATURE_INFO;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Known Blizzard public keys
|
||||
// Created by Jean-Francois Roy using OpenSSL
|
||||
|
||||
static const char * szBlizzardWeakPublicKey =
|
||||
"-----BEGIN PUBLIC KEY-----"
|
||||
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJJidwS/uILMBSO5DLGsBFknIXWWjQJe"
|
||||
"2kfdfEk3G/j66w4KkhZ1V61Rt4zLaMVCYpDun7FLwRjkMDSepO1q2DcCAwEAAQ=="
|
||||
"-----END PUBLIC KEY-----";
|
||||
|
||||
static const char * szBlizzardStrongPublicKey =
|
||||
"-----BEGIN PUBLIC KEY-----"
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsQZ+ziT2h8h+J/iMQpgd"
|
||||
"tH1HaJzOBE3agjU4yMPcrixaPOZoA4t8bwfey7qczfWywocYo3pleytFF+IuD4HD"
|
||||
"Fl9OXN1SFyupSgMx1EGZlgbFAomnbq9MQJyMqQtMhRAjFgg4TndS7YNb+JMSAEKp"
|
||||
"kXNqY28n/EVBHD5TsMuVCL579gIenbr61dI92DDEdy790IzIG0VKWLh/KOTcTJfm"
|
||||
"Ds/7HQTkGouVW+WUsfekuqNQo7ND9DBnhLjLjptxeFE2AZqYcA1ao3S9LN3GL1tW"
|
||||
"lVXFIX9c7fWqaVTQlZ2oNsI/ARVApOK3grNgqvwH6YoVYVXjNJEo5sQJsPsdV/hk"
|
||||
"dwIDAQAB"
|
||||
"-----END PUBLIC KEY-----";
|
||||
|
||||
static const char * szWarcraft3MapPublicKey =
|
||||
"-----BEGIN PUBLIC KEY-----"
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1BwklUUQ3UvjizOBRoF5"
|
||||
"yyOVc7KD+oGOQH5i6eUk1yfs0luCC70kNucNrfqhmviywVtahRse1JtXCPrx2bd3"
|
||||
"iN8Dx91fbkxjYIOGTsjYoHKTp0BbaFkJih776fcHgnFSb+7mJcDuJVvJOXxEH6w0"
|
||||
"1vo6VtujCqj1arqbyoal+xtAaczF3us5cOEp45sR1zAWTn1+7omN7VWV4QqJPaDS"
|
||||
"gBSESc0l1grO0i1VUSumayk7yBKIkb+LBvcG6WnYZHCi7VdLmaxER5m8oZfER66b"
|
||||
"heHoiSQIZf9PAY6Guw2DT5BTc54j/AaLQAKf2qcRSgQLVo5kQaddF3rCpsXoB/74"
|
||||
"6QIDAQAB"
|
||||
"-----END PUBLIC KEY-----";
|
||||
|
||||
static const char * szWowPatchPublicKey =
|
||||
"-----BEGIN PUBLIC KEY-----"
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOsMV0LagAWPEtEQM6b9"
|
||||
"6FHFkUyGbbyda2/Dfc9dyl21E9QvX+Yw7qKRMAKPzA2TlQQLZKvXpnKXF/YIK5xa"
|
||||
"5uwg9CEHCEAYolLG4xn0FUOE0E/0PuuytI0p0ICe6rk00PifZzTr8na2wI/l/GnQ"
|
||||
"bvnIVF1ck6cslATpQJ5JJVMXzoFlUABS19WESw4MXuJAS3AbMhxNWdEhVv7eO51c"
|
||||
"yGjRLy9QjogZODZTY0fSEksgBqQxNCoYVJYI/sF5K2flDsGqrIp0OdJ6teJlzg1Y"
|
||||
"UjYnb6bKjlidXoHEXI2TgA/mD6O3XFIt08I9s3crOCTgICq7cgX35qrZiIVWZdRv"
|
||||
"TwIDAQAB"
|
||||
"-----END PUBLIC KEY-----";
|
||||
|
||||
static const char * szWowSurveyPublicKey =
|
||||
"-----BEGIN PUBLIC KEY-----"
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnIt1DR6nRyyKsy2qahHe"
|
||||
"MKLtacatn/KxieHcwH87wLBxKy+jZ0gycTmJ7SaTdBAEMDs/V5IPIXEtoqYnid2c"
|
||||
"63TmfGDU92oc3Ph1PWUZ2PWxBhT06HYxRdbrgHw9/I29pNPi/607x+lzPORITOgU"
|
||||
"BR6MR8au8HsQP4bn4vkJNgnSgojh48/XQOB/cAln7As1neP61NmVimoLR4Bwi3zt"
|
||||
"zfgrZaUpyeNCUrOYJmH09YIjbBySTtXOUidoPHjFrMsCWpr6xs8xbETbs7MJFL6a"
|
||||
"vcUfTT67qfIZ9RsuKfnXJTIrV0kwDSjjuNXiPTmWAehSsiHIsrUXX5RNcwsSjClr"
|
||||
"nQIDAQAB"
|
||||
"-----END PUBLIC KEY-----";
|
||||
|
||||
static const char * szStarcraft2MapPublicKey =
|
||||
"-----BEGIN PUBLIC KEY-----"
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmk4GT8zb+ICC25a17KZB"
|
||||
"q/ygKGJ2VSO6IT5PGHJlm1KfnHBA4B6SH3xMlJ4c6eG2k7QevZv+FOhjsAHubyWq"
|
||||
"2VKqWbrIFKv2ILc2RfMn8J9EDVRxvcxh6slRrVL69D0w1tfVGjMiKq2Fym5yGoRT"
|
||||
"E7CRgDqbAbXP9LBsCNWHiJLwfxMGzHbk8pIl9oia5pvM7ofZamSHchxlpy6xa4GJ"
|
||||
"7xKN01YCNvklTL1D7uol3wkwcHc7vrF8QwuJizuA5bSg4poEGtH62BZOYi+UL/z0"
|
||||
"31YK+k9CbQyM0X0pJoJoYz1TK+Y5J7vBnXCZtfcTYQ/ZzN6UcxTa57dJaiOlCh9z"
|
||||
"nQIDAQAB"
|
||||
"-----END PUBLIC KEY-----";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
static void memrev(unsigned char *buf, size_t count)
|
||||
{
|
||||
unsigned char *r;
|
||||
|
||||
for (r = buf + count - 1; buf < r; buf++, r--)
|
||||
{
|
||||
*buf ^= *r;
|
||||
*r ^= *buf;
|
||||
*buf ^= *r;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_valid_md5(void * pvMd5)
|
||||
{
|
||||
LPDWORD Md5 = (LPDWORD)pvMd5;
|
||||
|
||||
return (Md5[0] | Md5[1] | Md5[2] | Md5[3]) ? true : false;
|
||||
}
|
||||
|
||||
static bool decode_base64_key(const char * szKeyBase64, rsa_key * key)
|
||||
{
|
||||
unsigned char decoded_key[0x200];
|
||||
const char * szBase64Begin;
|
||||
const char * szBase64End;
|
||||
unsigned long decoded_length = sizeof(decoded_key);
|
||||
unsigned long length;
|
||||
|
||||
// Find out the begin of the BASE64 data
|
||||
szBase64Begin = szKeyBase64 + strlen("-----BEGIN PUBLIC KEY-----");
|
||||
szBase64End = szBase64Begin + strlen(szBase64Begin) - strlen("-----END PUBLIC KEY-----");
|
||||
if(szBase64End[0] != '-')
|
||||
return false;
|
||||
|
||||
// decode the base64 string
|
||||
length = (unsigned long)(szBase64End - szBase64Begin);
|
||||
if(base64_decode((unsigned char *)szBase64Begin, length, decoded_key, &decoded_length) != CRYPT_OK)
|
||||
return false;
|
||||
|
||||
// Create RSA key
|
||||
if(rsa_import(decoded_key, decoded_length, key) != CRYPT_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void GetPlainAnsiFileName(
|
||||
const TCHAR * szFileName,
|
||||
char * szPlainName)
|
||||
{
|
||||
const TCHAR * szPlainNameT = GetPlainFileNameT(szFileName);
|
||||
|
||||
// Convert the plain name to ANSI
|
||||
while(*szPlainNameT != 0)
|
||||
*szPlainName++ = (char)*szPlainNameT++;
|
||||
*szPlainName = 0;
|
||||
}
|
||||
|
||||
// Calculate begin and end of the MPQ archive
|
||||
static void CalculateArchiveRange(
|
||||
TMPQArchive * ha,
|
||||
PMPQ_SIGNATURE_INFO pSI)
|
||||
{
|
||||
TMPQHeader * pHeader = ha->pHeader;
|
||||
ULONGLONG TempPos = 0;
|
||||
ULONGLONG MaxPos;
|
||||
char szMapHeader[0x200];
|
||||
|
||||
// Get the MPQ begin
|
||||
pSI->BeginMpqData = ha->MpqPos;
|
||||
|
||||
// Warcraft III maps are signed from the map header to the end
|
||||
if(FileStream_Read(ha->pStream, &TempPos, szMapHeader, sizeof(szMapHeader)))
|
||||
{
|
||||
// Is it a map header ?
|
||||
if(szMapHeader[0] == 'H' && szMapHeader[1] == 'M' && szMapHeader[2] == '3' && szMapHeader[3] == 'W')
|
||||
{
|
||||
// We will have to hash since the map header
|
||||
pSI->BeginMpqData = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the MPQ data end. The end is calculated as the biggest
|
||||
// value of (end of the last file), (end of block table),
|
||||
// (end of ext block table), (end of hash table)
|
||||
FindFreeMpqSpace(ha, &MaxPos);
|
||||
|
||||
// Check if hash table is beyond
|
||||
TempPos = ha->MpqPos + MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos) + pHeader->HashTableSize64;
|
||||
if(TempPos > MaxPos)
|
||||
MaxPos = TempPos;
|
||||
|
||||
// Check if block table is beyond
|
||||
TempPos = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos) + pHeader->BlockTableSize64;
|
||||
if(TempPos > MaxPos)
|
||||
MaxPos = TempPos;
|
||||
|
||||
// Check if ext block table is beyond
|
||||
if(pHeader->HiBlockTablePos64 != 0)
|
||||
{
|
||||
TempPos = ha->MpqPos + pHeader->HiBlockTablePos64 + pHeader->HiBlockTableSize64;
|
||||
if(TempPos > MaxPos)
|
||||
MaxPos = TempPos;
|
||||
}
|
||||
|
||||
// Give the end
|
||||
pSI->EndMpqData = MaxPos;
|
||||
|
||||
// Get the size of the entire file
|
||||
FileStream_GetSize(ha->pStream, pSI->EndOfFile);
|
||||
}
|
||||
|
||||
static bool QueryMpqSignatureInfo(
|
||||
TMPQArchive * ha,
|
||||
PMPQ_SIGNATURE_INFO pSI)
|
||||
{
|
||||
ULONGLONG ExtraBytes;
|
||||
TMPQFile * hf;
|
||||
HANDLE hFile;
|
||||
DWORD dwFileSize;
|
||||
|
||||
// Calculate the range of the MPQ
|
||||
CalculateArchiveRange(ha, pSI);
|
||||
|
||||
// If there is "(signature)" file in the MPQ, it has a weak signature
|
||||
if(SFileOpenFileEx((HANDLE)ha, SIGNATURE_NAME, SFILE_OPEN_FROM_MPQ, &hFile))
|
||||
{
|
||||
// Get the content of the signature
|
||||
SFileReadFile(hFile, pSI->Signature, sizeof(pSI->Signature), &pSI->cbSignatureSize);
|
||||
|
||||
// Verify the size of the signature
|
||||
hf = (TMPQFile *)hFile;
|
||||
|
||||
// We have to exclude the signature file from the digest
|
||||
pSI->BeginExclude = ha->MpqPos + hf->pFileEntry->ByteOffset;
|
||||
pSI->EndExclude = pSI->BeginExclude + hf->pFileEntry->dwCmpSize;
|
||||
dwFileSize = hf->dwDataSize;
|
||||
|
||||
// Close the file
|
||||
SFileCloseFile(hFile);
|
||||
pSI->nSignatureType = SIGNATURE_TYPE_WEAK;
|
||||
return (dwFileSize == (MPQ_WEAK_SIGNATURE_SIZE + 8)) ? true : false;
|
||||
}
|
||||
|
||||
// If there is extra bytes beyond the end of the archive,
|
||||
// it's the strong signature
|
||||
ExtraBytes = pSI->EndOfFile - pSI->EndMpqData;
|
||||
if(ExtraBytes >= (MPQ_STRONG_SIGNATURE_SIZE + 4))
|
||||
{
|
||||
// Read the strong signature
|
||||
if(!FileStream_Read(ha->pStream, &pSI->EndMpqData, pSI->Signature, (MPQ_STRONG_SIGNATURE_SIZE + 4)))
|
||||
return false;
|
||||
|
||||
// Check the signature header "NGIS"
|
||||
if(pSI->Signature[0] != 'N' || pSI->Signature[1] != 'G' || pSI->Signature[2] != 'I' || pSI->Signature[3] != 'S')
|
||||
return false;
|
||||
|
||||
pSI->nSignatureType = SIGNATURE_TYPE_STRONG;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Succeeded, but no known signature found
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CalculateMpqHashMd5(
|
||||
TMPQArchive * ha,
|
||||
PMPQ_SIGNATURE_INFO pSI,
|
||||
LPBYTE pMd5Digest)
|
||||
{
|
||||
hash_state md5_state;
|
||||
ULONGLONG BeginBuffer;
|
||||
ULONGLONG EndBuffer;
|
||||
LPBYTE pbDigestBuffer = NULL;
|
||||
|
||||
// Allocate buffer for creating the MPQ digest.
|
||||
pbDigestBuffer = ALLOCMEM(BYTE, MPQ_DIGEST_UNIT_SIZE);
|
||||
if(pbDigestBuffer == NULL)
|
||||
return false;
|
||||
|
||||
// Initialize the MD5 hash state
|
||||
md5_init(&md5_state);
|
||||
|
||||
// Set the byte offset of begin of the data
|
||||
BeginBuffer = pSI->BeginMpqData;
|
||||
|
||||
// Create the digest
|
||||
for(;;)
|
||||
{
|
||||
ULONGLONG BytesRemaining;
|
||||
LPBYTE pbSigBegin = NULL;
|
||||
LPBYTE pbSigEnd = NULL;
|
||||
DWORD dwToRead = MPQ_DIGEST_UNIT_SIZE;
|
||||
|
||||
// Check the number of bytes remaining
|
||||
BytesRemaining = pSI->EndMpqData - BeginBuffer;
|
||||
if(BytesRemaining < MPQ_DIGEST_UNIT_SIZE)
|
||||
dwToRead = (DWORD)BytesRemaining;
|
||||
if(dwToRead == 0)
|
||||
break;
|
||||
|
||||
// Read the next chunk
|
||||
if(!FileStream_Read(ha->pStream, &BeginBuffer, pbDigestBuffer, dwToRead))
|
||||
{
|
||||
FREEMEM(pbDigestBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move the current byte offset
|
||||
EndBuffer = BeginBuffer + dwToRead;
|
||||
|
||||
// Check if the signature is within the loaded digest
|
||||
if(BeginBuffer <= pSI->BeginExclude && pSI->BeginExclude < EndBuffer)
|
||||
pbSigBegin = pbDigestBuffer + (size_t)(pSI->BeginExclude - BeginBuffer);
|
||||
if(BeginBuffer <= pSI->EndExclude && pSI->EndExclude < EndBuffer)
|
||||
pbSigEnd = pbDigestBuffer + (size_t)(pSI->EndExclude - BeginBuffer);
|
||||
|
||||
// Zero the part that belongs to the signature
|
||||
if(pbSigBegin != NULL || pbSigEnd != NULL)
|
||||
{
|
||||
if(pbSigBegin == NULL)
|
||||
pbSigBegin = pbDigestBuffer;
|
||||
if(pbSigEnd == NULL)
|
||||
pbSigEnd = pbDigestBuffer + dwToRead;
|
||||
|
||||
memset(pbSigBegin, 0, (pbSigEnd - pbSigBegin));
|
||||
}
|
||||
|
||||
// Pass the buffer to the hashing function
|
||||
md5_process(&md5_state, pbDigestBuffer, dwToRead);
|
||||
|
||||
// Move pointers
|
||||
BeginBuffer += dwToRead;
|
||||
}
|
||||
|
||||
// Finalize the MD5 hash
|
||||
md5_done(&md5_state, pMd5Digest);
|
||||
FREEMEM(pbDigestBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void AddTailToSha1(
|
||||
hash_state * psha1_state,
|
||||
const char * szTail)
|
||||
{
|
||||
unsigned char szUpperCase[0x200];
|
||||
unsigned long nLength = 0;
|
||||
|
||||
// Convert the tail to uppercase
|
||||
// Note that we don't need to terminate the string with zero
|
||||
while(*szTail != 0)
|
||||
{
|
||||
szUpperCase[nLength++] = (unsigned char)toupper(*szTail++);
|
||||
}
|
||||
|
||||
// Append the tail to the SHA1
|
||||
sha1_process(psha1_state, szUpperCase, nLength);
|
||||
}
|
||||
|
||||
static bool CalculateMpqHashSha1(
|
||||
TMPQArchive * ha,
|
||||
PMPQ_SIGNATURE_INFO pSI,
|
||||
unsigned char * sha1_tail0,
|
||||
unsigned char * sha1_tail1,
|
||||
unsigned char * sha1_tail2)
|
||||
{
|
||||
ULONGLONG BeginBuffer;
|
||||
hash_state sha1_state_temp;
|
||||
hash_state sha1_state;
|
||||
LPBYTE pbDigestBuffer = NULL;
|
||||
char szPlainName[MAX_PATH];
|
||||
|
||||
// Allocate buffer for creating the MPQ digest.
|
||||
pbDigestBuffer = ALLOCMEM(BYTE, MPQ_DIGEST_UNIT_SIZE);
|
||||
if(pbDigestBuffer == NULL)
|
||||
return false;
|
||||
|
||||
// Initialize SHA1 state structure
|
||||
sha1_init(&sha1_state);
|
||||
|
||||
// Calculate begin of data to be hashed
|
||||
BeginBuffer = pSI->BeginMpqData;
|
||||
|
||||
// Create the digest
|
||||
for(;;)
|
||||
{
|
||||
ULONGLONG BytesRemaining;
|
||||
DWORD dwToRead = MPQ_DIGEST_UNIT_SIZE;
|
||||
|
||||
// Check the number of bytes remaining
|
||||
BytesRemaining = pSI->EndMpqData - BeginBuffer;
|
||||
if(BytesRemaining < MPQ_DIGEST_UNIT_SIZE)
|
||||
dwToRead = (DWORD)BytesRemaining;
|
||||
if(dwToRead == 0)
|
||||
break;
|
||||
|
||||
// Read the next chunk
|
||||
if(!FileStream_Read(ha->pStream, &BeginBuffer, pbDigestBuffer, dwToRead))
|
||||
{
|
||||
FREEMEM(pbDigestBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pass the buffer to the hashing function
|
||||
sha1_process(&sha1_state, pbDigestBuffer, dwToRead);
|
||||
|
||||
// Move pointers
|
||||
BeginBuffer += dwToRead;
|
||||
}
|
||||
|
||||
// Add all three known tails and generate three hashes
|
||||
memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
|
||||
sha1_done(&sha1_state_temp, sha1_tail0);
|
||||
|
||||
memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
|
||||
GetPlainAnsiFileName(ha->pStream->szFileName, szPlainName);
|
||||
AddTailToSha1(&sha1_state_temp, szPlainName);
|
||||
sha1_done(&sha1_state_temp, sha1_tail1);
|
||||
|
||||
memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state));
|
||||
AddTailToSha1(&sha1_state_temp, "ARCHIVE");
|
||||
sha1_done(&sha1_state_temp, sha1_tail2);
|
||||
|
||||
// Finalize the MD5 hash
|
||||
FREEMEM(pbDigestBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int VerifyRawMpqData(
|
||||
TMPQArchive * ha,
|
||||
ULONGLONG ByteOffset,
|
||||
DWORD dwDataSize)
|
||||
{
|
||||
hash_state md5_state;
|
||||
ULONGLONG DataOffset = ha->MpqPos + ByteOffset;
|
||||
LPBYTE pbDataChunk;
|
||||
LPBYTE pbMD5Array1; // Calculated MD5 array
|
||||
LPBYTE pbMD5Array2; // MD5 array loaded from the MPQ
|
||||
DWORD dwBytesInChunk;
|
||||
DWORD dwChunkCount;
|
||||
DWORD dwChunkSize = ha->pHeader->dwRawChunkSize;
|
||||
DWORD dwMD5Size;
|
||||
int nError = ERROR_SUCCESS;
|
||||
|
||||
// Get the number of data chunks to calculate MD5
|
||||
assert(dwChunkSize != 0);
|
||||
dwChunkCount = dwDataSize / dwChunkSize;
|
||||
if(dwDataSize % dwChunkSize)
|
||||
dwChunkCount++;
|
||||
dwMD5Size = dwChunkCount * MD5_DIGEST_SIZE;
|
||||
|
||||
// Allocate space for data chunk and for the MD5 array
|
||||
pbDataChunk = ALLOCMEM(BYTE, dwChunkSize);
|
||||
if(pbDataChunk == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Allocate space for MD5 array
|
||||
pbMD5Array1 = ALLOCMEM(BYTE, dwMD5Size);
|
||||
pbMD5Array2 = ALLOCMEM(BYTE, dwMD5Size);
|
||||
if(pbMD5Array1 == NULL || pbMD5Array2 == NULL)
|
||||
nError = ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
// Calculate MD5 of each data chunk
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
LPBYTE pbMD5 = pbMD5Array1;
|
||||
|
||||
for(DWORD i = 0; i < dwChunkCount; i++)
|
||||
{
|
||||
// Get the number of bytes in the chunk
|
||||
dwBytesInChunk = STORMLIB_MIN(dwChunkSize, dwDataSize);
|
||||
|
||||
// Read the data chunk
|
||||
if(!FileStream_Read(ha->pStream, &DataOffset, pbDataChunk, dwBytesInChunk))
|
||||
{
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate MD5
|
||||
md5_init(&md5_state);
|
||||
md5_process(&md5_state, pbDataChunk, dwBytesInChunk);
|
||||
md5_done(&md5_state, pbMD5);
|
||||
|
||||
// Move pointers and offsets
|
||||
DataOffset += dwBytesInChunk;
|
||||
dwDataSize -= dwBytesInChunk;
|
||||
pbMD5 += MD5_DIGEST_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the MD5 array
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Read the array of MD5
|
||||
if(!FileStream_Read(ha->pStream, &DataOffset, pbMD5Array2, dwMD5Size))
|
||||
nError = GetLastError();
|
||||
}
|
||||
|
||||
// Compare the array of MD5
|
||||
if(nError == ERROR_SUCCESS)
|
||||
{
|
||||
// Compare the MD5
|
||||
if(memcmp(pbMD5Array1, pbMD5Array2, dwMD5Size))
|
||||
nError = ERROR_FILE_CORRUPT;
|
||||
}
|
||||
|
||||
// Free memory and return result
|
||||
if(pbMD5Array2 != NULL)
|
||||
FREEMEM(pbMD5Array2);
|
||||
if(pbMD5Array1 != NULL)
|
||||
FREEMEM(pbMD5Array1);
|
||||
if(pbDataChunk != NULL)
|
||||
FREEMEM(pbDataChunk);
|
||||
return nError;
|
||||
}
|
||||
|
||||
static DWORD VerifyWeakSignature(
|
||||
TMPQArchive * ha,
|
||||
PMPQ_SIGNATURE_INFO pSI)
|
||||
{
|
||||
BYTE RevSignature[MPQ_WEAK_SIGNATURE_SIZE];
|
||||
BYTE Md5Digest[MD5_DIGEST_SIZE];
|
||||
rsa_key key;
|
||||
int hash_idx = find_hash("md5");
|
||||
int result = 0;
|
||||
|
||||
// Calculate hash of the entire archive, skipping the (signature) file
|
||||
if(!CalculateMpqHashMd5(ha, pSI, Md5Digest))
|
||||
return ERROR_VERIFY_FAILED;
|
||||
|
||||
// Import the Blizzard key in OpenSSL format
|
||||
if(!decode_base64_key(szBlizzardWeakPublicKey, &key))
|
||||
return ERROR_VERIFY_FAILED;
|
||||
|
||||
// Verify the signature
|
||||
memcpy(RevSignature, &pSI->Signature[8], MPQ_WEAK_SIGNATURE_SIZE);
|
||||
memrev(RevSignature, MPQ_WEAK_SIGNATURE_SIZE);
|
||||
rsa_verify_hash_ex(RevSignature, MPQ_WEAK_SIGNATURE_SIZE, Md5Digest, sizeof(Md5Digest), LTC_LTC_PKCS_1_V1_5, hash_idx, 0, &result, &key);
|
||||
rsa_free(&key);
|
||||
|
||||
// Return the result
|
||||
return result ? ERROR_WEAK_SIGNATURE_OK : ERROR_WEAK_SIGNATURE_ERROR;
|
||||
}
|
||||
|
||||
static DWORD VerifyStrongSignatureWithKey(
|
||||
unsigned char * reversed_signature,
|
||||
unsigned char * padded_digest,
|
||||
const char * szPublicKey)
|
||||
{
|
||||
rsa_key key;
|
||||
int result = 0;
|
||||
|
||||
// Import the Blizzard key in OpenSSL format
|
||||
if(!decode_base64_key(szPublicKey, &key))
|
||||
{
|
||||
assert(false);
|
||||
return ERROR_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
// Verify the signature
|
||||
if(rsa_verify_simple(reversed_signature, MPQ_STRONG_SIGNATURE_SIZE, padded_digest, MPQ_STRONG_SIGNATURE_SIZE, &result, &key) != CRYPT_OK)
|
||||
return ERROR_VERIFY_FAILED;
|
||||
|
||||
// Free the key and return result
|
||||
rsa_free(&key);
|
||||
return result ? ERROR_STRONG_SIGNATURE_OK : ERROR_STRONG_SIGNATURE_ERROR;
|
||||
}
|
||||
|
||||
static DWORD VerifyStrongSignature(
|
||||
TMPQArchive * ha,
|
||||
PMPQ_SIGNATURE_INFO pSI)
|
||||
{
|
||||
unsigned char reversed_signature[MPQ_STRONG_SIGNATURE_SIZE];
|
||||
unsigned char Sha1Digest_tail0[SHA1_DIGEST_SIZE];
|
||||
unsigned char Sha1Digest_tail1[SHA1_DIGEST_SIZE];
|
||||
unsigned char Sha1Digest_tail2[SHA1_DIGEST_SIZE];
|
||||
unsigned char padded_digest[MPQ_STRONG_SIGNATURE_SIZE];
|
||||
DWORD dwResult;
|
||||
size_t digest_offset;
|
||||
|
||||
// Calculate SHA1 hash of the archive
|
||||
if(!CalculateMpqHashSha1(ha, pSI, Sha1Digest_tail0, Sha1Digest_tail1, Sha1Digest_tail2))
|
||||
return ERROR_VERIFY_FAILED;
|
||||
|
||||
// Prepare the signature for decryption
|
||||
memcpy(reversed_signature, &pSI->Signature[4], MPQ_STRONG_SIGNATURE_SIZE);
|
||||
memrev(reversed_signature, MPQ_STRONG_SIGNATURE_SIZE);
|
||||
|
||||
// Prepare the padded digest for comparison
|
||||
digest_offset = sizeof(padded_digest) - SHA1_DIGEST_SIZE;
|
||||
memset(padded_digest, 0xbb, digest_offset);
|
||||
padded_digest[0] = 0x0b;
|
||||
|
||||
// Try Blizzard Strong public key with no SHA1 tail
|
||||
memcpy(padded_digest + digest_offset, Sha1Digest_tail0, SHA1_DIGEST_SIZE);
|
||||
memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
|
||||
dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szBlizzardStrongPublicKey);
|
||||
if(dwResult == ERROR_STRONG_SIGNATURE_OK)
|
||||
return dwResult;
|
||||
|
||||
// Try War 3 map public key with plain file name as SHA1 tail
|
||||
memcpy(padded_digest + digest_offset, Sha1Digest_tail1, SHA1_DIGEST_SIZE);
|
||||
memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
|
||||
dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szWarcraft3MapPublicKey);
|
||||
if(dwResult == ERROR_STRONG_SIGNATURE_OK)
|
||||
return dwResult;
|
||||
|
||||
// Try WoW-TBC public key with "ARCHIVE" as SHA1 tail
|
||||
memcpy(padded_digest + digest_offset, Sha1Digest_tail2, SHA1_DIGEST_SIZE);
|
||||
memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
|
||||
dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szWowPatchPublicKey);
|
||||
if(dwResult == ERROR_STRONG_SIGNATURE_OK)
|
||||
return dwResult;
|
||||
|
||||
// Try Survey public key with no SHA1 tail
|
||||
memcpy(padded_digest + digest_offset, Sha1Digest_tail0, SHA1_DIGEST_SIZE);
|
||||
memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
|
||||
dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szWowSurveyPublicKey);
|
||||
if(dwResult == ERROR_STRONG_SIGNATURE_OK)
|
||||
return dwResult;
|
||||
|
||||
// Try Starcraft II public key with no SHA1 tail
|
||||
memcpy(padded_digest + digest_offset, Sha1Digest_tail0, SHA1_DIGEST_SIZE);
|
||||
memrev(padded_digest + digest_offset, SHA1_DIGEST_SIZE);
|
||||
dwResult = VerifyStrongSignatureWithKey(reversed_signature, padded_digest, szStarcraft2MapPublicKey);
|
||||
if(dwResult == ERROR_STRONG_SIGNATURE_OK)
|
||||
return dwResult;
|
||||
|
||||
return ERROR_STRONG_SIGNATURE_ERROR;
|
||||
}
|
||||
|
||||
static DWORD VerifyFile(
|
||||
HANDLE hMpq,
|
||||
const char * szFileName,
|
||||
LPDWORD pdwCrc32,
|
||||
char * pMD5,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
hash_state md5_state;
|
||||
unsigned char * pFileMd5;
|
||||
unsigned char md5[MD5_DIGEST_SIZE];
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQFile * hf;
|
||||
BYTE Buffer[0x1000];
|
||||
HANDLE hFile = NULL;
|
||||
DWORD dwVerifyResult = 0;
|
||||
DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ;
|
||||
DWORD dwTotalBytes = 0;
|
||||
DWORD dwBytesRead;
|
||||
DWORD dwCrc32 = 0;
|
||||
|
||||
// Fix the open type for patched archives
|
||||
if(SFileIsPatchedArchive(hMpq))
|
||||
dwSearchScope = SFILE_OPEN_PATCHED_FILE;
|
||||
|
||||
// Attempt to open the file
|
||||
if(SFileOpenFileEx(hMpq, szFileName, dwSearchScope, &hFile))
|
||||
{
|
||||
// Get the file size
|
||||
hf = (TMPQFile *)hFile;
|
||||
pFileEntry = hf->pFileEntry;
|
||||
dwTotalBytes = SFileGetFileSize(hFile, NULL);
|
||||
|
||||
// Initialize the CRC32 and MD5 contexts
|
||||
md5_init(&md5_state);
|
||||
dwCrc32 = crc32(0, Z_NULL, 0);
|
||||
|
||||
// If we have to verify raw data MD5, do it
|
||||
if(dwFlags & SFILE_VERIFY_RAW_MD5)
|
||||
{
|
||||
if(hf->ha->pHeader->dwRawChunkSize != 0)
|
||||
{
|
||||
// Note: we have to open the file from the MPQ where it was open from
|
||||
if(VerifyRawMpqData(hf->ha, pFileEntry->ByteOffset, pFileEntry->dwCmpSize) != ERROR_SUCCESS)
|
||||
dwVerifyResult |= VERIFY_FILE_RAW_MD5_ERROR;
|
||||
dwVerifyResult |= VERIFY_FILE_HAS_RAW_MD5;
|
||||
}
|
||||
}
|
||||
|
||||
// Also turn on sector checksum verification
|
||||
if(dwFlags & SFILE_VERIFY_SECTOR_CRC)
|
||||
hf->bCheckSectorCRCs = true;
|
||||
|
||||
// Go through entire file and update both CRC32 and MD5
|
||||
for(;;)
|
||||
{
|
||||
// Read data from file
|
||||
SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
|
||||
if(dwBytesRead == 0)
|
||||
{
|
||||
if(GetLastError() == ERROR_CHECKSUM_ERROR)
|
||||
dwVerifyResult |= VERIFY_FILE_SECTOR_CRC_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
// Update CRC32 value
|
||||
if(dwFlags & SFILE_VERIFY_FILE_CRC)
|
||||
dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead);
|
||||
|
||||
// Update MD5 value
|
||||
if(dwFlags & SFILE_VERIFY_FILE_MD5)
|
||||
md5_process(&md5_state, Buffer, dwBytesRead);
|
||||
|
||||
// Decrement the total size
|
||||
dwTotalBytes -= dwBytesRead;
|
||||
}
|
||||
|
||||
// If the file has sector checksums, indicate it in the flags
|
||||
if(dwFlags & SFILE_VERIFY_SECTOR_CRC)
|
||||
{
|
||||
if((hf->pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->SectorChksums != NULL && hf->SectorChksums[0] != 0)
|
||||
dwVerifyResult |= VERIFY_FILE_HAS_SECTOR_CRC;
|
||||
}
|
||||
|
||||
// Check if the entire file has been read
|
||||
// No point in checking CRC32 and MD5 if not
|
||||
// Skip checksum checks if the file has patches
|
||||
if(dwTotalBytes == 0)
|
||||
{
|
||||
// Check CRC32 and MD5 only if there is no patches
|
||||
if(hf->hfPatchFile == NULL)
|
||||
{
|
||||
// Check if the CRC32 matches.
|
||||
if(dwFlags & SFILE_VERIFY_FILE_CRC)
|
||||
{
|
||||
// Only check the CRC32 if it is valid
|
||||
if(pFileEntry->dwCrc32 != 0)
|
||||
{
|
||||
dwVerifyResult |= VERIFY_FILE_HAS_CHECKSUM;
|
||||
if(dwCrc32 != pFileEntry->dwCrc32)
|
||||
dwVerifyResult |= VERIFY_FILE_CHECKSUM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if MD5 matches
|
||||
if(dwFlags & SFILE_VERIFY_FILE_MD5)
|
||||
{
|
||||
// Patch files have their MD5 saved in the patch info
|
||||
pFileMd5 = (hf->pPatchInfo != NULL) ? hf->pPatchInfo->md5 : pFileEntry->md5;
|
||||
md5_done(&md5_state, md5);
|
||||
|
||||
// Only check the MD5 if it is valid
|
||||
if(is_valid_md5(pFileMd5))
|
||||
{
|
||||
dwVerifyResult |= VERIFY_FILE_HAS_MD5;
|
||||
if(memcmp(md5, pFileMd5, MD5_DIGEST_SIZE))
|
||||
dwVerifyResult |= VERIFY_FILE_MD5_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Patched files are MD5-checked automatically
|
||||
dwVerifyResult |= VERIFY_FILE_HAS_MD5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwVerifyResult |= VERIFY_READ_ERROR;
|
||||
}
|
||||
|
||||
SFileCloseFile(hFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remember that the file couldn't be open
|
||||
dwVerifyResult |= VERIFY_OPEN_ERROR;
|
||||
}
|
||||
|
||||
// If the caller required CRC32 and/or MD5, give it to him
|
||||
if(pdwCrc32 != NULL)
|
||||
*pdwCrc32 = dwCrc32;
|
||||
if(pMD5 != NULL)
|
||||
memcpy(pMD5, md5, MD5_DIGEST_SIZE);
|
||||
|
||||
return dwVerifyResult;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public (exported) functions
|
||||
|
||||
bool WINAPI SFileGetFileChecksums(HANDLE hMpq, const char * szFileName, LPDWORD pdwCrc32, char * pMD5)
|
||||
{
|
||||
DWORD dwVerifyResult;
|
||||
DWORD dwVerifyFlags = 0;
|
||||
|
||||
if(pdwCrc32 != NULL)
|
||||
dwVerifyFlags |= SFILE_VERIFY_FILE_CRC;
|
||||
if(pMD5 != NULL)
|
||||
dwVerifyFlags |= SFILE_VERIFY_FILE_MD5;
|
||||
|
||||
dwVerifyResult = VerifyFile(hMpq,
|
||||
szFileName,
|
||||
pdwCrc32,
|
||||
pMD5,
|
||||
dwVerifyFlags);
|
||||
|
||||
// If verification failed, return zero
|
||||
if(dwVerifyResult & VERIFY_FILE_ERROR_MASK)
|
||||
{
|
||||
SetLastError(ERROR_FILE_CORRUPT);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags)
|
||||
{
|
||||
return VerifyFile(hMpq,
|
||||
szFileName,
|
||||
NULL,
|
||||
NULL,
|
||||
dwFlags);
|
||||
}
|
||||
|
||||
// Verifies raw data of the archive Only works for MPQs version 4 or newer
|
||||
int WINAPI SFileVerifyRawData(HANDLE hMpq, DWORD dwWhatToVerify, const char * szFileName)
|
||||
{
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
TFileEntry * pFileEntry;
|
||||
TMPQHeader * pHeader;
|
||||
|
||||
// Verify input parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
pHeader = ha->pHeader;
|
||||
|
||||
// If the archive doesn't have raw data MD5, report it as OK
|
||||
if(pHeader->dwRawChunkSize == 0)
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// If we have to verify MPQ header, do it
|
||||
switch(dwWhatToVerify)
|
||||
{
|
||||
case SFILE_VERIFY_MPQ_HEADER:
|
||||
|
||||
// Only if the header is of version 4 or newer
|
||||
if(pHeader->dwHeaderSize >= (MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE))
|
||||
return VerifyRawMpqData(ha, 0, MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE);
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case SFILE_VERIFY_HET_TABLE:
|
||||
|
||||
// Only if we have HET table
|
||||
if(pHeader->HetTablePos64 && pHeader->HetTableSize64)
|
||||
return VerifyRawMpqData(ha, pHeader->HetTablePos64, (DWORD)pHeader->HetTableSize64);
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case SFILE_VERIFY_BET_TABLE:
|
||||
|
||||
// Only if we have BET table
|
||||
if(pHeader->BetTablePos64 && pHeader->BetTableSize64)
|
||||
return VerifyRawMpqData(ha, pHeader->BetTablePos64, (DWORD)pHeader->BetTableSize64);
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case SFILE_VERIFY_HASH_TABLE:
|
||||
|
||||
// Hash table is not protected by MD5
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case SFILE_VERIFY_BLOCK_TABLE:
|
||||
|
||||
// Block table is not protected by MD5
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case SFILE_VERIFY_HIBLOCK_TABLE:
|
||||
|
||||
// It is unknown if the hi-block table is protected my MD5 or not.
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
case SFILE_VERIFY_FILE:
|
||||
|
||||
// Verify parameters
|
||||
if(szFileName == NULL || *szFileName == 0)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
// Get the offset of a file
|
||||
pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale);
|
||||
if(pFileEntry == NULL)
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
|
||||
return VerifyRawMpqData(ha, pFileEntry->ByteOffset, pFileEntry->dwCmpSize);
|
||||
}
|
||||
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
||||
// Verifies the archive against the signature
|
||||
DWORD WINAPI SFileVerifyArchive(HANDLE hMpq)
|
||||
{
|
||||
MPQ_SIGNATURE_INFO si;
|
||||
TMPQArchive * ha = (TMPQArchive *)hMpq;
|
||||
|
||||
// Verify input parameters
|
||||
if(!IsValidMpqHandle(ha))
|
||||
return ERROR_VERIFY_FAILED;
|
||||
|
||||
// Get the MPQ signature and signature type
|
||||
memset(&si, 0, sizeof(MPQ_SIGNATURE_INFO));
|
||||
if(!QueryMpqSignatureInfo(ha, &si))
|
||||
return ERROR_VERIFY_FAILED;
|
||||
|
||||
// Verify the signature
|
||||
switch(si.nSignatureType)
|
||||
{
|
||||
case SIGNATURE_TYPE_NONE:
|
||||
return ERROR_NO_SIGNATURE;
|
||||
|
||||
case SIGNATURE_TYPE_WEAK:
|
||||
return VerifyWeakSignature(ha, &si);
|
||||
|
||||
case SIGNATURE_TYPE_STRONG:
|
||||
return VerifyStrongSignature(ha, &si);
|
||||
}
|
||||
|
||||
return ERROR_VERIFY_FAILED;
|
||||
}
|
||||
232
src/dep/src/StormLib/src/StormCommon.h
Normal file
232
src/dep/src/StormLib/src/StormCommon.h
Normal file
@ -0,0 +1,232 @@
|
||||
/*****************************************************************************/
|
||||
/* SCommon.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Common functions for encryption/decryption from Storm.dll. Included by */
|
||||
/* SFile*** functions, do not include and do not use this file directly */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 24.03.03 1.00 Lad The first version of SFileCommon.h */
|
||||
/* 12.06.04 1.00 Lad Renamed to SCommon.h */
|
||||
/* 06.09.10 1.00 Lad Renamed to StormCommon.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __STORMCOMMON_H__
|
||||
#define __STORMCOMMON_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compression support
|
||||
|
||||
// Include functions from Pkware Data Compression Library
|
||||
#include "pklib/pklib.h"
|
||||
|
||||
// Include functions from Huffmann compression
|
||||
#include "huffman/huff.h"
|
||||
|
||||
// Include functions from IMA ADPCM compression
|
||||
#include "adpcm/adpcm.h"
|
||||
|
||||
// Include functions from SPARSE compression
|
||||
#include "sparse/sparse.h"
|
||||
|
||||
// Include functions from LZMA compression
|
||||
#include "lzma/C/LzmaEnc.h"
|
||||
#include "lzma/C/LzmaDec.h"
|
||||
|
||||
// Include functions from zlib
|
||||
#ifndef __SYS_ZLIB
|
||||
#include "zlib/zlib.h"
|
||||
#else
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
// Include functions from bzlib
|
||||
#ifndef __SYS_BZLIB
|
||||
#include "bzip2/bzlib.h"
|
||||
#else
|
||||
#include <bzlib.h>
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Cryptography support
|
||||
|
||||
// Headers from LibTomCrypt
|
||||
#include "libtomcrypt/src/headers/tomcrypt.h"
|
||||
|
||||
// For HashStringJenkins
|
||||
#include "jenkins/lookup.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StormLib private defines
|
||||
|
||||
#define ID_MPQ_FILE 0x46494c45 // Used internally for checking TMPQFile ('FILE')
|
||||
|
||||
#define MPQ_WEAK_SIGNATURE_SIZE 64
|
||||
#define MPQ_STRONG_SIGNATURE_SIZE 256
|
||||
|
||||
// Prevent problems with CRT "min" and "max" functions,
|
||||
// as they are not defined on all platforms
|
||||
#define STORMLIB_MIN(a, b) ((a < b) ? a : b)
|
||||
#define STORMLIB_MAX(a, b) ((a > b) ? a : b)
|
||||
|
||||
// Macro for building 64-bit file offset from two 32-bit
|
||||
#define MAKE_OFFSET64(hi, lo) (((ULONGLONG)hi << 32) | lo)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StormLib internal global variables
|
||||
|
||||
extern DWORD dwGlobalFlags; // Global StormLib flags
|
||||
extern LCID lcFileLocale; // Preferred file locale
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Encryption and decryption functions
|
||||
|
||||
#define MPQ_HASH_TABLE_INDEX 0x000
|
||||
#define MPQ_HASH_NAME_A 0x100
|
||||
#define MPQ_HASH_NAME_B 0x200
|
||||
#define MPQ_HASH_FILE_KEY 0x300
|
||||
|
||||
DWORD HashString(const char * szFileName, DWORD dwHashType);
|
||||
|
||||
void InitializeMpqCryptography();
|
||||
|
||||
DWORD GetHashTableSizeForFileCount(DWORD dwFileCount);
|
||||
|
||||
bool IsPseudoFileName(const char * szFileName, LPDWORD pdwFileIndex);
|
||||
ULONGLONG HashStringJenkins(const char * szFileName);
|
||||
|
||||
void ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG FileSize, DWORD dwFlags);
|
||||
|
||||
void EncryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwKey);
|
||||
void DecryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwKey);
|
||||
|
||||
DWORD DetectFileKeyBySectorSize(LPDWORD SectorOffsets, DWORD decrypted);
|
||||
DWORD DetectFileKeyByContent(void * pvFileContent, DWORD dwFileSize);
|
||||
DWORD DecryptFileKey(const char * szFileName, ULONGLONG MpqPos, DWORD dwFileSize, DWORD dwFlags);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Handle validation functions
|
||||
|
||||
bool IsValidMpqHandle(TMPQArchive * ha);
|
||||
bool IsValidFileHandle(TMPQFile * hf);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hash table and block table manipulation
|
||||
|
||||
TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName);
|
||||
TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * pPrevHash);
|
||||
DWORD AllocateHashEntry(TMPQArchive * ha, TFileEntry * pFileEntry);
|
||||
DWORD AllocateHetEntry(TMPQArchive * ha, TFileEntry * pFileEntry);
|
||||
|
||||
void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos);
|
||||
|
||||
// Functions that load the HET abd BET tables
|
||||
int CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize);
|
||||
int LoadAnyHashTable(TMPQArchive * ha);
|
||||
int BuildFileTable(TMPQArchive * ha, ULONGLONG FileSize);
|
||||
int SaveMPQTables(TMPQArchive * ha);
|
||||
|
||||
TMPQHetTable * CreateHetTable(DWORD dwMaxFileCount, DWORD dwHashBitSize, bool bCreateEmpty);
|
||||
void FreeHetTable(TMPQHetTable * pHetTable);
|
||||
|
||||
TMPQBetTable * CreateBetTable(DWORD dwMaxFileCount);
|
||||
void FreeBetTable(TMPQBetTable * pBetTable);
|
||||
|
||||
// Functions for finding files in the file table
|
||||
TFileEntry * GetFileEntryAny(TMPQArchive * ha, const char * szFileName);
|
||||
TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
|
||||
TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
|
||||
TFileEntry * GetFileEntryByIndex(TMPQArchive * ha, DWORD dwIndex);
|
||||
|
||||
// Allocates file name in the file entry
|
||||
void AllocateFileName(TFileEntry * pFileEntry, const char * szFileName);
|
||||
|
||||
// Allocates new file entry in the MPQ tables. Reuses existing, if possible
|
||||
TFileEntry * FindFreeFileEntry(TMPQArchive * ha);
|
||||
TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcLocale);
|
||||
int RenameFileEntry(TMPQArchive * ha, TFileEntry * pFileEntry, const char * szNewFileName);
|
||||
void ClearFileEntry(TMPQArchive * ha, TFileEntry * pFileEntry);
|
||||
int FreeFileEntry(TMPQArchive * ha, TFileEntry * pFileEntry);
|
||||
|
||||
// Invalidates entries for (listfile) and (attributes)
|
||||
void InvalidateInternalFiles(TMPQArchive * ha);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Common functions - MPQ File
|
||||
|
||||
TMPQFile * CreateMpqFile(TMPQArchive * ha);
|
||||
int LoadMpqTable(TMPQArchive * ha, ULONGLONG ByteOffset, void * pvTable, DWORD dwCompressedSize, DWORD dwRealSize, DWORD dwKey);
|
||||
int AllocateSectorBuffer(TMPQFile * hf);
|
||||
int AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile);
|
||||
int AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile);
|
||||
int AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile);
|
||||
void CalculateRawSectorOffset(ULONGLONG & RawFilePos, TMPQFile * hf, DWORD dwSectorOffset);
|
||||
int WritePatchInfo(TMPQFile * hf);
|
||||
int WriteSectorOffsets(TMPQFile * hf);
|
||||
int WriteSectorChecksums(TMPQFile * hf);
|
||||
int WriteMemDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, void * pvRawData, DWORD dwRawDataSize, DWORD dwChunkSize, LPDWORD pcbTotalSize);
|
||||
int WriteMpqDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, DWORD dwRawDataSize, DWORD dwChunkSize);
|
||||
void FreeMPQFile(TMPQFile *& hf);
|
||||
|
||||
bool IsPatchData(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize);
|
||||
int PatchFileData(TMPQFile * hf);
|
||||
|
||||
void FreeMPQArchive(TMPQArchive *& ha);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Utility functions
|
||||
|
||||
bool CheckWildCard(const char * szString, const char * szWildCard);
|
||||
const char * GetPlainFileNameA(const char * szFileName);
|
||||
const TCHAR * GetPlainFileNameT(const TCHAR * szFileName);
|
||||
bool IsInternalMpqFileName(const char * szFileName);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Support for adding files to the MPQ
|
||||
|
||||
int SFileAddFile_Init(
|
||||
TMPQArchive * ha,
|
||||
const char * szArchivedName,
|
||||
ULONGLONG ft,
|
||||
DWORD dwFileSize,
|
||||
LCID lcLocale,
|
||||
DWORD dwFlags,
|
||||
TMPQFile ** phf
|
||||
);
|
||||
|
||||
int SFileAddFile_Write(
|
||||
TMPQFile * hf,
|
||||
const void * pvData,
|
||||
DWORD dwSize,
|
||||
DWORD dwCompression
|
||||
);
|
||||
|
||||
int SFileAddFile_Finish(
|
||||
TMPQFile * hf
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Attributes support
|
||||
|
||||
int SAttrLoadAttributes(TMPQArchive * ha);
|
||||
int SAttrFileSaveToMpq(TMPQArchive * ha);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Listfile functions
|
||||
|
||||
int SListFileSaveToMpq(TMPQArchive * ha);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Dump data support
|
||||
|
||||
#ifdef __STORMLIB_DUMP_DATA__
|
||||
void DumpMpqHeader(TMPQHeader * pHeader);
|
||||
void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable);
|
||||
|
||||
#else
|
||||
#define DumpMpqHeader(h) /* */
|
||||
#define DumpHetAndBetTable(h, b) /* */
|
||||
#endif
|
||||
|
||||
#endif // __STORMCOMMON_H__
|
||||
|
||||
988
src/dep/src/StormLib/src/StormLib.h
Normal file
988
src/dep/src/StormLib/src/StormLib.h
Normal file
@ -0,0 +1,988 @@
|
||||
/*****************************************************************************/
|
||||
/* StormLib.h Copyright (c) Ladislav Zezula 1999-2010 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* StormLib library v 7.02 */
|
||||
/* */
|
||||
/* Author : Ladislav Zezula */
|
||||
/* E-mail : ladik@zezula.net */
|
||||
/* WWW : http://www.zezula.net */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.99 1.00 Lad Created */
|
||||
/* 24.03.03 2.50 Lad Version 2.50 */
|
||||
/* 02.04.03 3.00 Lad Version 3.00 with compression */
|
||||
/* 11.04.03 3.01 Lad Renamed to StormLib.h for compatibility with */
|
||||
/* original headers for Storm.dll */
|
||||
/* 10.05.03 3.02 Lad Added Pkware DCL compression */
|
||||
/* 26.05.03 4.00 Lad Completed all compressions */
|
||||
/* 18.06.03 4.01 Lad Added SFileSetFileLocale */
|
||||
/* Added SFileExtractFile */
|
||||
/* 26.07.03 4.02 Lad Implemented nameless rename and delete */
|
||||
/* 26.07.03 4.03 Lad Added support for protected MPQs */
|
||||
/* 28.08.03 4.10 Lad Fixed bugs that caused StormLib incorrectly work */
|
||||
/* with Diablo I savegames and with files having full */
|
||||
/* hash table */
|
||||
/* 08.12.03 4.11 DCH Fixed bug in reading file sector larger than 0x1000 */
|
||||
/* on certain files. */
|
||||
/* Fixed bug in AddFile with MPQ_FILE_REPLACE_EXISTING */
|
||||
/* (Thanx Daniel Chiamarello, dchiamarello@madvawes.com)*/
|
||||
/* 21.12.03 4.50 Lad Completed port for Mac */
|
||||
/* Fixed bug in compacting (if fsize is mul of 0x1000) */
|
||||
/* Fixed bug in SCompCompress */
|
||||
/* 27.05.04 4.51 Lad Changed memory management from new/delete to our */
|
||||
/* own macros */
|
||||
/* 22.06.04 4.60 Lad Optimized search. Support for multiple listfiles. */
|
||||
/* 30.09.04 4.61 Lad Fixed some bugs (Aaargh !!!) */
|
||||
/* Correctly works if HashTableSize > BlockTableSize */
|
||||
/* 29.12.04 4.70 Lad Fixed compatibility problem with MPQs from WoW */
|
||||
/* 14.07.05 5.00 Lad Added the BZLIB compression support */
|
||||
/* Added suport of files stored as single unit */
|
||||
/* 17.04.06 5.01 Lad Converted to MS Visual Studio 8.0 */
|
||||
/* Fixed issue with protected Warcraft 3 protected maps */
|
||||
/* 15.05.06 5.02 Lad Fixed issue with WoW 1.10+ */
|
||||
/* 07.09.06 5.10 Lad Fixed processing files longer than 2GB */
|
||||
/* 22.11.06 6.00 Lad Support for MPQ archives V2 */
|
||||
/* 12.06.07 6.10 Lad Support for (attributes) file */
|
||||
/* 10.09.07 6.12 Lad Support for MPQs protected by corrupting hash table */
|
||||
/* 03.12.07 6.13 Lad Support for MPQs with hash tbl size > block tbl size */
|
||||
/* 07.04.08 6.20 Lad Added SFileFlushArchive */
|
||||
/* 09.04.08 Lad Removed FilePointer variable from MPQ handle */
|
||||
/* structure, as it caused more problems than benefits */
|
||||
/* 12.05.08 6.22 Lad Support for w3xMaster map protector */
|
||||
/* 05.10.08 6.23 Lad Support for protectors who set negative values in */
|
||||
/* the table of file blocks */
|
||||
/* 26.05.09 6.24 Lad Fixed search for multiple lang files with deleted */
|
||||
/* entries */
|
||||
/* 03.09.09 6.25 Lad Fixed decompression bug in huffmann decompression */
|
||||
/* 22.03.10 6.50 Lad New compressions in Starcraft II (LZMA, sparse) */
|
||||
/* Fixed compacting MPQs that contain single unit files */
|
||||
/* 26.04.10 7.00 Lad Major rewrite */
|
||||
/* 08.06.10 7.10 Lad Support for partial MPQs */
|
||||
/* 08.07.10 7.11 Lad Support for MPQs v 3.0 */
|
||||
/* 20.08.10 7.20 Lad Support for opening multiple MPQs in patch mode */
|
||||
/* 20.09.10 8.00 Lad MPQs v 4, HET and BET tables */
|
||||
/* 07.01.11 8.01 Lad Write support for MPQs v 3 and 4 */
|
||||
/* 15.09.11 8.04 Lad Bug fixes, testing for Diablo III MPQs */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __STORMLIB_H__
|
||||
#define __STORMLIB_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4668) // 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
|
||||
#pragma warning(disable:4820) // 'XXX' : '2' bytes padding added after data member 'XXX::yyy'
|
||||
#endif
|
||||
|
||||
#include "StormPort.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Use the apropriate library
|
||||
//
|
||||
// The library type is encoded in the library name as the following
|
||||
// StormLibXYZ.lib
|
||||
//
|
||||
// X - D for Debug version, R for Release version
|
||||
// Y - A for ANSI version, U for Unicode version
|
||||
// Z - S for static-linked CRT library, D for multithreaded DLL CRT library
|
||||
//
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__STORMLIB_SELF__)
|
||||
|
||||
#ifdef _DEBUG // DEBUG VERSIONS
|
||||
#ifndef _UNICODE
|
||||
#ifdef _DLL
|
||||
#pragma comment(lib, "StormLibDAD.lib") // Debug Ansi CRT-DLL version
|
||||
#else
|
||||
#pragma comment(lib, "StormLibDAS.lib") // Debug Ansi CRT-LIB version
|
||||
#endif
|
||||
#else
|
||||
#ifdef _DLL
|
||||
#pragma comment(lib, "StormLibDUD.lib") // Debug Unicode CRT-DLL version
|
||||
#else
|
||||
#pragma comment(lib, "StormLibDUS.lib") // Debug Unicode CRT-LIB version
|
||||
#endif
|
||||
#endif
|
||||
#else // RELEASE VERSIONS
|
||||
#ifndef _UNICODE
|
||||
#ifdef _DLL
|
||||
#pragma comment(lib, "StormLibRAD.lib") // Release Ansi CRT-DLL version
|
||||
#else
|
||||
#pragma comment(lib, "StormLibRAS.lib") // Release Ansi CRT-LIB version
|
||||
#endif
|
||||
#else
|
||||
#ifdef _DLL
|
||||
#pragma comment(lib, "StormLibRUD.lib") // Release Unicode CRT-DLL version
|
||||
#else
|
||||
#pragma comment(lib, "StormLibRUS.lib") // Release Unicode CRT-LIB version
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A')
|
||||
#define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B')
|
||||
|
||||
#define ERROR_AVI_FILE 10000 // No MPQ file, but AVI file.
|
||||
#define ERROR_UNKNOWN_FILE_KEY 10001 // Returned by SFileReadFile when can't find file key
|
||||
#define ERROR_CHECKSUM_ERROR 10002 // Returned by SFileReadFile when sector CRC doesn't match
|
||||
#define ERROR_INTERNAL_FILE 10003 // The given operation is not allowed on internal file
|
||||
#define ERROR_BASE_FILE_MISSING 10004 // The file is present as incremental patch file, but base file is missing
|
||||
#define ERROR_MARKED_FOR_DELETE 10005 // The file was marked as "deleted" in the MPQ
|
||||
|
||||
// Values for SFileCreateArchive
|
||||
#define HASH_TABLE_SIZE_MIN 0x00000004 // Minimum acceptable hash table size
|
||||
#define HASH_TABLE_SIZE_DEFAULT 0x00001000 // Default hash table size for empty MPQs
|
||||
#define HASH_TABLE_SIZE_MAX 0x00080000 // Maximum acceptable hash table size
|
||||
|
||||
#define HASH_ENTRY_DELETED 0xFFFFFFFE // Block index for deleted entry in the hash table
|
||||
#define HASH_ENTRY_FREE 0xFFFFFFFF // Block index for free entry in the hash table
|
||||
|
||||
#define HET_ENTRY_DELETED 0x80 // HET hash value for a deleted entry
|
||||
#define HET_ENTRY_FREE 0x00 // HET hash value for free entry
|
||||
|
||||
#define HASH_STATE_SIZE 0x60 // Size of LibTomCrypt's hash_state structure
|
||||
|
||||
#define MPQ_PATCH_PREFIX_LEN 0x20 // Maximum length of the patch prefix
|
||||
|
||||
// Values for TFileStream::Flags
|
||||
#define STREAM_FLAG_READ_ONLY 0x01 // The stream is read only
|
||||
#define STREAM_FLAG_PART_FILE 0x02 // The stream is a PART file.
|
||||
#define STREAM_FLAG_ENCRYPTED_FILE 0x04 // The stream is an encrypted MPQ (MPQE).
|
||||
|
||||
// Values for SFileOpenArchive
|
||||
#define SFILE_OPEN_HARD_DISK_FILE 2 // Open the archive on HDD
|
||||
#define SFILE_OPEN_CDROM_FILE 3 // Open the archive only if it is on CDROM
|
||||
|
||||
// Values for SFileOpenFile
|
||||
#define SFILE_OPEN_FROM_MPQ 0x00000000 // Open the file from the MPQ archive
|
||||
#define SFILE_OPEN_PATCHED_FILE 0x00000001 // Open the file from the MPQ archive
|
||||
#define SFILE_OPEN_ANY_LOCALE 0xFFFFFFFE // Reserved for StormLib internal use
|
||||
#define SFILE_OPEN_LOCAL_FILE 0xFFFFFFFF // Open a local file
|
||||
|
||||
// Flags for TMPQArchive::dwFlags
|
||||
#define MPQ_FLAG_READ_ONLY 0x00000001 // If set, the MPQ has been open for read-only access
|
||||
#define MPQ_FLAG_CHANGED 0x00000002 // If set, the MPQ tables have been changed
|
||||
#define MPQ_FLAG_PROTECTED 0x00000004 // Set on protected MPQs (like W3M maps)
|
||||
#define MPQ_FLAG_CHECK_SECTOR_CRC 0x0000008 // Checking sector CRC when reading files
|
||||
#define MPQ_FLAG_NEED_FIX_SIZE 0x00000010 // Used during opening the archive
|
||||
#define MPQ_FLAG_INV_LISTFILE 0x00000020 // If set, it means that the (listfile) has been invalidated
|
||||
#define MPQ_FLAG_INV_ATTRIBUTES 0x00000040 // If set, it means that the (attributes) has been invalidated
|
||||
|
||||
// Return value for SFilGetFileSize and SFileSetFilePointer
|
||||
#define SFILE_INVALID_SIZE 0xFFFFFFFF
|
||||
#define SFILE_INVALID_POS 0xFFFFFFFF
|
||||
#define SFILE_INVALID_ATTRIBUTES 0xFFFFFFFF
|
||||
|
||||
// Flags for SFileAddFile
|
||||
#define MPQ_FILE_IMPLODE 0x00000100 // Implode method (By PKWARE Data Compression Library)
|
||||
#define MPQ_FILE_COMPRESS 0x00000200 // Compress methods (By multiple methods)
|
||||
#define MPQ_FILE_COMPRESSED 0x0000FF00 // File is compressed
|
||||
#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted
|
||||
#define MPQ_FILE_FIX_KEY 0x00020000 // File decryption key has to be fixed
|
||||
#define MPQ_FILE_PATCH_FILE 0x00100000 // The file is a patch file. Raw file data begin with TPatchInfo structure
|
||||
#define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam)
|
||||
#define MPQ_FILE_DELETE_MARKER 0x02000000 // File is a deletion marker, indicating that the file no longer exists.
|
||||
#define MPQ_FILE_SECTOR_CRC 0x04000000 // File has checksums for each sector.
|
||||
// Ignored if file is not compressed or imploded.
|
||||
#define MPQ_FILE_EXISTS 0x80000000 // Set if file exists, reset when the file was deleted
|
||||
#define MPQ_FILE_REPLACEEXISTING 0x80000000 // Replace when the file exist (SFileAddFile)
|
||||
|
||||
#define MPQ_FILE_VALID_FLAGS (MPQ_FILE_IMPLODE | \
|
||||
MPQ_FILE_COMPRESS | \
|
||||
MPQ_FILE_ENCRYPTED | \
|
||||
MPQ_FILE_FIX_KEY | \
|
||||
MPQ_FILE_PATCH_FILE | \
|
||||
MPQ_FILE_SINGLE_UNIT | \
|
||||
MPQ_FILE_DELETE_MARKER | \
|
||||
MPQ_FILE_SECTOR_CRC | \
|
||||
MPQ_FILE_EXISTS)
|
||||
|
||||
// Compression types for multiple compressions
|
||||
#define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only)
|
||||
#define MPQ_COMPRESSION_ZLIB 0x02 // ZLIB compression
|
||||
#define MPQ_COMPRESSION_PKWARE 0x08 // PKWARE DCL compression
|
||||
#define MPQ_COMPRESSION_BZIP2 0x10 // BZIP2 compression (added in Warcraft III)
|
||||
#define MPQ_COMPRESSION_SPARSE 0x20 // Sparse compression (added in Starcraft 2)
|
||||
#define MPQ_COMPRESSION_ADPCM_MONO 0x40 // IMA ADPCM compression (mono)
|
||||
#define MPQ_COMPRESSION_ADPCM_STEREO 0x80 // IMA ADPCM compression (stereo)
|
||||
|
||||
// For backward compatibility
|
||||
#define MPQ_COMPRESSION_WAVE_MONO 0x40 // IMA ADPCM compression (mono)
|
||||
#define MPQ_COMPRESSION_WAVE_STEREO 0x80 // IMA ADPCM compression (stereo)
|
||||
|
||||
// LZMA compression. Added in Starcraft 2. This value is NOT a combination of flags.
|
||||
#define MPQ_COMPRESSION_LZMA 0x12
|
||||
|
||||
// Constants for SFileAddWave
|
||||
#define MPQ_WAVE_QUALITY_HIGH 0 // Best quality, the worst compression
|
||||
#define MPQ_WAVE_QUALITY_MEDIUM 1 // Medium quality, medium compression
|
||||
#define MPQ_WAVE_QUALITY_LOW 2 // Low quality, the best compression
|
||||
|
||||
// Signatures for HET and BET table
|
||||
#define HET_TABLE_SIGNATURE 0x1A544548 // 'HET\x1a'
|
||||
#define BET_TABLE_SIGNATURE 0x1A544542 // 'BET\x1a'
|
||||
|
||||
// Decryption keys for MPQ tables
|
||||
#define MPQ_KEY_HASH_TABLE 0xC3AF3770 // Obtained by HashString("(hash table)", MPQ_HASH_FILE_KEY)
|
||||
#define MPQ_KEY_BLOCK_TABLE 0xEC83B3A3 // Obtained by HashString("(block table)", MPQ_HASH_FILE_KEY)
|
||||
|
||||
// Constants for SFileGetFileInfo
|
||||
#define SFILE_INFO_ARCHIVE_NAME 1 // MPQ size (value from header)
|
||||
#define SFILE_INFO_ARCHIVE_SIZE 2 // MPQ size (value from header)
|
||||
#define SFILE_INFO_MAX_FILE_COUNT 3 // Max number of files in the MPQ
|
||||
#define SFILE_INFO_HASH_TABLE_SIZE 4 // Size of hash table, in entries
|
||||
#define SFILE_INFO_BLOCK_TABLE_SIZE 5 // Number of entries in the block table
|
||||
#define SFILE_INFO_SECTOR_SIZE 6 // Size of file sector (in bytes)
|
||||
#define SFILE_INFO_HASH_TABLE 7 // Pointer to Hash table (TMPQHash *)
|
||||
#define SFILE_INFO_BLOCK_TABLE 8 // Pointer to Block Table (TMPQBlock *)
|
||||
#define SFILE_INFO_NUM_FILES 9 // Real number of files within archive
|
||||
#define SFILE_INFO_STREAM_FLAGS 10 // Stream flags for the MPQ. See STREAM_FLAG_XXX
|
||||
#define SFILE_INFO_IS_READ_ONLY 11 // TRUE of the MPQ was open as read only
|
||||
//------
|
||||
#define SFILE_INFO_HASH_INDEX 100 // Hash index of file in MPQ
|
||||
#define SFILE_INFO_CODENAME1 101 // The first codename of the file
|
||||
#define SFILE_INFO_CODENAME2 102 // The second codename of the file
|
||||
#define SFILE_INFO_LOCALEID 103 // Locale ID of file in MPQ
|
||||
#define SFILE_INFO_BLOCKINDEX 104 // Index to Block Table
|
||||
#define SFILE_INFO_FILE_SIZE 105 // Original file size (from the block table)
|
||||
#define SFILE_INFO_COMPRESSED_SIZE 106 // Compressed file size (from the block table)
|
||||
#define SFILE_INFO_FLAGS 107 // File flags
|
||||
#define SFILE_INFO_POSITION 108 // File position within archive
|
||||
#define SFILE_INFO_KEY 109 // File decryption key
|
||||
#define SFILE_INFO_KEY_UNFIXED 110 // Decryption key not fixed to file pos and size
|
||||
#define SFILE_INFO_FILETIME 111 // TMPQFileTime
|
||||
#define SFILE_INFO_PATCH_CHAIN 112 // Chain of patches
|
||||
|
||||
#define LISTFILE_NAME "(listfile)" // Name of internal listfile
|
||||
#define SIGNATURE_NAME "(signature)" // Name of internal signature
|
||||
#define ATTRIBUTES_NAME "(attributes)" // Name of internal attributes file
|
||||
|
||||
#define STORMLIB_VERSION 0x0804 // Current version of StormLib (8.04)
|
||||
#define STORMLIB_VERSION_STRING "8.04"
|
||||
|
||||
#define MPQ_FORMAT_VERSION_1 0 // Up to The Burning Crusade
|
||||
#define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer
|
||||
#define MPQ_FORMAT_VERSION_3 2 // WoW Cataclysm Beta
|
||||
#define MPQ_FORMAT_VERSION_4 3 // WoW Cataclysm and newer
|
||||
|
||||
// Flags for MPQ attributes
|
||||
#define MPQ_ATTRIBUTE_CRC32 0x00000001 // The "(attributes)" contains CRC32 for each file
|
||||
#define MPQ_ATTRIBUTE_FILETIME 0x00000002 // The "(attributes)" contains file time for each file
|
||||
#define MPQ_ATTRIBUTE_MD5 0x00000004 // The "(attributes)" contains MD5 for each file
|
||||
#define MPQ_ATTRIBUTE_ALL 0x00000007 // Summary mask
|
||||
|
||||
#define MPQ_ATTRIBUTES_V1 100 // (attributes) format version 1.00
|
||||
|
||||
// Flags for SFileOpenArchive
|
||||
#define MPQ_OPEN_NO_LISTFILE 0x0010 // Don't load the internal listfile
|
||||
#define MPQ_OPEN_NO_ATTRIBUTES 0x0020 // Don't open the attributes
|
||||
#define MPQ_OPEN_FORCE_MPQ_V1 0x0040 // Always open the archive as MPQ v 1.00, ignore the "wFormatVersion" variable in the header
|
||||
#define MPQ_OPEN_CHECK_SECTOR_CRC 0x0080 // On files with MPQ_FILE_SECTOR_CRC, the CRC will be checked when reading file
|
||||
#define MPQ_OPEN_READ_ONLY 0x0100 // Open the archive for read-only access
|
||||
#define MPQ_OPEN_ENCRYPTED 0x0200 // Opens an encrypted MPQ archive (Example: Starcraft II installation)
|
||||
|
||||
// Flags for SFileCreateArchive
|
||||
#define MPQ_CREATE_ATTRIBUTES 0x00000001 // Also add the (attributes) file
|
||||
#define MPQ_CREATE_ARCHIVE_V1 0x00000000 // Creates archive of version 1 (size up to 4GB)
|
||||
#define MPQ_CREATE_ARCHIVE_V2 0x00010000 // Creates archive of version 2 (larger than 4 GB)
|
||||
#define MPQ_CREATE_ARCHIVE_V3 0x00020000 // Creates archive of version 3
|
||||
#define MPQ_CREATE_ARCHIVE_V4 0x00030000 // Creates archive of version 4
|
||||
#define MPQ_CREATE_ARCHIVE_VMASK 0x000F0000 // Mask for archive version
|
||||
|
||||
// Flags for SFileVerifyFile
|
||||
#define SFILE_VERIFY_SECTOR_CRC 0x0001 // Verify sector checksum for the file, if available
|
||||
#define SFILE_VERIFY_FILE_CRC 0x0002 // Verify file CRC, if available
|
||||
#define SFILE_VERIFY_FILE_MD5 0x0004 // Verify file MD5, if available
|
||||
#define SFILE_VERIFY_RAW_MD5 0x0008 // Verify raw file MD5, if available
|
||||
#define SFILE_VERIFY_ALL 0x000F // Verify every checksum possible
|
||||
|
||||
// Return values for SFileVerifyFile
|
||||
#define VERIFY_OPEN_ERROR 0x0001 // Failed to open the file
|
||||
#define VERIFY_READ_ERROR 0x0002 // Failed to read all data from the file
|
||||
#define VERIFY_FILE_HAS_SECTOR_CRC 0x0004 // File has sector CRC
|
||||
#define VERIFY_FILE_SECTOR_CRC_ERROR 0x0008 // Sector CRC check failed
|
||||
#define VERIFY_FILE_HAS_CHECKSUM 0x0010 // File has CRC32
|
||||
#define VERIFY_FILE_CHECKSUM_ERROR 0x0020 // CRC32 check failed
|
||||
#define VERIFY_FILE_HAS_MD5 0x0040 // File has data MD5
|
||||
#define VERIFY_FILE_MD5_ERROR 0x0080 // MD5 check failed
|
||||
#define VERIFY_FILE_HAS_RAW_MD5 0x0100 // File has raw data MD5
|
||||
#define VERIFY_FILE_RAW_MD5_ERROR 0x0200 // Raw MD5 check failed
|
||||
#define VERIFY_FILE_ERROR_MASK (VERIFY_OPEN_ERROR | VERIFY_READ_ERROR | VERIFY_FILE_SECTOR_CRC_ERROR | VERIFY_FILE_CHECKSUM_ERROR | VERIFY_FILE_MD5_ERROR | VERIFY_FILE_RAW_MD5_ERROR)
|
||||
|
||||
// Flags for SFileVerifyRawData (for MPQs version 4.0 or higher)
|
||||
#define SFILE_VERIFY_MPQ_HEADER 0x0001 // Verify raw MPQ header
|
||||
#define SFILE_VERIFY_HET_TABLE 0x0002 // Verify raw data of the HET table
|
||||
#define SFILE_VERIFY_BET_TABLE 0x0003 // Verify raw data of the BET table
|
||||
#define SFILE_VERIFY_HASH_TABLE 0x0004 // Verify raw data of the hash table
|
||||
#define SFILE_VERIFY_BLOCK_TABLE 0x0005 // Verify raw data of the block table
|
||||
#define SFILE_VERIFY_HIBLOCK_TABLE 0x0006 // Verify raw data of the hi-block table
|
||||
#define SFILE_VERIFY_FILE 0x0007 // Verify raw data of a file
|
||||
|
||||
// Return values for SFileVerifyArchive
|
||||
#define ERROR_NO_SIGNATURE 0 // There is no signature in the MPQ
|
||||
#define ERROR_VERIFY_FAILED 1 // There was an error during verifying signature (like no memory)
|
||||
#define ERROR_WEAK_SIGNATURE_OK 2 // There is a weak signature and sign check passed
|
||||
#define ERROR_WEAK_SIGNATURE_ERROR 3 // There is a weak signature but sign check failed
|
||||
#define ERROR_STRONG_SIGNATURE_OK 4 // There is a strong signature and sign check passed
|
||||
#define ERROR_STRONG_SIGNATURE_ERROR 5 // There is a strong signature but sign check failed
|
||||
|
||||
#ifndef MD5_DIGEST_SIZE
|
||||
#define MD5_DIGEST_SIZE 0x10
|
||||
#endif
|
||||
|
||||
#ifndef SHA1_DIGEST_SIZE
|
||||
#define SHA1_DIGEST_SIZE 0x14 // 160 bits
|
||||
#endif
|
||||
|
||||
#ifndef LANG_NEUTRAL
|
||||
#define LANG_NEUTRAL 0x00 // Neutral locale
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Callback functions
|
||||
|
||||
// Values for compact callback
|
||||
#define CCB_CHECKING_FILES 1 // Checking archive (dwParam1 = current, dwParam2 = total)
|
||||
#define CCB_CHECKING_HASH_TABLE 2 // Checking hash table (dwParam1 = current, dwParam2 = total)
|
||||
#define CCB_COPYING_NON_MPQ_DATA 3 // Copying non-MPQ data: No params used
|
||||
#define CCB_COMPACTING_FILES 4 // Compacting archive (dwParam1 = current, dwParam2 = total)
|
||||
#define CCB_CLOSING_ARCHIVE 5 // Closing archive: No params used
|
||||
|
||||
typedef void (WINAPI * SFILE_ADDFILE_CALLBACK)(void * pvUserData, DWORD dwBytesWritten, DWORD dwTotalBytes, bool bFinalCall);
|
||||
typedef void (WINAPI * SFILE_COMPACT_CALLBACK)(void * pvUserData, DWORD dwWorkType, ULONGLONG BytesProcessed, ULONGLONG TotalBytes);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Stream support - structures
|
||||
|
||||
struct TFileStream;
|
||||
|
||||
typedef bool (*STREAM_GETPOS)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG & ByteOffset // Pointer to store current file position
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_READ)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
|
||||
void * pvBuffer, // Pointer to data to be read
|
||||
DWORD dwBytesToRead // Number of bytes to read from the file
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_WRITE)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it writes to the current position
|
||||
const void * pvBuffer, // Pointer to data to be written
|
||||
DWORD dwBytesToWrite // Number of bytes to read from the file
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_GETSIZE)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG & FileSize // Receives the file size, in bytes
|
||||
);
|
||||
|
||||
typedef bool (*STREAM_SETSIZE)(
|
||||
struct TFileStream * pStream, // Pointer to an open stream
|
||||
ULONGLONG FileSize // New size for the file, in bytes
|
||||
);
|
||||
|
||||
// Common stream structure. Can be variable length
|
||||
struct TFileStream
|
||||
{
|
||||
ULONGLONG RawFilePos; // Current position in raw file
|
||||
HANDLE hFile; // File handle. Do not use directly.
|
||||
TCHAR szFileName[MAX_PATH];// Name of the file
|
||||
BYTE StreamFlags; // See STREAM_FLAG_XXXX
|
||||
|
||||
STREAM_GETPOS StreamGetPos; // Pointer to function that returns current file position
|
||||
STREAM_READ StreamRead; // Pointer to stream read function for this archive. Do not use directly.
|
||||
STREAM_WRITE StreamWrite; // Pointer to stream write function for this archive. Do not use directly.
|
||||
STREAM_GETSIZE StreamGetSize; // Pointer to function returning file size
|
||||
STREAM_SETSIZE StreamSetSize; // Pointer to function changing file size
|
||||
|
||||
// Extra members may follow
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structure for bit arrays used for HET and BET tables
|
||||
|
||||
struct TBitArray
|
||||
{
|
||||
void GetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
|
||||
void SetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
|
||||
|
||||
DWORD NumberOfBits; // Total number of bits that are available
|
||||
BYTE Elements[1]; // Array of elements (variable length)
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures related to MPQ format
|
||||
//
|
||||
// Note: All structures in this header file are supposed to remain private
|
||||
// to StormLib. The structures may (and will) change over time, as the MPQ
|
||||
// file format evolves. Programmers directly using these structures need to
|
||||
// be aware of this. And the last, but not least, NEVER do any modifications
|
||||
// to those structures directly, always use SFile* functions.
|
||||
//
|
||||
|
||||
#define MPQ_HEADER_SIZE_V1 0x20
|
||||
#define MPQ_HEADER_SIZE_V2 0x2C
|
||||
#define MPQ_HEADER_SIZE_V3 0x44
|
||||
#define MPQ_HEADER_SIZE_V4 0xD0
|
||||
|
||||
struct TMPQUserData
|
||||
{
|
||||
// The ID_MPQ_USERDATA ('MPQ\x1B') signature
|
||||
DWORD dwID;
|
||||
|
||||
// Maximum size of the user data
|
||||
DWORD cbUserDataSize;
|
||||
|
||||
// Offset of the MPQ header, relative to the begin of this header
|
||||
DWORD dwHeaderOffs;
|
||||
|
||||
// Appears to be size of user data header (Starcraft II maps)
|
||||
DWORD cbUserDataHeader;
|
||||
};
|
||||
|
||||
// MPQ file header
|
||||
//
|
||||
// We have to make sure that the header is packed OK.
|
||||
// Reason: A 64-bit integer at the beginning of 3.0 part,
|
||||
// which is offset 0x2C
|
||||
#pragma pack(push, 1)
|
||||
struct TMPQHeader
|
||||
{
|
||||
// The ID_MPQ ('MPQ\x1A') signature
|
||||
DWORD dwID;
|
||||
|
||||
// Size of the archive header
|
||||
DWORD dwHeaderSize;
|
||||
|
||||
// 32-bit size of MPQ archive
|
||||
// This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive
|
||||
// is calculated as the size from the beginning of the archive to the end of the hash table,
|
||||
// block table, or hi-block table (whichever is largest).
|
||||
DWORD dwArchiveSize;
|
||||
|
||||
// 0 = Format 1 (up to The Burning Crusade)
|
||||
// 1 = Format 2 (The Burning Crusade and newer)
|
||||
// 2 = Format 3 (WoW - Cataclysm beta or newer)
|
||||
// 3 = Format 4 (WoW - Cataclysm beta or newer)
|
||||
USHORT wFormatVersion;
|
||||
|
||||
// Power of two exponent specifying the number of 512-byte disk sectors in each file sector
|
||||
// in the archive. The size of each file sector in the archive is 512 * 2 ^ wSectorSize.
|
||||
USHORT wSectorSize;
|
||||
|
||||
// Offset to the beginning of the hash table, relative to the beginning of the archive.
|
||||
DWORD dwHashTablePos;
|
||||
|
||||
// Offset to the beginning of the block table, relative to the beginning of the archive.
|
||||
DWORD dwBlockTablePos;
|
||||
|
||||
// Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for
|
||||
// the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
|
||||
DWORD dwHashTableSize;
|
||||
|
||||
// Number of entries in the block table
|
||||
DWORD dwBlockTableSize;
|
||||
|
||||
//-- MPQ HEADER v 2 -------------------------------------------
|
||||
|
||||
// Offset to the beginning of array of 16-bit high parts of file offsets.
|
||||
ULONGLONG HiBlockTablePos64;
|
||||
|
||||
// High 16 bits of the hash table offset for large archives.
|
||||
USHORT wHashTablePosHi;
|
||||
|
||||
// High 16 bits of the block table offset for large archives.
|
||||
USHORT wBlockTablePosHi;
|
||||
|
||||
//-- MPQ HEADER v 3 -------------------------------------------
|
||||
|
||||
// 64-bit version of the archive size
|
||||
ULONGLONG ArchiveSize64;
|
||||
|
||||
// 64-bit position of the BET table
|
||||
ULONGLONG BetTablePos64;
|
||||
|
||||
// 64-bit position of the HET table
|
||||
ULONGLONG HetTablePos64;
|
||||
|
||||
//-- MPQ HEADER v 4 -------------------------------------------
|
||||
|
||||
// Compressed size of the hash table
|
||||
ULONGLONG HashTableSize64;
|
||||
|
||||
// Compressed size of the block table
|
||||
ULONGLONG BlockTableSize64;
|
||||
|
||||
// Compressed size of the hi-block table
|
||||
ULONGLONG HiBlockTableSize64;
|
||||
|
||||
// Compressed size of the HET block
|
||||
ULONGLONG HetTableSize64;
|
||||
|
||||
// Compressed size of the BET block
|
||||
ULONGLONG BetTableSize64;
|
||||
|
||||
// Size of raw data chunk to calculate MD5.
|
||||
// MD5 of each data chunk follows the raw file data.
|
||||
DWORD dwRawChunkSize;
|
||||
|
||||
// MD5 of MPQ tables
|
||||
unsigned char MD5_BlockTable[MD5_DIGEST_SIZE]; // MD5 of the block table before decryption
|
||||
unsigned char MD5_HashTable[MD5_DIGEST_SIZE]; // MD5 of the hash table before decryption
|
||||
unsigned char MD5_HiBlockTable[MD5_DIGEST_SIZE]; // MD5 of the hi-block table
|
||||
unsigned char MD5_BetTable[MD5_DIGEST_SIZE]; // MD5 of the BET table before decryption
|
||||
unsigned char MD5_HetTable[MD5_DIGEST_SIZE]; // MD5 of the HET table before decryption
|
||||
unsigned char MD5_MpqHeader[MD5_DIGEST_SIZE]; // MD5 of the MPQ header from signature to (including) MD5_HetTable
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
// Hash entry. All files in the archive are searched by their hashes.
|
||||
struct TMPQHash
|
||||
{
|
||||
// The hash of the file path, using method A.
|
||||
DWORD dwName1;
|
||||
|
||||
// The hash of the file path, using method B.
|
||||
DWORD dwName2;
|
||||
|
||||
#ifdef PLATFORM_LITTLE_ENDIAN
|
||||
|
||||
// The language of the file. This is a Windows LANGID data type, and uses the same values.
|
||||
// 0 indicates the default language (American English), or that the file is language-neutral.
|
||||
USHORT lcLocale;
|
||||
|
||||
// The platform the file is used for. 0 indicates the default platform.
|
||||
// No other values have been observed.
|
||||
// Note: wPlatform is actually just BYTE, but since it has never been used, we don't care.
|
||||
USHORT wPlatform;
|
||||
|
||||
#else
|
||||
|
||||
USHORT wPlatform;
|
||||
USHORT lcLocale;
|
||||
|
||||
#endif
|
||||
|
||||
// If the hash table entry is valid, this is the index into the block table of the file.
|
||||
// Otherwise, one of the following two values:
|
||||
// - FFFFFFFFh: Hash table entry is empty, and has always been empty.
|
||||
// Terminates searches for a given file.
|
||||
// - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file).
|
||||
// Does not terminate searches for a given file.
|
||||
DWORD dwBlockIndex;
|
||||
};
|
||||
|
||||
|
||||
// File description block contains informations about the file
|
||||
struct TMPQBlock
|
||||
{
|
||||
// Offset of the beginning of the file, relative to the beginning of the archive.
|
||||
DWORD dwFilePos;
|
||||
|
||||
// Compressed file size
|
||||
DWORD dwCSize;
|
||||
|
||||
// Only valid if the block is a file; otherwise meaningless, and should be 0.
|
||||
// If the file is compressed, this is the size of the uncompressed file data.
|
||||
DWORD dwFSize;
|
||||
|
||||
// Flags for the file. See MPQ_FILE_XXXX constants
|
||||
DWORD dwFlags;
|
||||
};
|
||||
|
||||
// Patch file information, preceding the sector offset table
|
||||
struct TPatchInfo
|
||||
{
|
||||
DWORD dwLength; // Length of patch info header, in bytes
|
||||
DWORD dwFlags; // Flags. 0x80000000 = MD5 (?)
|
||||
DWORD dwDataSize; // Uncompressed size of the patch file
|
||||
BYTE md5[0x10]; // MD5 of the entire patch file after decompression
|
||||
|
||||
// Followed by the sector table (variable length)
|
||||
};
|
||||
|
||||
// Header for PTCH files
|
||||
struct TPatchHeader
|
||||
{
|
||||
//-- PATCH header -----------------------------------
|
||||
DWORD dwSignature; // 'PTCH'
|
||||
DWORD dwSizeOfPatchData; // Size of the entire patch (decompressed)
|
||||
DWORD dwSizeBeforePatch; // Size of the file before patch
|
||||
DWORD dwSizeAfterPatch; // Size of file after patch
|
||||
|
||||
//-- MD5 block --------------------------------------
|
||||
DWORD dwMD5; // 'MD5_'
|
||||
DWORD dwMd5BlockSize; // Size of the MD5 block, including the signature and size itself
|
||||
BYTE md5_before_patch[0x10]; // MD5 of the original (unpached) file
|
||||
BYTE md5_after_patch[0x10]; // MD5 of the patched file
|
||||
|
||||
//-- XFRM block -------------------------------------
|
||||
DWORD dwXFRM; // 'XFRM'
|
||||
DWORD dwXfrmBlockSize; // Size of the XFRM block, includes XFRM header and patch data
|
||||
DWORD dwPatchType; // Type of patch ('BSD0' or 'COPY')
|
||||
|
||||
// Followed by the patch data
|
||||
};
|
||||
|
||||
#define SIZE_OF_XFRM_HEADER 0x0C
|
||||
|
||||
// This is the combined file entry for maintaining file list in the MPQ.
|
||||
// This structure is combined from block table, hi-block table,
|
||||
// (attributes) file and from (listfile).
|
||||
struct TFileEntry
|
||||
{
|
||||
ULONGLONG ByteOffset; // Position of the file content in the MPQ, relative to the MPQ header
|
||||
ULONGLONG FileTime; // FileTime from the (attributes) file. 0 if not present.
|
||||
ULONGLONG BetHash; // Lower part of the file name hash. Only used when the MPQ has BET table.
|
||||
DWORD dwHashIndex; // Index to the hash table. Only used when the MPQ has classic hash table
|
||||
DWORD dwHetIndex; // Index to the HET table. Only used when the MPQ has HET table
|
||||
DWORD dwFileSize; // Decompressed size of the file
|
||||
DWORD dwCmpSize; // Compressed size of the file (i.e., size of the file data in the MPQ)
|
||||
DWORD dwFlags; // File flags (from block table)
|
||||
USHORT lcLocale; // Locale ID for the file
|
||||
USHORT wPlatform; // Platform ID for the file
|
||||
DWORD dwCrc32; // CRC32 from (attributes) file. 0 if not present.
|
||||
unsigned char md5[MD5_DIGEST_SIZE]; // File MD5 from the (attributes) file. 0 if not present.
|
||||
char * szFileName; // File name. NULL if not known.
|
||||
};
|
||||
|
||||
// Common header for HET and BET tables
|
||||
struct TMPQExtTable
|
||||
{
|
||||
DWORD dwSignature; // 'HET\x1A' or 'BET\x1A'
|
||||
DWORD dwVersion; // Version. Seems to be always 1
|
||||
DWORD dwDataSize; // Size of the contained table
|
||||
|
||||
// Followed by the table header
|
||||
// Followed by the table data
|
||||
|
||||
};
|
||||
|
||||
// Structure for parsed HET table
|
||||
struct TMPQHetTable
|
||||
{
|
||||
TBitArray * pBetIndexes; // Bit array of indexes to BET tables
|
||||
LPBYTE pHetHashes; // Array of HET hashes. Each entry has size of 1 byte
|
||||
ULONGLONG AndMask64; // AND mask used for calculating file name hash
|
||||
ULONGLONG OrMask64; // OR mask used for setting the highest bit of the file name hash
|
||||
|
||||
DWORD dwIndexSizeTotal; // Total size of one entry in pBetIndexes (in bits)
|
||||
DWORD dwIndexSizeExtra; // Extra bits in the entry in pBetIndexes
|
||||
DWORD dwIndexSize; // Effective size of one entry in pBetIndexes (in bits)
|
||||
DWORD dwMaxFileCount; // Maximum number of files in the MPQ
|
||||
DWORD dwHashTableSize; // Number of entries in pBetHashes
|
||||
DWORD dwHashBitSize; // Effective number of bits in the hash
|
||||
};
|
||||
|
||||
// Structure for parsed BET table
|
||||
struct TMPQBetTable
|
||||
{
|
||||
TBitArray * pBetHashes; // Array of BET hashes
|
||||
TBitArray * pFileTable; // Bit-based file table
|
||||
LPDWORD pFileFlags; // Array of file flags
|
||||
|
||||
DWORD dwTableEntrySize; // Size of one table entry, in bits
|
||||
DWORD dwBitIndex_FilePos; // Bit index of the file position in the table entry
|
||||
DWORD dwBitIndex_FileSize; // Bit index of the file size in the table entry
|
||||
DWORD dwBitIndex_CmpSize; // Bit index of the compressed size in the table entry
|
||||
DWORD dwBitIndex_FlagIndex; // Bit index of the flag index in the table entry
|
||||
DWORD dwBitIndex_Unknown; // Bit index of ??? in the table entry
|
||||
DWORD dwBitCount_FilePos; // Size of file offset (in bits) within table entry
|
||||
DWORD dwBitCount_FileSize; // Size of file size (in bits) within table entry
|
||||
DWORD dwBitCount_CmpSize; // Size of compressed file size (in bits) within table entry
|
||||
DWORD dwBitCount_FlagIndex; // Size of flag index (in bits) within table entry
|
||||
DWORD dwBitCount_Unknown; // Size of ??? (in bits) within table entry
|
||||
DWORD dwBetHashSizeTotal; // Total size of bet hash
|
||||
DWORD dwBetHashSizeExtra; // Extra bits in the bet hash
|
||||
DWORD dwBetHashSize; // Effective size of the bet hash
|
||||
DWORD dwFileCount; // Number of files (usually equal to maximum number of files)
|
||||
DWORD dwFlagCount; // Number of entries in pFileFlags
|
||||
};
|
||||
|
||||
// Archive handle structure
|
||||
struct TMPQArchive
|
||||
{
|
||||
TFileStream * pStream; // Open stream for the MPQ
|
||||
|
||||
ULONGLONG UserDataPos; // Position of user data (relative to the begin of the file)
|
||||
ULONGLONG MpqPos; // MPQ header offset (relative to the begin of the file)
|
||||
|
||||
TMPQArchive * haPatch; // Pointer to patch archive, if any
|
||||
TMPQArchive * haBase; // Pointer to base ("previous version") archive, if any
|
||||
char szPatchPrefix[MPQ_PATCH_PREFIX_LEN]; // Prefix for file names in patch MPQs
|
||||
size_t cchPatchPrefix; // Length of the patch prefix, in characters
|
||||
|
||||
TMPQUserData * pUserData; // MPQ user data (NULL if not present in the file)
|
||||
TMPQHeader * pHeader; // MPQ file header
|
||||
TMPQHash * pHashTable; // Hash table
|
||||
TMPQHetTable * pHetTable; // Het table
|
||||
TFileEntry * pFileTable; // File table
|
||||
|
||||
TMPQUserData UserData; // MPQ user data. Valid only when ID_MPQ_USERDATA has been found
|
||||
BYTE HeaderData[MPQ_HEADER_SIZE_V4]; // Storage for MPQ header
|
||||
|
||||
DWORD dwHETBlockSize;
|
||||
DWORD dwBETBlockSize;
|
||||
DWORD dwFileTableSize; // Current size of the file table, e.g. index of the entry past the last occupied one
|
||||
DWORD dwMaxFileCount; // Maximum number of files in the MPQ
|
||||
DWORD dwSectorSize; // Default size of one file sector
|
||||
DWORD dwFileFlags1; // Flags for (listfile)
|
||||
DWORD dwFileFlags2; // Flags for (attributes)
|
||||
DWORD dwAttrFlags; // Flags for the (attributes) file, see MPQ_ATTRIBUTE_XXX
|
||||
DWORD dwFlags; // See MPQ_FLAG_XXXXX
|
||||
};
|
||||
|
||||
// File handle structure
|
||||
struct TMPQFile
|
||||
{
|
||||
TFileStream * pStream; // File stream. Only used on local files
|
||||
TMPQArchive * ha; // Archive handle
|
||||
TFileEntry * pFileEntry; // File entry for the file
|
||||
DWORD dwFileKey; // Decryption key
|
||||
DWORD dwFilePos; // Current file position
|
||||
ULONGLONG RawFilePos; // Offset in MPQ archive (relative to file begin)
|
||||
ULONGLONG MpqFilePos; // Offset in MPQ archive (relative to MPQ header)
|
||||
DWORD dwMagic; // 'FILE'
|
||||
|
||||
TMPQFile * hfPatchFile; // Pointer to opened patch file
|
||||
TPatchHeader * pPatchHeader; // Patch header. Only used if the file is a patch file
|
||||
LPBYTE pbFileData; // Loaded and patched file data. Only used if the file is a patch file
|
||||
DWORD cbFileData; // Size of loaded patched data
|
||||
|
||||
TPatchInfo * pPatchInfo; // Patch info block, preceding the sector table
|
||||
DWORD * SectorOffsets; // Position of each file sector, relative to the begin of the file. Only for compressed files.
|
||||
DWORD * SectorChksums; // Array of ADLER32 values for each sector
|
||||
DWORD dwSectorCount; // Number of sectors in the file
|
||||
DWORD dwPatchedFileSize; // Size of patched file. Used when saving patch file to the MPQ
|
||||
DWORD dwDataSize; // Size of data in the file (on patch files, this differs from file size in block table entry)
|
||||
|
||||
LPBYTE pbFileSector; // Last loaded file sector. For single unit files, entire file content
|
||||
DWORD dwSectorOffs; // File position of currently loaded file sector
|
||||
DWORD dwSectorSize; // Size of the file sector. For single unit files, this is equal to the file size
|
||||
|
||||
unsigned char hctx[HASH_STATE_SIZE];// Hash state for MD5. Used when saving file to MPQ
|
||||
DWORD dwCrc32; // CRC32 value, used when saving file to MPQ
|
||||
BYTE PreviousCompression; // Compression of previous sector
|
||||
|
||||
bool bLoadedSectorCRCs; // If true, we already tried to load sector CRCs
|
||||
bool bCheckSectorCRCs; // If true, then SFileReadFile will check sector CRCs when reading the file
|
||||
bool bIsWriteHandle; // If true, this handle has been created by SFileCreateFile
|
||||
bool bErrorOccured; // If true, then at least one error occured during saving the file to the archive
|
||||
};
|
||||
|
||||
// Structure for SFileFindFirstFile and SFileFindNextFile
|
||||
typedef struct _SFILE_FIND_DATA
|
||||
{
|
||||
char cFileName[MAX_PATH]; // Full name of the found file
|
||||
char * szPlainName; // Plain name of the found file
|
||||
DWORD dwHashIndex; // Hash table index for the file
|
||||
DWORD dwBlockIndex; // Block table index for the file
|
||||
DWORD dwFileSize; // File size in bytes
|
||||
DWORD dwFileFlags; // MPQ file flags
|
||||
DWORD dwCompSize; // Compressed file size
|
||||
DWORD dwFileTimeLo; // Low 32-bits of the file time (0 if not present)
|
||||
DWORD dwFileTimeHi; // High 32-bits of the file time (0 if not present)
|
||||
LCID lcLocale; // Locale version
|
||||
|
||||
} SFILE_FIND_DATA, *PSFILE_FIND_DATA;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory management
|
||||
//
|
||||
// We use our own macros for allocating/freeing memory. If you want
|
||||
// to redefine them, please keep the following rules
|
||||
//
|
||||
// - The memory allocation must return NULL if not enough memory
|
||||
// (i.e not to throw exception)
|
||||
// - It is not necessary to fill the allocated buffer with zeros
|
||||
// - Memory freeing function doesn't have to test the pointer to NULL.
|
||||
//
|
||||
|
||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||
__inline void * DebugMalloc(char * /* szFile */, int /* nLine */, size_t nSize)
|
||||
{
|
||||
// return new BYTE[nSize];
|
||||
return HeapAlloc(GetProcessHeap(), 0, nSize);
|
||||
}
|
||||
|
||||
__inline void DebugFree(void * ptr)
|
||||
{
|
||||
// delete [] ptr;
|
||||
HeapFree(GetProcessHeap(), 0, ptr);
|
||||
}
|
||||
|
||||
#define ALLOCMEM(type, nitems) (type *)DebugMalloc(__FILE__, __LINE__, (nitems) * sizeof(type))
|
||||
#define FREEMEM(ptr) DebugFree(ptr)
|
||||
#else
|
||||
|
||||
#define ALLOCMEM(type, nitems) (type *)malloc((nitems) * sizeof(type))
|
||||
#define FREEMEM(ptr) free(ptr)
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Stream support - functions
|
||||
|
||||
TFileStream * FileStream_CreateFile(const TCHAR * szFileName);
|
||||
TFileStream * FileStream_OpenFile(const TCHAR * szFileName, bool bWriteAccess);
|
||||
TFileStream * FileStream_OpenEncrypted(const TCHAR * szFileName);
|
||||
bool FileStream_GetPos(TFileStream * pStream, ULONGLONG & ByteOffset);
|
||||
bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead);
|
||||
bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite);
|
||||
bool FileStream_GetLastWriteTime(TFileStream * pStream, ULONGLONG * pFT);
|
||||
bool FileStream_GetSize(TFileStream * pStream, ULONGLONG & FileSize);
|
||||
bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize);
|
||||
bool FileStream_MoveFile(TFileStream * pStream, TFileStream * pTempStream);
|
||||
void FileStream_Close(TFileStream * pStream);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions prototypes for Storm.dll
|
||||
|
||||
// Typedefs for functions exported by Storm.dll
|
||||
typedef LCID (WINAPI * SFILESETLOCALE)(LCID);
|
||||
typedef bool (WINAPI * SFILEOPENARCHIVE)(const char *, DWORD, DWORD, HANDLE *);
|
||||
typedef bool (WINAPI * SFILECLOSEARCHIVE)(HANDLE);
|
||||
typedef bool (WINAPI * SFILEOPENFILEEX)(HANDLE, const char *, DWORD, HANDLE *);
|
||||
typedef bool (WINAPI * SFILECLOSEFILE)(HANDLE);
|
||||
typedef DWORD (WINAPI * SFILEGETFILESIZE)(HANDLE, LPDWORD);
|
||||
typedef DWORD (WINAPI * SFILESETFILEPOINTER)(HANDLE, LONG, LONG *, DWORD);
|
||||
typedef bool (WINAPI * SFILEREADFILE)(HANDLE, void *, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions for manipulation with StormLib global flags
|
||||
|
||||
#define SFILE_FLAG_ALLOW_WRITE_SHARE 0x00000001 // When a MPQ is open for write by StorLib,
|
||||
// it is allowed to open it for write with another application.
|
||||
|
||||
DWORD WINAPI SFileGetGlobalFlags();
|
||||
DWORD WINAPI SFileSetGlobalFlags(DWORD dwNewFlags);
|
||||
|
||||
LCID WINAPI SFileGetLocale();
|
||||
LCID WINAPI SFileSetLocale(LCID lcNewLocale);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions for archive manipulation
|
||||
|
||||
bool WINAPI SFileOpenArchive(const TCHAR * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMpq);
|
||||
bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwMaxFileCount, HANDLE * phMpq);
|
||||
|
||||
bool WINAPI SFileFlushArchive(HANDLE hMpq);
|
||||
bool WINAPI SFileCloseArchive(HANDLE hMpq);
|
||||
|
||||
// Adds another listfile into MPQ. The currently added listfile(s) remain,
|
||||
// so you can use this API to combining more listfiles.
|
||||
// Note that this function is internally called by SFileFindFirstFile
|
||||
int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile);
|
||||
|
||||
// Archive compacting
|
||||
bool WINAPI SFileSetCompactCallback(HANDLE hMpq, SFILE_COMPACT_CALLBACK CompactCB, void * pvData);
|
||||
bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile = NULL, bool bReserved = 0);
|
||||
|
||||
// Changing the maximum file count
|
||||
DWORD WINAPI SFileGetMaxFileCount(HANDLE hMpq);
|
||||
bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount);
|
||||
|
||||
// Changing (attributes) file
|
||||
DWORD WINAPI SFileGetAttributes(HANDLE hMpq);
|
||||
bool WINAPI SFileSetAttributes(HANDLE hMpq, DWORD dwFlags);
|
||||
bool WINAPI SFileUpdateFileAttributes(HANDLE hMpq, const char * szFileName);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions for manipulation with patch archives
|
||||
|
||||
bool WINAPI SFileOpenPatchArchive(HANDLE hMpq, const TCHAR * szPatchMpqName, const char * szPatchPathPrefix, DWORD dwFlags);
|
||||
bool WINAPI SFileIsPatchedArchive(HANDLE hMpq);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions for file manipulation
|
||||
|
||||
// Reading from MPQ file
|
||||
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile);
|
||||
DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh = NULL);
|
||||
DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHigh, DWORD dwMoveMethod);
|
||||
bool WINAPI SFileReadFile(HANDLE hFile, void * lpBuffer, DWORD dwToRead, LPDWORD pdwRead = NULL, LPOVERLAPPED lpOverlapped = NULL);
|
||||
bool WINAPI SFileCloseFile(HANDLE hFile);
|
||||
|
||||
// Retrieving info about the file
|
||||
bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName);
|
||||
bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName);
|
||||
bool WINAPI SFileGetFileInfo(HANDLE hMpqOrFile, DWORD dwInfoType, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded = NULL);
|
||||
|
||||
// High-level extract function
|
||||
bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions for file and archive verification
|
||||
|
||||
// Generates file CRC32
|
||||
bool WINAPI SFileGetFileChecksums(HANDLE hMpq, const char * szFileName, LPDWORD pdwCrc32, char * pMD5);
|
||||
|
||||
// Verifies file against its checksums stored in (attributes) attributes (depending on dwFlags).
|
||||
// For dwFlags, use one or more of MPQ_ATTRIBUTE_MD5
|
||||
DWORD WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags);
|
||||
|
||||
// Verifies raw data of the archive. Only works for MPQs version 4 or newer
|
||||
int WINAPI SFileVerifyRawData(HANDLE hMpq, DWORD dwWhatToVerify, const char * szFileName);
|
||||
|
||||
// Verifies the signature, if present
|
||||
DWORD WINAPI SFileVerifyArchive(HANDLE hMpq);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions for file searching
|
||||
|
||||
HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile);
|
||||
bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
|
||||
bool WINAPI SFileFindClose(HANDLE hFind);
|
||||
|
||||
HANDLE WINAPI SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData);
|
||||
bool WINAPI SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
|
||||
bool WINAPI SListFileFindClose(HANDLE hFind);
|
||||
|
||||
// Locale support
|
||||
int WINAPI SFileEnumLocales(HANDLE hMpq, const char * szFileName, LCID * plcLocales, LPDWORD pdwMaxLocales, DWORD dwSearchScope);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Support for adding files to the MPQ
|
||||
|
||||
bool WINAPI SFileCreateFile(HANDLE hMpq, const char * szArchivedName, ULONGLONG FileTime, DWORD dwFileSize, LCID lcLocale, DWORD dwFlags, HANDLE * phFile);
|
||||
bool WINAPI SFileWriteFile(HANDLE hFile, const void * pvData, DWORD dwSize, DWORD dwCompression);
|
||||
bool WINAPI SFileFinishFile(HANDLE hFile);
|
||||
|
||||
bool WINAPI SFileAddFileEx(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwCompression, DWORD dwCompressionNext = 0xFFFFFFFF);
|
||||
bool WINAPI SFileAddFile(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags);
|
||||
bool WINAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality);
|
||||
bool WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ);
|
||||
bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szOldFileName, const char * szNewFileName);
|
||||
bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale);
|
||||
bool WINAPI SFileSetDataCompression(DWORD DataCompression);
|
||||
|
||||
bool WINAPI SFileSetAddFileCallback(HANDLE hMpq, SFILE_ADDFILE_CALLBACK AddFileCB, void * pvData);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compression and decompression
|
||||
|
||||
int WINAPI SCompImplode (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer);
|
||||
int WINAPI SCompExplode (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer);
|
||||
int WINAPI SCompCompress (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer, unsigned uCompressionMask, int nCmpType, int nCmpLevel);
|
||||
int WINAPI SCompDecompress (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions from Storm.dll. They use slightly different names for keeping
|
||||
// possibility to use them together with StormLib (StormXXX instead of SFileXXX)
|
||||
|
||||
#ifdef __LINK_STORM_DLL__
|
||||
#define STORM_ALTERNATE_NAMES // Force storm_dll.h to use alternate fnc names
|
||||
#include "..\storm_dll\storm_dll.h"
|
||||
#endif // __LINK_STORM_DLL__
|
||||
|
||||
#endif // __STORMLIB_H__
|
||||
239
src/dep/src/StormLib/src/StormPort.h
Normal file
239
src/dep/src/StormLib/src/StormPort.h
Normal file
@ -0,0 +1,239 @@
|
||||
/*****************************************************************************/
|
||||
/* StormPort.h Copyright (c) Marko Friedemann 2001 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Portability module for the StormLib library. Contains a wrapper symbols */
|
||||
/* to make the compilation under Linux work */
|
||||
/* */
|
||||
/* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de> */
|
||||
/* Created at: Mon Jan 29 18:26:01 CEST 2001 */
|
||||
/* Computer: whiplash.flachland-chemnitz.de */
|
||||
/* System: Linux 2.4.0 on i686 */
|
||||
/* */
|
||||
/* Author: Sam Wilkins */
|
||||
/* System: Mac OS X and port to big endian processor */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 29.01.01 1.00 Mar Created */
|
||||
/* 24.03.03 1.01 Lad Some cosmetic changes */
|
||||
/* 12.11.03 1.02 Dan Macintosh compatibility */
|
||||
/* 24.07.04 1.03 Sam Mac OS X compatibility */
|
||||
/* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */
|
||||
/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __STORMPORT_H__
|
||||
#define __STORMPORT_H__
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define bool char
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
// Defines for Windows
|
||||
#if !defined(PLATFORM_DEFINED) && (defined(WIN32) || defined(WIN64))
|
||||
|
||||
// In MSVC 8.0, there are some functions declared as deprecated.
|
||||
#if _MSC_VER >= 1400
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_NON_CONFORMING_SWPRINTFS
|
||||
#endif
|
||||
|
||||
#include <tchar.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#define PLATFORM_LITTLE_ENDIAN
|
||||
|
||||
#ifdef WIN64
|
||||
#define PLATFORM_64BIT
|
||||
#else
|
||||
#define PLATFORM_32BIT
|
||||
#endif
|
||||
|
||||
#define PLATFORM_WINDOWS
|
||||
#define PLATFORM_DEFINED // The platform is known now
|
||||
|
||||
#endif
|
||||
|
||||
// Defines for Mac Carbon
|
||||
#if !defined(PLATFORM_DEFINED) && defined(__APPLE__) // Mac Carbon API
|
||||
|
||||
// Macintosh using Carbon
|
||||
#include <Carbon/Carbon.h> // Mac OS X
|
||||
|
||||
#define PKEXPORT
|
||||
#define __SYS_ZLIB
|
||||
#define __SYS_BZLIB
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define PLATFORM_LITTLE_ENDIAN // Apple is now making Macs with Intel CPUs
|
||||
#endif
|
||||
|
||||
#define PLATFORM_MAC
|
||||
#define PLATFORM_DEFINED // The platform is known now
|
||||
|
||||
#endif
|
||||
|
||||
// Assumption: we are not on Windows nor Macintosh, so this must be linux *grin*
|
||||
#if !defined(PLATFORM_DEFINED)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define PLATFORM_LITTLE_ENDIAN
|
||||
#define PLATFORM_LINUX
|
||||
#define PLATFORM_DEFINED
|
||||
|
||||
#endif
|
||||
|
||||
// Definition of Windows-specific structures for non-Windows platforms
|
||||
#ifndef PLATFORM_WINDOWS
|
||||
#if __LP64__
|
||||
#define PLATFORM_64BIT
|
||||
#else
|
||||
#define PLATFORM_32BIT
|
||||
#endif
|
||||
|
||||
// Typedefs for ANSI C
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short USHORT;
|
||||
typedef int LONG;
|
||||
typedef unsigned int DWORD;
|
||||
typedef unsigned long DWORD_PTR;
|
||||
typedef long LONG_PTR;
|
||||
typedef long INT_PTR;
|
||||
typedef long long LONGLONG;
|
||||
typedef unsigned long long ULONGLONG;
|
||||
typedef void * HANDLE;
|
||||
typedef void * LPOVERLAPPED; // Unsupported on Linux and Mac
|
||||
typedef char TCHAR;
|
||||
typedef unsigned int LCID;
|
||||
typedef LONG * PLONG;
|
||||
typedef DWORD * LPDWORD;
|
||||
typedef BYTE * LPBYTE;
|
||||
|
||||
#ifdef PLATFORM_32BIT
|
||||
#define _LZMA_UINT32_IS_ULONG
|
||||
#endif
|
||||
|
||||
// Some Windows-specific defines
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 1024
|
||||
#endif
|
||||
|
||||
#define WINAPI
|
||||
|
||||
#define FILE_BEGIN SEEK_SET
|
||||
#define FILE_CURRENT SEEK_CUR
|
||||
#define FILE_END SEEK_END
|
||||
|
||||
#define _T(x) x
|
||||
#define _tcslen strlen
|
||||
#define _tcscpy strcpy
|
||||
#define _tcscat strcat
|
||||
#define _tcsrchr strrchr
|
||||
#define _tprintf printf
|
||||
#define _stprintf sprintf
|
||||
#define _tremove remove
|
||||
|
||||
#define _stricmp strcasecmp
|
||||
#define _strnicmp strncasecmp
|
||||
|
||||
void SetLastError(int err);
|
||||
int GetLastError();
|
||||
|
||||
|
||||
#endif // !WIN32
|
||||
|
||||
// Platform-specific error codes
|
||||
#ifdef PLATFORM_MAC
|
||||
#define ERROR_SUCCESS noErr
|
||||
#define ERROR_FILE_NOT_FOUND fnfErr
|
||||
#define ERROR_ACCESS_DENIED permErr
|
||||
#define ERROR_INVALID_HANDLE rfNumErr
|
||||
#define ERROR_NOT_ENOUGH_MEMORY mFulErr
|
||||
#define ERROR_BAD_FORMAT 200 // Returned when the opened file is in format that is not recognized by StormLib
|
||||
#define ERROR_NO_MORE_FILES errFSNoMoreItems
|
||||
#define ERROR_HANDLE_EOF eofErr
|
||||
#define ERROR_NOT_SUPPORTED 201
|
||||
#define ERROR_INVALID_PARAMETER paramErr
|
||||
#define ERROR_DISK_FULL dskFulErr
|
||||
#define ERROR_ALREADY_EXISTS dupFNErr
|
||||
#define ERROR_CAN_NOT_COMPLETE 202 // A generic error, when any operation fails from an unknown reason
|
||||
#define ERROR_FILE_CORRUPT 203 // At any point when there is bad data format in the file
|
||||
#define ERROR_INSUFFICIENT_BUFFER errFSBadBuffer
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_LINUX
|
||||
#define ERROR_SUCCESS 0
|
||||
#define ERROR_FILE_NOT_FOUND ENOENT
|
||||
#define ERROR_ACCESS_DENIED EPERM
|
||||
#define ERROR_INVALID_HANDLE EBADF
|
||||
#define ERROR_NOT_ENOUGH_MEMORY ENOMEM
|
||||
#define ERROR_BAD_FORMAT 105 // No such error code under Linux
|
||||
#define ERROR_NO_MORE_FILES 106
|
||||
#define ERROR_HANDLE_EOF 107 // No such error code under Linux
|
||||
#define ERROR_NOT_SUPPORTED ENOTSUP
|
||||
#define ERROR_INVALID_PARAMETER EINVAL
|
||||
#define ERROR_DISK_FULL ENOSPC
|
||||
#define ERROR_ALREADY_EXISTS EEXIST
|
||||
#define ERROR_CAN_NOT_COMPLETE 108 // No such error code under Linux
|
||||
#define ERROR_FILE_CORRUPT 109 // No such error code under Linux
|
||||
#define ERROR_INSUFFICIENT_BUFFER ENOBUFS
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_LITTLE_ENDIAN
|
||||
#define BSWAP_INT16_UNSIGNED(a) (a)
|
||||
#define BSWAP_INT16_SIGNED(a) (a)
|
||||
#define BSWAP_INT32_UNSIGNED(a) (a)
|
||||
#define BSWAP_INT32_SIGNED(a) (a)
|
||||
#define BSWAP_INT64_SIGNED(a) (a)
|
||||
#define BSWAP_INT64_UNSIGNED(a) (a)
|
||||
#define BSWAP_ARRAY16_UNSIGNED(a,b) {}
|
||||
#define BSWAP_ARRAY32_UNSIGNED(a,b) {}
|
||||
#define BSWAP_ARRAY64_UNSIGNED(a,b) {}
|
||||
#define BSWAP_PART_HEADER(a) {}
|
||||
#define BSWAP_TMPQUSERDATA(a) {}
|
||||
#define BSWAP_TMPQHEADER(a) {}
|
||||
#else
|
||||
int16_t SwapInt16(uint16_t);
|
||||
uint16_t SwapUInt16(uint16_t);
|
||||
int32_t SwapInt32(uint32_t);
|
||||
uint32_t SwapUInt32(uint32_t);
|
||||
int64_t SwapInt64(uint64_t);
|
||||
uint64_t SwapUInt64(uint64_t);
|
||||
void ConvertUInt16Buffer(void * ptr, size_t length);
|
||||
void ConvertUInt32Buffer(void * ptr, size_t length);
|
||||
void ConvertUInt64Buffer(void * ptr, size_t length);
|
||||
void ConvertPartHeader(void * partHeader);
|
||||
void ConvertTMPQUserData(void *userData);
|
||||
void ConvertTMPQHeader(void *header);
|
||||
#define BSWAP_INT16_SIGNED(a) SwapInt16((a))
|
||||
#define BSWAP_INT16_UNSIGNED(a) SwapUInt16((a))
|
||||
#define BSWAP_INT32_SIGNED(a) SwapInt32((a))
|
||||
#define BSWAP_INT32_UNSIGNED(a) SwapUInt32((a))
|
||||
#define BSWAP_INT64_SIGNED(a) SwapInt64((a))
|
||||
#define BSWAP_INT64_UNSIGNED(a) SwapUInt64((a))
|
||||
#define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUInt16Buffer((a),(b))
|
||||
#define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUInt32Buffer((a),(b))
|
||||
#define BSWAP_ARRAY64_UNSIGNED(a,b) ConvertUInt64Buffer((a),(b))
|
||||
#define BSWAP_PART_HEADER(a) ConvertPartHeader(a)
|
||||
#define BSWAP_TMPQUSERDATA(a) ConvertTMPQUserData((a))
|
||||
#define BSWAP_TMPQHEADER(a) ConvertTMPQHeader((a))
|
||||
#endif
|
||||
|
||||
#endif // __STORMPORT_H__
|
||||
@ -1,356 +1,357 @@
|
||||
/*****************************************************************************/
|
||||
/* wave.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* This module contains decompression methods used by Storm.dll to decompress*/
|
||||
/* WAVe files. Thanks to Tom Amigo for releasing his sources. */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
|
||||
/* 20.05.03 2.00 Lad Added compression */
|
||||
/* 19.11.03 2.01 Dan Big endian handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "wave.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Structures
|
||||
|
||||
union TByteAndWordPtr
|
||||
{
|
||||
short * pw;
|
||||
unsigned char * pb;
|
||||
};
|
||||
|
||||
union TWordAndByteArray
|
||||
{
|
||||
short w;
|
||||
unsigned char b[2];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tables necessary dor decompression
|
||||
|
||||
static long Table1503F120[] =
|
||||
{
|
||||
0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006,
|
||||
0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
|
||||
0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
|
||||
0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008
|
||||
};
|
||||
|
||||
static long Table1503F1A0[] =
|
||||
{
|
||||
0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
|
||||
0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F,
|
||||
0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042,
|
||||
0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F,
|
||||
0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133,
|
||||
0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292,
|
||||
0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583,
|
||||
0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0,
|
||||
0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954,
|
||||
0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B,
|
||||
0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462,
|
||||
0x00007FFF
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CompressWave
|
||||
|
||||
// 1500EF70
|
||||
int CompressWave(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nChannels, int nCmpLevel)
|
||||
// ECX EDX
|
||||
{
|
||||
TWordAndByteArray Wcmp;
|
||||
TByteAndWordPtr out; // Pointer to the output buffer
|
||||
long SInt32Array1[2];
|
||||
long SInt32Array2[2];
|
||||
long SInt32Array3[2];
|
||||
long nBytesRemains = dwOutLength; // Number of bytes remaining
|
||||
long nWordsRemains; // Number of words remaining
|
||||
// unsigned char * pbSaveOutBuffer; // Copy of output buffer (actually not used)
|
||||
unsigned long dwBitBuff;
|
||||
unsigned long dwStopBit;
|
||||
unsigned long dwBit;
|
||||
unsigned long ebx;
|
||||
unsigned long esi;
|
||||
long nTableValue;
|
||||
long nOneWord;
|
||||
long var_1C;
|
||||
long var_2C;
|
||||
int nLength;
|
||||
int nIndex;
|
||||
int nValue;
|
||||
|
||||
// If less than 2 bytes remain, don't decompress anything
|
||||
// pbSaveOutBuffer = pbOutBuffer;
|
||||
out.pb = pbOutBuffer;
|
||||
if(nBytesRemains < 2)
|
||||
return 2;
|
||||
|
||||
Wcmp.b[1] = (unsigned char)(nCmpLevel - 1);
|
||||
Wcmp.b[0] = (unsigned char)0;
|
||||
|
||||
*out.pw++ = BSWAP_INT16_SIGNED(Wcmp.w);
|
||||
if((out.pb - pbOutBuffer + (nChannels * 2)) > nBytesRemains)
|
||||
return (int)(out.pb - pbOutBuffer + (nChannels * 2));
|
||||
|
||||
SInt32Array1[0] = SInt32Array1[1] = 0x2C;
|
||||
|
||||
for(int i = 0; i < nChannels; i++)
|
||||
{
|
||||
nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++);
|
||||
*out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord);
|
||||
SInt32Array2[i] = nOneWord;
|
||||
}
|
||||
|
||||
// Weird. But it's there
|
||||
nLength = dwInLength;
|
||||
if(nLength < 0) // mov eax, dwInLength; cdq; sub eax, edx;
|
||||
nLength++;
|
||||
|
||||
nLength = (nLength / 2) - (int)(out.pb - pbOutBuffer);
|
||||
nLength = (nLength < 0) ? 0 : nLength;
|
||||
|
||||
nIndex = nChannels - 1; // edi
|
||||
nWordsRemains = dwInLength / 2; // eax
|
||||
|
||||
// ebx - nChannels
|
||||
// ecx - pwOutPos
|
||||
for(int chnl = nChannels; chnl < nWordsRemains; chnl++)
|
||||
{
|
||||
// 1500F030
|
||||
if((out.pb - pbOutBuffer + 2) > nBytesRemains)
|
||||
return (int)(out.pb - pbOutBuffer + 2);
|
||||
|
||||
// Switch index
|
||||
if(nChannels == 2)
|
||||
nIndex = (nIndex == 0) ? 1 : 0;
|
||||
|
||||
// Load one word from the input stream
|
||||
nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++); // ecx - nOneWord
|
||||
SInt32Array3[nIndex] = nOneWord;
|
||||
|
||||
// esi - SInt32Array2[nIndex]
|
||||
// eax - nValue
|
||||
nValue = nOneWord - SInt32Array2[nIndex];
|
||||
nValue = (nValue < 0) ? ((nValue ^ 0xFFFFFFFF) + 1) : nValue;
|
||||
|
||||
ebx = (nOneWord >= SInt32Array2[nIndex]) ? 0 : 0x40;
|
||||
|
||||
// esi - SInt32Array2[nIndex]
|
||||
// edx - Table1503F1A0[SInt32Array2[nIndex]]
|
||||
// edi - (Table1503F1A0[SInt32Array1[nIndex]] >> nCmpLevel)
|
||||
nTableValue = Table1503F1A0[SInt32Array1[nIndex]];
|
||||
dwStopBit = (unsigned long)nCmpLevel;
|
||||
|
||||
// edi - nIndex;
|
||||
if(nValue < (nTableValue >> nCmpLevel))
|
||||
{
|
||||
if(SInt32Array1[nIndex] != 0)
|
||||
SInt32Array1[nIndex]--;
|
||||
*out.pb++ = 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(nValue > nTableValue * 2)
|
||||
{
|
||||
if(SInt32Array1[nIndex] >= 0x58 || nLength == 0)
|
||||
break;
|
||||
|
||||
SInt32Array1[nIndex] += 8;
|
||||
if(SInt32Array1[nIndex] > 0x58)
|
||||
SInt32Array1[nIndex] = 0x58;
|
||||
|
||||
nTableValue = Table1503F1A0[SInt32Array1[nIndex]];
|
||||
*out.pb++ = 0x81;
|
||||
nLength--;
|
||||
}
|
||||
|
||||
var_2C = nTableValue >> Wcmp.b[1];
|
||||
dwBitBuff = 0;
|
||||
|
||||
esi = (1 << (dwStopBit - 2));
|
||||
dwStopBit = (esi <= 0x20) ? esi : 0x20;
|
||||
|
||||
for(var_1C = 0, dwBit = 1; ; dwBit <<= 1)
|
||||
{
|
||||
// esi = var_1C + nTableValue;
|
||||
if((var_1C + nTableValue) <= nValue)
|
||||
{
|
||||
var_1C += nTableValue;
|
||||
dwBitBuff |= dwBit;
|
||||
}
|
||||
if(dwBit == dwStopBit)
|
||||
break;
|
||||
|
||||
nTableValue >>= 1;
|
||||
}
|
||||
|
||||
nValue = SInt32Array2[nIndex];
|
||||
if(ebx != 0)
|
||||
{
|
||||
nValue -= (var_1C + var_2C);
|
||||
if(nValue < -32768)
|
||||
nValue = -32768;
|
||||
}
|
||||
else
|
||||
{
|
||||
nValue += (var_1C + var_2C);
|
||||
if(nValue > 32767)
|
||||
nValue = 32767;
|
||||
}
|
||||
|
||||
SInt32Array2[nIndex] = nValue;
|
||||
*out.pb++ = (unsigned char)(dwBitBuff | ebx);
|
||||
nTableValue = Table1503F120[dwBitBuff & 0x1F];
|
||||
SInt32Array1[nIndex] = SInt32Array1[nIndex] + nTableValue;
|
||||
if(SInt32Array1[nIndex] < 0)
|
||||
SInt32Array1[nIndex] = 0;
|
||||
else if(SInt32Array1[nIndex] > 0x58)
|
||||
SInt32Array1[nIndex] = 0x58;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)(out.pb - pbOutBuffer);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DecompressWave
|
||||
|
||||
// 1500F230
|
||||
int DecompressWave(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels)
|
||||
{
|
||||
TByteAndWordPtr out; // Output buffer
|
||||
TByteAndWordPtr in;
|
||||
unsigned char * pbInBufferEnd = (pbInBuffer + dwInLength);
|
||||
long SInt32Array1[2];
|
||||
long SInt32Array2[2];
|
||||
long nOneWord;
|
||||
int dwOutLengthCopy = dwOutLength;
|
||||
int nIndex;
|
||||
|
||||
SInt32Array1[0] = SInt32Array1[1] = 0x2C;
|
||||
out.pb = pbOutBuffer;
|
||||
in.pb = pbInBuffer;
|
||||
in.pw++;
|
||||
|
||||
// Fill the Uint32Array2 array by channel values.
|
||||
for(int i = 0; i < nChannels; i++)
|
||||
{
|
||||
nOneWord = BSWAP_INT16_SIGNED(*in.pw++);
|
||||
SInt32Array2[i] = nOneWord;
|
||||
if(dwOutLengthCopy < 2)
|
||||
return (int)(out.pb - pbOutBuffer);
|
||||
|
||||
*out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord);
|
||||
dwOutLengthCopy -= sizeof(short);
|
||||
}
|
||||
|
||||
// Get the initial index
|
||||
nIndex = nChannels - 1;
|
||||
|
||||
// Perform the decompression
|
||||
while(in.pb < pbInBufferEnd)
|
||||
{
|
||||
unsigned char nOneByte = *in.pb++;
|
||||
|
||||
// Switch index
|
||||
if(nChannels == 2)
|
||||
nIndex = (nIndex == 0) ? 1 : 0;
|
||||
|
||||
// 1500F2A2: Get one byte from input buffer
|
||||
if(nOneByte & 0x80)
|
||||
{
|
||||
switch(nOneByte & 0x7F)
|
||||
{
|
||||
case 0: // 1500F315
|
||||
if(SInt32Array1[nIndex] != 0)
|
||||
SInt32Array1[nIndex]--;
|
||||
|
||||
if(dwOutLengthCopy < 2)
|
||||
return (int)(out.pb - pbOutBuffer);
|
||||
|
||||
*out.pw++ = BSWAP_INT16_SIGNED((unsigned short)SInt32Array2[nIndex]);
|
||||
dwOutLength -= sizeof(unsigned short);
|
||||
break;
|
||||
|
||||
case 1: // 1500F2E8
|
||||
SInt32Array1[nIndex] += 8;
|
||||
if(SInt32Array1[nIndex] > 0x58)
|
||||
SInt32Array1[nIndex] = 0x58;
|
||||
|
||||
if(nChannels == 2)
|
||||
nIndex = (nIndex == 0) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 2: // 1500F41E
|
||||
break;
|
||||
|
||||
default: // 1500F2C4
|
||||
SInt32Array1[nIndex] -= 8;
|
||||
if(SInt32Array1[nIndex] < 0)
|
||||
SInt32Array1[nIndex] = 0;
|
||||
|
||||
if(nChannels == 2)
|
||||
nIndex = (nIndex == 0) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1500F349
|
||||
long temp1 = Table1503F1A0[SInt32Array1[nIndex]]; // EDI
|
||||
long temp2 = temp1 >> pbInBuffer[1]; // ESI
|
||||
long temp3 = SInt32Array2[nIndex]; // ECX
|
||||
|
||||
if(nOneByte & 0x01) // EBX = nOneByte
|
||||
temp2 += (temp1 >> 0);
|
||||
|
||||
if(nOneByte & 0x02)
|
||||
temp2 += (temp1 >> 1);
|
||||
|
||||
if(nOneByte & 0x04)
|
||||
temp2 += (temp1 >> 2);
|
||||
|
||||
if(nOneByte & 0x08)
|
||||
temp2 += (temp1 >> 3);
|
||||
|
||||
if(nOneByte & 0x10)
|
||||
temp2 += (temp1 >> 4);
|
||||
|
||||
if(nOneByte & 0x20)
|
||||
temp2 += (temp1 >> 5);
|
||||
|
||||
if(nOneByte & 0x40)
|
||||
{
|
||||
temp3 = temp3 - temp2;
|
||||
if(temp3 <= -32768)
|
||||
temp3 = -32768;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp3 = temp3 + temp2;
|
||||
if(temp3 >= 32767)
|
||||
temp3 = 32767;
|
||||
}
|
||||
|
||||
SInt32Array2[nIndex] = temp3;
|
||||
if(dwOutLength < 2)
|
||||
break;
|
||||
|
||||
// Store the output 16-bit value
|
||||
*out.pw++ = BSWAP_INT16_SIGNED((short)SInt32Array2[nIndex]);
|
||||
dwOutLength -= 2;
|
||||
|
||||
SInt32Array1[nIndex] += Table1503F120[nOneByte & 0x1F];
|
||||
|
||||
if(SInt32Array1[nIndex] < 0)
|
||||
SInt32Array1[nIndex] = 0;
|
||||
else if(SInt32Array1[nIndex] > 0x58)
|
||||
SInt32Array1[nIndex] = 0x58;
|
||||
}
|
||||
}
|
||||
return (int)(out.pb - pbOutBuffer);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/* adpcm.cpp Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* This module contains implementation of adpcm decompression method used by */
|
||||
/* Storm.dll to decompress WAVE files. Thanks to Tom Amigo for releasing */
|
||||
/* his sources. */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
|
||||
/* 20.05.03 2.00 Lad Added compression */
|
||||
/* 19.11.03 2.01 Dan Big endian handling */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "adpcm.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Structures
|
||||
|
||||
union TByteAndWordPtr
|
||||
{
|
||||
short * pw;
|
||||
unsigned char * pb;
|
||||
};
|
||||
|
||||
union TWordAndByteArray
|
||||
{
|
||||
short w;
|
||||
unsigned char b[2];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tables necessary dor decompression
|
||||
|
||||
static long Table1503F120[] =
|
||||
{
|
||||
0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006,
|
||||
0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
|
||||
0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
|
||||
0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008
|
||||
};
|
||||
|
||||
static long step_table[] =
|
||||
{
|
||||
0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
|
||||
0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F,
|
||||
0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042,
|
||||
0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F,
|
||||
0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133,
|
||||
0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292,
|
||||
0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583,
|
||||
0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0,
|
||||
0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954,
|
||||
0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B,
|
||||
0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462,
|
||||
0x00007FFF
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CompressWave
|
||||
|
||||
// 1500EF70
|
||||
int CompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nChannels, int nCmpLevel)
|
||||
// ECX EDX
|
||||
{
|
||||
TWordAndByteArray Wcmp;
|
||||
TByteAndWordPtr out; // Pointer to the output buffer
|
||||
long SInt32Array1[2];
|
||||
long SInt32Array2[2];
|
||||
long SInt32Array3[2];
|
||||
long nBytesRemains = dwOutLength; // Number of bytes remaining
|
||||
long nWordsRemains; // Number of words remaining
|
||||
// unsigned char * pbSaveOutBuffer; // Copy of output buffer (actually not used)
|
||||
unsigned long dwBitBuff;
|
||||
unsigned long dwStopBit;
|
||||
unsigned long dwBit;
|
||||
unsigned long ebx;
|
||||
unsigned long esi;
|
||||
long nTableValue;
|
||||
long nOneWord;
|
||||
long var_1C;
|
||||
long var_2C;
|
||||
int nLength;
|
||||
int nIndex;
|
||||
int nValue;
|
||||
|
||||
// If less than 2 bytes remain, don't decompress anything
|
||||
// pbSaveOutBuffer = pbOutBuffer;
|
||||
out.pb = pbOutBuffer;
|
||||
if(nBytesRemains < 2)
|
||||
return 2;
|
||||
|
||||
Wcmp.b[1] = (unsigned char)(nCmpLevel - 1);
|
||||
Wcmp.b[0] = (unsigned char)0;
|
||||
|
||||
*out.pw++ = BSWAP_INT16_SIGNED(Wcmp.w);
|
||||
if((out.pb - pbOutBuffer + (nChannels * 2)) > nBytesRemains)
|
||||
return (int)(out.pb - pbOutBuffer + (nChannels * 2));
|
||||
|
||||
SInt32Array1[0] = SInt32Array1[1] = 0x2C;
|
||||
|
||||
for(int i = 0; i < nChannels; i++)
|
||||
{
|
||||
nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++);
|
||||
*out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord);
|
||||
SInt32Array2[i] = nOneWord;
|
||||
}
|
||||
|
||||
// Weird. But it's there
|
||||
nLength = dwInLength;
|
||||
if(nLength < 0) // mov eax, dwInLength; cdq; sub eax, edx;
|
||||
nLength++;
|
||||
|
||||
nLength = (nLength / 2) - (int)(out.pb - pbOutBuffer);
|
||||
nLength = (nLength < 0) ? 0 : nLength;
|
||||
|
||||
nIndex = nChannels - 1; // edi
|
||||
nWordsRemains = dwInLength / 2; // eax
|
||||
|
||||
// ebx - nChannels
|
||||
// ecx - pwOutPos
|
||||
for(int chnl = nChannels; chnl < nWordsRemains; chnl++)
|
||||
{
|
||||
// 1500F030
|
||||
if((out.pb - pbOutBuffer + 2) > nBytesRemains)
|
||||
return (int)(out.pb - pbOutBuffer + 2);
|
||||
|
||||
// Switch index
|
||||
if(nChannels == 2)
|
||||
nIndex = (nIndex == 0) ? 1 : 0;
|
||||
|
||||
// Load one word from the input stream
|
||||
nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++); // ecx - nOneWord
|
||||
SInt32Array3[nIndex] = nOneWord;
|
||||
|
||||
// esi - SInt32Array2[nIndex]
|
||||
// eax - nValue
|
||||
nValue = nOneWord - SInt32Array2[nIndex];
|
||||
nValue = (nValue < 0) ? ((nValue ^ 0xFFFFFFFF) + 1) : nValue;
|
||||
|
||||
ebx = (nOneWord >= SInt32Array2[nIndex]) ? 0 : 0x40;
|
||||
|
||||
// esi - SInt32Array2[nIndex]
|
||||
// edx - step_table[SInt32Array2[nIndex]]
|
||||
// edi - (step_table[SInt32Array1[nIndex]] >> nCmpLevel)
|
||||
nTableValue = step_table[SInt32Array1[nIndex]];
|
||||
dwStopBit = (unsigned long)nCmpLevel;
|
||||
|
||||
// edi - nIndex;
|
||||
if(nValue < (nTableValue >> nCmpLevel))
|
||||
{
|
||||
if(SInt32Array1[nIndex] != 0)
|
||||
SInt32Array1[nIndex]--;
|
||||
*out.pb++ = 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(nValue > nTableValue * 2)
|
||||
{
|
||||
if(SInt32Array1[nIndex] >= 0x58 || nLength == 0)
|
||||
break;
|
||||
|
||||
SInt32Array1[nIndex] += 8;
|
||||
if(SInt32Array1[nIndex] > 0x58)
|
||||
SInt32Array1[nIndex] = 0x58;
|
||||
|
||||
nTableValue = step_table[SInt32Array1[nIndex]];
|
||||
*out.pb++ = 0x81;
|
||||
nLength--;
|
||||
}
|
||||
|
||||
var_2C = nTableValue >> Wcmp.b[1];
|
||||
dwBitBuff = 0;
|
||||
|
||||
esi = (1 << (dwStopBit - 2));
|
||||
dwStopBit = (esi <= 0x20) ? esi : 0x20;
|
||||
|
||||
for(var_1C = 0, dwBit = 1; ; dwBit <<= 1)
|
||||
{
|
||||
// esi = var_1C + nTableValue;
|
||||
if((var_1C + nTableValue) <= nValue)
|
||||
{
|
||||
var_1C += nTableValue;
|
||||
dwBitBuff |= dwBit;
|
||||
}
|
||||
if(dwBit == dwStopBit)
|
||||
break;
|
||||
|
||||
nTableValue >>= 1;
|
||||
}
|
||||
|
||||
nValue = SInt32Array2[nIndex];
|
||||
if(ebx != 0)
|
||||
{
|
||||
nValue -= (var_1C + var_2C);
|
||||
if(nValue < -32768)
|
||||
nValue = -32768;
|
||||
}
|
||||
else
|
||||
{
|
||||
nValue += (var_1C + var_2C);
|
||||
if(nValue > 32767)
|
||||
nValue = 32767;
|
||||
}
|
||||
|
||||
SInt32Array2[nIndex] = nValue;
|
||||
*out.pb++ = (unsigned char)(dwBitBuff | ebx);
|
||||
nTableValue = Table1503F120[dwBitBuff & 0x1F];
|
||||
SInt32Array1[nIndex] = SInt32Array1[nIndex] + nTableValue;
|
||||
if(SInt32Array1[nIndex] < 0)
|
||||
SInt32Array1[nIndex] = 0;
|
||||
else if(SInt32Array1[nIndex] > 0x58)
|
||||
SInt32Array1[nIndex] = 0x58;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)(out.pb - pbOutBuffer);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DecompressADPCM
|
||||
|
||||
// 1500F230
|
||||
int DecompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels)
|
||||
{
|
||||
TByteAndWordPtr out; // Output buffer
|
||||
TByteAndWordPtr in;
|
||||
unsigned char * pbInBufferEnd = (pbInBuffer + dwInLength);
|
||||
long SInt32Array1[2];
|
||||
long SInt32Array2[2];
|
||||
long nOneWord;
|
||||
int dwOutLengthCopy = dwOutLength;
|
||||
int nIndex;
|
||||
|
||||
SInt32Array1[0] = SInt32Array1[1] = 0x2C;
|
||||
out.pb = pbOutBuffer;
|
||||
in.pb = pbInBuffer;
|
||||
in.pw++;
|
||||
|
||||
// Fill the Uint32Array2 array by channel values.
|
||||
for(int i = 0; i < nChannels; i++)
|
||||
{
|
||||
nOneWord = BSWAP_INT16_SIGNED(*in.pw++);
|
||||
SInt32Array2[i] = nOneWord;
|
||||
if(dwOutLengthCopy < 2)
|
||||
return (int)(out.pb - pbOutBuffer);
|
||||
|
||||
*out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord);
|
||||
dwOutLengthCopy -= sizeof(short);
|
||||
}
|
||||
|
||||
// Get the initial index
|
||||
nIndex = nChannels - 1;
|
||||
|
||||
// Perform the decompression
|
||||
while(in.pb < pbInBufferEnd)
|
||||
{
|
||||
unsigned char nOneByte = *in.pb++;
|
||||
|
||||
// Switch index
|
||||
if(nChannels == 2)
|
||||
nIndex = (nIndex == 0) ? 1 : 0;
|
||||
|
||||
// 1500F2A2: Get one byte from input buffer
|
||||
if(nOneByte & 0x80)
|
||||
{
|
||||
switch(nOneByte & 0x7F)
|
||||
{
|
||||
case 0: // 1500F315
|
||||
if(SInt32Array1[nIndex] != 0)
|
||||
SInt32Array1[nIndex]--;
|
||||
|
||||
if(dwOutLengthCopy < 2)
|
||||
return (int)(out.pb - pbOutBuffer);
|
||||
|
||||
*out.pw++ = BSWAP_INT16_SIGNED((unsigned short)SInt32Array2[nIndex]);
|
||||
dwOutLength -= sizeof(unsigned short);
|
||||
break;
|
||||
|
||||
case 1: // 1500F2E8
|
||||
SInt32Array1[nIndex] += 8;
|
||||
if(SInt32Array1[nIndex] > 0x58)
|
||||
SInt32Array1[nIndex] = 0x58;
|
||||
|
||||
if(nChannels == 2)
|
||||
nIndex = (nIndex == 0) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 2: // 1500F41E
|
||||
break;
|
||||
|
||||
default: // 1500F2C4
|
||||
SInt32Array1[nIndex] -= 8;
|
||||
if(SInt32Array1[nIndex] < 0)
|
||||
SInt32Array1[nIndex] = 0;
|
||||
|
||||
if(nChannels == 2)
|
||||
nIndex = (nIndex == 0) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1500F349
|
||||
long temp1 = step_table[SInt32Array1[nIndex]]; // EDI
|
||||
long temp2 = temp1 >> pbInBuffer[1]; // ESI
|
||||
long temp3 = SInt32Array2[nIndex]; // ECX
|
||||
|
||||
if(nOneByte & 0x01) // EBX = nOneByte
|
||||
temp2 += (temp1 >> 0);
|
||||
|
||||
if(nOneByte & 0x02)
|
||||
temp2 += (temp1 >> 1);
|
||||
|
||||
if(nOneByte & 0x04)
|
||||
temp2 += (temp1 >> 2);
|
||||
|
||||
if(nOneByte & 0x08)
|
||||
temp2 += (temp1 >> 3);
|
||||
|
||||
if(nOneByte & 0x10)
|
||||
temp2 += (temp1 >> 4);
|
||||
|
||||
if(nOneByte & 0x20)
|
||||
temp2 += (temp1 >> 5);
|
||||
|
||||
if(nOneByte & 0x40)
|
||||
{
|
||||
temp3 = temp3 - temp2;
|
||||
if(temp3 <= -32768)
|
||||
temp3 = -32768;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp3 = temp3 + temp2;
|
||||
if(temp3 >= 32767)
|
||||
temp3 = 32767;
|
||||
}
|
||||
|
||||
SInt32Array2[nIndex] = temp3;
|
||||
if(dwOutLength < 2)
|
||||
break;
|
||||
|
||||
// Store the output 16-bit value
|
||||
*out.pw++ = BSWAP_INT16_SIGNED((short)SInt32Array2[nIndex]);
|
||||
dwOutLength -= 2;
|
||||
|
||||
SInt32Array1[nIndex] += Table1503F120[nOneByte & 0x1F];
|
||||
|
||||
if(SInt32Array1[nIndex] < 0)
|
||||
SInt32Array1[nIndex] = 0;
|
||||
else if(SInt32Array1[nIndex] > 0x58)
|
||||
SInt32Array1[nIndex] = 0x58;
|
||||
}
|
||||
}
|
||||
return (int)(out.pb - pbOutBuffer);
|
||||
}
|
||||
@ -1,22 +1,22 @@
|
||||
/*****************************************************************************/
|
||||
/* Wave.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Header file for WAVe unplode functions */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 31.03.03 1.00 Lad The first version of Wave.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __WAVE_H__
|
||||
#define __WAVE_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions
|
||||
|
||||
#include "../StormPort.h"
|
||||
|
||||
int CompressWave (unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nCmpType, int nChannels);
|
||||
int DecompressWave(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels);
|
||||
|
||||
#endif // __WAVE_H__
|
||||
/*****************************************************************************/
|
||||
/* adpcm.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Header file for adpcm decompress functions */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* 31.03.03 1.00 Lad The first version of adpcm.h */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __ADPCM_H__
|
||||
#define __ADPCM_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions
|
||||
|
||||
#include "../StormPort.h"
|
||||
|
||||
int CompressADPCM (unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nCmpType, int nChannels);
|
||||
int DecompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels);
|
||||
|
||||
#endif // __ADPCM_H__
|
||||
@ -11,7 +11,7 @@
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
@ -45,7 +45,7 @@ extern "C" {
|
||||
#define BZ_OUTBUFF_FULL (-8)
|
||||
#define BZ_CONFIG_ERROR (-9)
|
||||
|
||||
typedef
|
||||
typedef
|
||||
struct {
|
||||
char *next_in;
|
||||
unsigned int avail_in;
|
||||
@ -62,7 +62,7 @@ typedef
|
||||
void *(*bzalloc)(void *,int,int);
|
||||
void (*bzfree)(void *,void *);
|
||||
void *opaque;
|
||||
}
|
||||
}
|
||||
bz_stream;
|
||||
|
||||
|
||||
@ -97,34 +97,34 @@ typedef
|
||||
|
||||
/*-- Core (low-level) library functions --*/
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
|
||||
bz_stream* strm,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
|
||||
bz_stream* strm,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompress) (
|
||||
bz_stream* strm,
|
||||
int action
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompress) (
|
||||
bz_stream* strm,
|
||||
int action
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
|
||||
bz_stream* strm
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
|
||||
bz_stream* strm
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
|
||||
bz_stream *strm,
|
||||
int verbosity,
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
|
||||
bz_stream *strm,
|
||||
int verbosity,
|
||||
int small
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
|
||||
bz_stream* strm
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
|
||||
bz_stream* strm
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
|
||||
bz_stream *strm
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
|
||||
bz_stream *strm
|
||||
);
|
||||
|
||||
|
||||
@ -136,64 +136,64 @@ BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
|
||||
|
||||
typedef void BZFILE;
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
|
||||
int* bzerror,
|
||||
FILE* f,
|
||||
int verbosity,
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
|
||||
int* bzerror,
|
||||
FILE* f,
|
||||
int verbosity,
|
||||
int small,
|
||||
void* unused,
|
||||
int nUnused
|
||||
void* unused,
|
||||
int nUnused
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
|
||||
int* bzerror,
|
||||
BZFILE* b
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
|
||||
int* bzerror,
|
||||
BZFILE* b
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void** unused,
|
||||
int* nUnused
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void** unused,
|
||||
int* nUnused
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzRead) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
BZ_EXTERN int BZ_API(BZ2_bzRead) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
|
||||
int* bzerror,
|
||||
FILE* f,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
|
||||
int* bzerror,
|
||||
FILE* f,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWrite) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWrite) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in,
|
||||
unsigned int* nbytes_out
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in,
|
||||
unsigned int* nbytes_out
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in_lo32,
|
||||
unsigned int* nbytes_in_hi32,
|
||||
unsigned int* nbytes_out_lo32,
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in_lo32,
|
||||
unsigned int* nbytes_in_hi32,
|
||||
unsigned int* nbytes_out_lo32,
|
||||
unsigned int* nbytes_out_hi32
|
||||
);
|
||||
#endif
|
||||
@ -201,23 +201,23 @@ BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
|
||||
|
||||
/*-- Utility functions --*/
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
|
||||
char* dest,
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
|
||||
char* dest,
|
||||
unsigned int* destLen,
|
||||
char* source,
|
||||
char* source,
|
||||
unsigned int sourceLen,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
|
||||
char* dest,
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
|
||||
char* dest,
|
||||
unsigned int* destLen,
|
||||
char* source,
|
||||
char* source,
|
||||
unsigned int sourceLen,
|
||||
int small,
|
||||
int verbosity
|
||||
int small,
|
||||
int verbosity
|
||||
);
|
||||
|
||||
|
||||
@ -244,17 +244,17 @@ BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
|
||||
int fd,
|
||||
const char *mode
|
||||
);
|
||||
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzread) (
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzwrite) (
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzflush) (
|
||||
@ -266,7 +266,7 @@ BZ_EXTERN void BZ_API(BZ2_bzclose) (
|
||||
);
|
||||
|
||||
BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
|
||||
BZFILE *b,
|
||||
BZFILE *b,
|
||||
int *errnum
|
||||
);
|
||||
#endif
|
||||
@ -11,7 +11,7 @@
|
||||
bzip2/libbzip2 version 1.0.5 of 10 December 2007
|
||||
Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
@ -51,7 +51,7 @@ typedef unsigned short UInt16;
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __inline__ /* */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
|
||||
@ -109,7 +109,7 @@ extern void bz_internal_error ( int errcode );
|
||||
#define BZ_HDR_Z 0x5a /* 'Z' */
|
||||
#define BZ_HDR_h 0x68 /* 'h' */
|
||||
#define BZ_HDR_0 0x30 /* '0' */
|
||||
|
||||
|
||||
/*-- Constants for the back end. --*/
|
||||
|
||||
#define BZ_MAX_ALPHA_SIZE 258
|
||||
@ -269,19 +269,19 @@ typedef
|
||||
|
||||
/*-- externs for compression. --*/
|
||||
|
||||
extern void
|
||||
extern void
|
||||
BZ2_blockSort ( EState* );
|
||||
|
||||
extern void
|
||||
extern void
|
||||
BZ2_compressBlock ( EState*, Bool );
|
||||
|
||||
extern void
|
||||
extern void
|
||||
BZ2_bsInitWrite ( EState* );
|
||||
|
||||
extern void
|
||||
extern void
|
||||
BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
|
||||
|
||||
extern void
|
||||
extern void
|
||||
BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
|
||||
|
||||
|
||||
@ -425,7 +425,7 @@ typedef
|
||||
Int32 save_N;
|
||||
Int32 save_curr;
|
||||
Int32 save_zt;
|
||||
Int32 save_zn;
|
||||
Int32 save_zn;
|
||||
Int32 save_zvec;
|
||||
Int32 save_zj;
|
||||
Int32 save_gSel;
|
||||
@ -481,13 +481,13 @@ typedef
|
||||
|
||||
/*-- externs for decompression. --*/
|
||||
|
||||
extern Int32
|
||||
extern Int32
|
||||
BZ2_indexIntoF ( Int32, Int32* );
|
||||
|
||||
extern Int32
|
||||
extern Int32
|
||||
BZ2_decompress ( DState* );
|
||||
|
||||
extern void
|
||||
extern void
|
||||
BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
|
||||
Int32, Int32, Int32 );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,143 +1,144 @@
|
||||
/*****************************************************************************/
|
||||
/* huffman.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.xx 1.00 Lad The first version of huffman.h */
|
||||
/* 03.05.03 2.00 Lad Added compression */
|
||||
/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __HUFFMAN_H__
|
||||
#define __HUFFMAN_H__
|
||||
|
||||
#include "../StormPort.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define INSERT_ITEM 1
|
||||
#define SWITCH_ITEMS 2 // Switch the item1 and item2
|
||||
|
||||
#define PTR_NOT(ptr) (THTreeItem *)(~(DWORD_PTR)(ptr))
|
||||
#define PTR_PTR(ptr) ((THTreeItem *)(ptr))
|
||||
#define PTR_INT(ptr) (INT_PTR)(ptr)
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures and classes
|
||||
|
||||
// Input stream for Huffmann decompression
|
||||
class TInputStream
|
||||
{
|
||||
public:
|
||||
|
||||
unsigned long GetBit();
|
||||
unsigned long Get7Bits();
|
||||
unsigned long Get8Bits();
|
||||
void SkipBits(unsigned int BitCount);
|
||||
|
||||
unsigned char * pbInBuffer; // 00 - Input data
|
||||
unsigned long BitBuffer; // 04 - Input bit buffer
|
||||
unsigned int BitCount; // 08 - Number of bits remaining in 'dwBitBuff'
|
||||
};
|
||||
|
||||
// Output stream for Huffmann compression
|
||||
class TOutputStream
|
||||
{
|
||||
public:
|
||||
|
||||
void PutBits(unsigned long dwBuff, unsigned int nPutBits);
|
||||
|
||||
unsigned char * pbOutBuffer; // 00 : Output buffer
|
||||
unsigned long dwOutSize; // 04 : Size of output buffer
|
||||
unsigned char * pbOutPos; // 08 : Current output position
|
||||
unsigned long dwBitBuff; // 0C : Bit buffer
|
||||
unsigned long nBits; // 10 : Number of bits in the bit buffer
|
||||
};
|
||||
|
||||
// Huffmann tree item (?)
|
||||
struct THTreeItem
|
||||
{
|
||||
public:
|
||||
|
||||
THTreeItem * Call1501DB70(THTreeItem * pLast);
|
||||
THTreeItem * GetPrevItem(LONG_PTR value);
|
||||
void ClearItemLinks();
|
||||
void RemoveItem();
|
||||
|
||||
THTreeItem * next; // 00 - Pointer to next THTreeItem
|
||||
THTreeItem * prev; // 04 - Pointer to prev THTreeItem (< 0 if none)
|
||||
unsigned long dcmpByte; // 08 - Index of this item in item pointer array, decompressed byte value
|
||||
unsigned long byteValue; // 0C - Some byte value
|
||||
THTreeItem * parent; // 10 - Pointer to parent THTreeItem (NULL if none)
|
||||
THTreeItem * child; // 14 - Pointer to child THTreeItem
|
||||
int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive
|
||||
};
|
||||
|
||||
// Structure used for quick decompress. The 'bitCount' contains number of bits
|
||||
// and byte value contains result decompressed byte value.
|
||||
// After each walk through Huffman tree are filled all entries which are
|
||||
// multiplies of number of bits loaded from input stream. These entries
|
||||
// contain number of bits and result value. At the next 7 bits is tested this
|
||||
// structure first. If corresponding entry found, decompression routine will
|
||||
// not walk through Huffman tree and directly stores output byte to output stream.
|
||||
struct TQDecompress
|
||||
{
|
||||
unsigned long offs00; // 00 - 1 if resolved
|
||||
unsigned long nBits; // 04 - Bit count
|
||||
union
|
||||
{
|
||||
unsigned long dcmpByte; // 08 - Byte value for decompress (if bitCount <= 7)
|
||||
THTreeItem * pItem; // 08 - THTreeItem (if number of bits is greater than 7
|
||||
};
|
||||
};
|
||||
|
||||
// Structure for Huffman tree (Size 0x3674 bytes). Because I'm not expert
|
||||
// for the decompression, I do not know actually if the class is really a Hufmann
|
||||
// tree. If someone knows the decompression details, please let me know
|
||||
class THuffmannTree
|
||||
{
|
||||
public:
|
||||
|
||||
THuffmannTree();
|
||||
void InitTree(bool bCompression);
|
||||
void BuildTree(unsigned int nCmpType);
|
||||
// void ModifyTree(unsigned long dwIndex);
|
||||
// void UninitTree();
|
||||
|
||||
// void Call15007010(Bit32 dwInLength, THTreeItem * item);
|
||||
THTreeItem * Call1500E740(unsigned int nValue);
|
||||
void Call1500E820(THTreeItem * pItem);
|
||||
unsigned int DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType);
|
||||
unsigned int DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is);
|
||||
|
||||
unsigned long bIsCmp0; // 0000 - 1 if compression type 0
|
||||
unsigned long offs0004; // 0004 - Some flag
|
||||
THTreeItem items0008[0x203]; // 0008 - HTree items
|
||||
|
||||
//- Sometimes used as HTree item -----------
|
||||
THTreeItem * pItem3050; // 3050 - Always NULL (?)
|
||||
THTreeItem * pItem3054; // 3054 - Pointer to Huffman tree item
|
||||
THTreeItem * pItem3058; // 3058 - Pointer to Huffman tree item (< 0 if invalid)
|
||||
|
||||
//- Sometimes used as HTree item -----------
|
||||
THTreeItem * pItem305C; // 305C - Usually NULL
|
||||
THTreeItem * pFirst; // 3060 - Pointer to top (first) Huffman tree item
|
||||
THTreeItem * pLast; // 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid)
|
||||
unsigned long nItems; // 3068 - Number of used HTree items
|
||||
|
||||
//-------------------------------------------
|
||||
THTreeItem * items306C[0x102]; // 306C - THTreeItem pointer array
|
||||
TQDecompress qd3474[0x80]; // 3474 - Array for quick decompression
|
||||
int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive
|
||||
|
||||
static unsigned char Table1502A630[];// Some table
|
||||
};
|
||||
|
||||
#endif // __HUFFMAN_H__
|
||||
/*****************************************************************************/
|
||||
/* huffman.h Copyright (c) Ladislav Zezula 2003 */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Description : */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Date Ver Who Comment */
|
||||
/* -------- ---- --- ------- */
|
||||
/* xx.xx.xx 1.00 Lad The first version of huffman.h */
|
||||
/* 03.05.03 2.00 Lad Added compression */
|
||||
/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef __HUFFMAN_H__
|
||||
#define __HUFFMAN_H__
|
||||
|
||||
#include "../StormPort.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#define INSERT_ITEM 1
|
||||
#define SWITCH_ITEMS 2 // Switch the item1 and item2
|
||||
|
||||
#define PTR_NOT(ptr) (THTreeItem *)(~(DWORD_PTR)(ptr))
|
||||
#define PTR_PTR(ptr) ((THTreeItem *)(ptr))
|
||||
#define PTR_INT(ptr) (INT_PTR)(ptr)
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures and classes
|
||||
|
||||
// Input stream for Huffmann decompression
|
||||
class TInputStream
|
||||
{
|
||||
public:
|
||||
|
||||
unsigned long GetBit();
|
||||
unsigned long Get7Bits();
|
||||
unsigned long Get8Bits();
|
||||
void SkipBits(unsigned int BitCount);
|
||||
|
||||
unsigned char * pbInBuffer; // Input data
|
||||
unsigned char * pbInBufferEnd; // End of the input buffer
|
||||
unsigned long BitBuffer; // Input bit buffer
|
||||
unsigned int BitCount; // Number of bits remaining in 'dwBitBuff'
|
||||
};
|
||||
|
||||
// Output stream for Huffmann compression
|
||||
class TOutputStream
|
||||
{
|
||||
public:
|
||||
|
||||
void PutBits(unsigned long dwBuff, unsigned int nPutBits);
|
||||
|
||||
unsigned char * pbOutBuffer; // 00 : Output buffer
|
||||
unsigned long cbOutSize; // 04 : Size of output buffer
|
||||
unsigned char * pbOutPos; // 08 : Current output position
|
||||
unsigned long dwBitBuff; // 0C : Bit buffer
|
||||
unsigned long nBits; // 10 : Number of bits in the bit buffer
|
||||
};
|
||||
|
||||
// Huffmann tree item (?)
|
||||
struct THTreeItem
|
||||
{
|
||||
public:
|
||||
|
||||
THTreeItem * Call1501DB70(THTreeItem * pLast);
|
||||
THTreeItem * GetPrevItem(LONG_PTR value);
|
||||
void ClearItemLinks();
|
||||
void RemoveItem();
|
||||
|
||||
THTreeItem * next; // 00 - Pointer to next THTreeItem
|
||||
THTreeItem * prev; // 04 - Pointer to prev THTreeItem (< 0 if none)
|
||||
unsigned long dcmpByte; // 08 - Index of this item in item pointer array, decompressed byte value
|
||||
unsigned long byteValue; // 0C - Some byte value
|
||||
THTreeItem * parent; // 10 - Pointer to parent THTreeItem (NULL if none)
|
||||
THTreeItem * child; // 14 - Pointer to child THTreeItem
|
||||
int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive
|
||||
};
|
||||
|
||||
// Structure used for quick decompress. The 'bitCount' contains number of bits
|
||||
// and byte value contains result decompressed byte value.
|
||||
// After each walk through Huffman tree are filled all entries which are
|
||||
// multiplies of number of bits loaded from input stream. These entries
|
||||
// contain number of bits and result value. At the next 7 bits is tested this
|
||||
// structure first. If corresponding entry found, decompression routine will
|
||||
// not walk through Huffman tree and directly stores output byte to output stream.
|
||||
struct TQDecompress
|
||||
{
|
||||
unsigned long offs00; // 00 - 1 if resolved
|
||||
unsigned long nBits; // 04 - Bit count
|
||||
union
|
||||
{
|
||||
unsigned long dcmpByte; // 08 - Byte value for decompress (if bitCount <= 7)
|
||||
THTreeItem * pItem; // 08 - THTreeItem (if number of bits is greater than 7
|
||||
};
|
||||
};
|
||||
|
||||
// Structure for Huffman tree (Size 0x3674 bytes). Because I'm not expert
|
||||
// for the decompression, I do not know actually if the class is really a Hufmann
|
||||
// tree. If someone knows the decompression details, please let me know
|
||||
class THuffmannTree
|
||||
{
|
||||
public:
|
||||
|
||||
THuffmannTree();
|
||||
void InitTree(bool bCompression);
|
||||
void BuildTree(unsigned int nCmpType);
|
||||
// void ModifyTree(unsigned long dwIndex);
|
||||
// void UninitTree();
|
||||
|
||||
// void Call15007010(Bit32 dwInLength, THTreeItem * item);
|
||||
THTreeItem * Call1500E740(unsigned int nValue);
|
||||
void Call1500E820(THTreeItem * pItem);
|
||||
unsigned int DoCompression(TOutputStream * os, unsigned char * pbInBuffer, int nInLength, int nCmpType);
|
||||
unsigned int DoDecompression(unsigned char * pbOutBuffer, unsigned int dwOutLength, TInputStream * is);
|
||||
|
||||
unsigned long bIsCmp0; // 0000 - 1 if compression type 0
|
||||
unsigned long offs0004; // 0004 - Some flag
|
||||
THTreeItem items0008[0x203]; // 0008 - HTree items
|
||||
|
||||
//- Sometimes used as HTree item -----------
|
||||
THTreeItem * pItem3050; // 3050 - Always NULL (?)
|
||||
THTreeItem * pItem3054; // 3054 - Pointer to Huffman tree item
|
||||
THTreeItem * pItem3058; // 3058 - Pointer to Huffman tree item (< 0 if invalid)
|
||||
|
||||
//- Sometimes used as HTree item -----------
|
||||
THTreeItem * pItem305C; // 305C - Usually NULL
|
||||
THTreeItem * pFirst; // 3060 - Pointer to top (first) Huffman tree item
|
||||
THTreeItem * pLast; // 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid)
|
||||
unsigned long nItems; // 3068 - Number of used HTree items
|
||||
|
||||
//-------------------------------------------
|
||||
THTreeItem * items306C[0x102]; // 306C - THTreeItem pointer array
|
||||
TQDecompress qd3474[0x80]; // 3474 - Array for quick decompression
|
||||
int addressMultiplier; // -1 if object on negative address (>0x80000000), +1 if positive
|
||||
|
||||
static unsigned char Table1502A630[];// Some table
|
||||
};
|
||||
|
||||
#endif // __HUFFMAN_H__
|
||||
24
src/dep/src/StormLib/src/jenkins/lookup.h
Normal file
24
src/dep/src/StormLib/src/jenkins/lookup.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __LOOKUP3_H__
|
||||
#define __LOOKUP3_H__
|
||||
|
||||
#ifdef WIN32
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
#include <stdint.h> /* defines uint32_t etc */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
uint32_t hashlittle(const void *key, size_t length, uint32_t initval);
|
||||
void hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __LOOKUP3_H__
|
||||
1003
src/dep/src/StormLib/src/jenkins/lookup3.c
Normal file
1003
src/dep/src/StormLib/src/jenkins/lookup3.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,69 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file hash_memory.c
|
||||
Hash memory helper, Tom St Denis
|
||||
*/
|
||||
|
||||
/**
|
||||
Hash a block of memory and store the digest.
|
||||
@param hash The index of the hash you wish to use
|
||||
@param in The data you wish to hash
|
||||
@param inlen The length of the data to hash (octets)
|
||||
@param out [out] Where to store the digest
|
||||
@param outlen [in/out] Max size and resulting size of the digest
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
hash_state *md;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (*outlen < hash_descriptor[hash].hashsize) {
|
||||
*outlen = hash_descriptor[hash].hashsize;
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
md = XMALLOC(sizeof(hash_state));
|
||||
if (md == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
err = hash_descriptor[hash].done(md, out);
|
||||
*outlen = hash_descriptor[hash].hashsize;
|
||||
LBL_ERR:
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(md, sizeof(hash_state));
|
||||
#endif
|
||||
XFREE(md);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_memory.c,v $ */
|
||||
/* $Revision: 1.6 $ */
|
||||
/* $Date: 2006/12/28 01:27:23 $ */
|
||||
368
src/dep/src/StormLib/src/libtomcrypt/src/hashes/md5.c
Normal file
368
src/dep/src/StormLib/src/libtomcrypt/src/hashes/md5.c
Normal file
@ -0,0 +1,368 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
|
||||
/**
|
||||
@file md5.c
|
||||
LTC_MD5 hash function by Tom St Denis
|
||||
*/
|
||||
|
||||
#ifdef LTC_MD5
|
||||
|
||||
const struct ltc_hash_descriptor md5_desc =
|
||||
{
|
||||
"md5",
|
||||
3,
|
||||
16,
|
||||
64,
|
||||
|
||||
/* OID */
|
||||
{ 1, 2, 840, 113549, 2, 5, },
|
||||
6,
|
||||
|
||||
&md5_init,
|
||||
&md5_process,
|
||||
&md5_done,
|
||||
&md5_test,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define G(x,y,z) (y ^ (z & (y ^ x)))
|
||||
#define H(x,y,z) (x^y^z)
|
||||
#define I(x,y,z) (y^(x|(~z)))
|
||||
|
||||
#ifdef LTC_SMALL_CODE
|
||||
|
||||
#define FF(a,b,c,d,M,s,t) \
|
||||
a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b;
|
||||
|
||||
#define GG(a,b,c,d,M,s,t) \
|
||||
a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b;
|
||||
|
||||
#define HH(a,b,c,d,M,s,t) \
|
||||
a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b;
|
||||
|
||||
#define II(a,b,c,d,M,s,t) \
|
||||
a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
|
||||
|
||||
static const unsigned char Worder[64] = {
|
||||
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
|
||||
1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
|
||||
5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
|
||||
0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
|
||||
};
|
||||
|
||||
static const unsigned char Rorder[64] = {
|
||||
7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
|
||||
5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
|
||||
4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
|
||||
6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
|
||||
};
|
||||
|
||||
static const ulong32 Korder[64] = {
|
||||
0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
|
||||
0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
|
||||
0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
|
||||
0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
|
||||
0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
|
||||
0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
|
||||
0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
|
||||
0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define FF(a,b,c,d,M,s,t) \
|
||||
a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b;
|
||||
|
||||
#define GG(a,b,c,d,M,s,t) \
|
||||
a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b;
|
||||
|
||||
#define HH(a,b,c,d,M,s,t) \
|
||||
a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b;
|
||||
|
||||
#define II(a,b,c,d,M,s,t) \
|
||||
a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int _md5_compress(hash_state *md, unsigned char *buf)
|
||||
#else
|
||||
static int md5_compress(hash_state *md, unsigned char *buf)
|
||||
#endif
|
||||
{
|
||||
ulong32 i, W[16], a, b, c, d;
|
||||
#ifdef LTC_SMALL_CODE
|
||||
ulong32 t;
|
||||
#endif
|
||||
|
||||
/* copy the state into 512-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++) {
|
||||
LOAD32L(W[i], buf + (4*i));
|
||||
}
|
||||
|
||||
/* copy state */
|
||||
a = md->md5.state[0];
|
||||
b = md->md5.state[1];
|
||||
c = md->md5.state[2];
|
||||
d = md->md5.state[3];
|
||||
|
||||
#ifdef LTC_SMALL_CODE
|
||||
for (i = 0; i < 16; ++i) {
|
||||
FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 32; ++i) {
|
||||
GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 48; ++i) {
|
||||
HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 64; ++i) {
|
||||
II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
|
||||
t = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
#else
|
||||
FF(a,b,c,d,W[0],7,0xd76aa478UL)
|
||||
FF(d,a,b,c,W[1],12,0xe8c7b756UL)
|
||||
FF(c,d,a,b,W[2],17,0x242070dbUL)
|
||||
FF(b,c,d,a,W[3],22,0xc1bdceeeUL)
|
||||
FF(a,b,c,d,W[4],7,0xf57c0fafUL)
|
||||
FF(d,a,b,c,W[5],12,0x4787c62aUL)
|
||||
FF(c,d,a,b,W[6],17,0xa8304613UL)
|
||||
FF(b,c,d,a,W[7],22,0xfd469501UL)
|
||||
FF(a,b,c,d,W[8],7,0x698098d8UL)
|
||||
FF(d,a,b,c,W[9],12,0x8b44f7afUL)
|
||||
FF(c,d,a,b,W[10],17,0xffff5bb1UL)
|
||||
FF(b,c,d,a,W[11],22,0x895cd7beUL)
|
||||
FF(a,b,c,d,W[12],7,0x6b901122UL)
|
||||
FF(d,a,b,c,W[13],12,0xfd987193UL)
|
||||
FF(c,d,a,b,W[14],17,0xa679438eUL)
|
||||
FF(b,c,d,a,W[15],22,0x49b40821UL)
|
||||
GG(a,b,c,d,W[1],5,0xf61e2562UL)
|
||||
GG(d,a,b,c,W[6],9,0xc040b340UL)
|
||||
GG(c,d,a,b,W[11],14,0x265e5a51UL)
|
||||
GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)
|
||||
GG(a,b,c,d,W[5],5,0xd62f105dUL)
|
||||
GG(d,a,b,c,W[10],9,0x02441453UL)
|
||||
GG(c,d,a,b,W[15],14,0xd8a1e681UL)
|
||||
GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)
|
||||
GG(a,b,c,d,W[9],5,0x21e1cde6UL)
|
||||
GG(d,a,b,c,W[14],9,0xc33707d6UL)
|
||||
GG(c,d,a,b,W[3],14,0xf4d50d87UL)
|
||||
GG(b,c,d,a,W[8],20,0x455a14edUL)
|
||||
GG(a,b,c,d,W[13],5,0xa9e3e905UL)
|
||||
GG(d,a,b,c,W[2],9,0xfcefa3f8UL)
|
||||
GG(c,d,a,b,W[7],14,0x676f02d9UL)
|
||||
GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
|
||||
HH(a,b,c,d,W[5],4,0xfffa3942UL)
|
||||
HH(d,a,b,c,W[8],11,0x8771f681UL)
|
||||
HH(c,d,a,b,W[11],16,0x6d9d6122UL)
|
||||
HH(b,c,d,a,W[14],23,0xfde5380cUL)
|
||||
HH(a,b,c,d,W[1],4,0xa4beea44UL)
|
||||
HH(d,a,b,c,W[4],11,0x4bdecfa9UL)
|
||||
HH(c,d,a,b,W[7],16,0xf6bb4b60UL)
|
||||
HH(b,c,d,a,W[10],23,0xbebfbc70UL)
|
||||
HH(a,b,c,d,W[13],4,0x289b7ec6UL)
|
||||
HH(d,a,b,c,W[0],11,0xeaa127faUL)
|
||||
HH(c,d,a,b,W[3],16,0xd4ef3085UL)
|
||||
HH(b,c,d,a,W[6],23,0x04881d05UL)
|
||||
HH(a,b,c,d,W[9],4,0xd9d4d039UL)
|
||||
HH(d,a,b,c,W[12],11,0xe6db99e5UL)
|
||||
HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
|
||||
HH(b,c,d,a,W[2],23,0xc4ac5665UL)
|
||||
II(a,b,c,d,W[0],6,0xf4292244UL)
|
||||
II(d,a,b,c,W[7],10,0x432aff97UL)
|
||||
II(c,d,a,b,W[14],15,0xab9423a7UL)
|
||||
II(b,c,d,a,W[5],21,0xfc93a039UL)
|
||||
II(a,b,c,d,W[12],6,0x655b59c3UL)
|
||||
II(d,a,b,c,W[3],10,0x8f0ccc92UL)
|
||||
II(c,d,a,b,W[10],15,0xffeff47dUL)
|
||||
II(b,c,d,a,W[1],21,0x85845dd1UL)
|
||||
II(a,b,c,d,W[8],6,0x6fa87e4fUL)
|
||||
II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
|
||||
II(c,d,a,b,W[6],15,0xa3014314UL)
|
||||
II(b,c,d,a,W[13],21,0x4e0811a1UL)
|
||||
II(a,b,c,d,W[4],6,0xf7537e82UL)
|
||||
II(d,a,b,c,W[11],10,0xbd3af235UL)
|
||||
II(c,d,a,b,W[2],15,0x2ad7d2bbUL)
|
||||
II(b,c,d,a,W[9],21,0xeb86d391UL)
|
||||
#endif
|
||||
|
||||
md->md5.state[0] = md->md5.state[0] + a;
|
||||
md->md5.state[1] = md->md5.state[1] + b;
|
||||
md->md5.state[2] = md->md5.state[2] + c;
|
||||
md->md5.state[3] = md->md5.state[3] + d;
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int md5_compress(hash_state *md, unsigned char *buf)
|
||||
{
|
||||
int err;
|
||||
err = _md5_compress(md, buf);
|
||||
burn_stack(sizeof(ulong32) * 21);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initialize the hash state
|
||||
@param md The hash state you wish to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int md5_init(hash_state * md)
|
||||
{
|
||||
LTC_ARGCHK(md != NULL);
|
||||
md->md5.state[0] = 0x67452301UL;
|
||||
md->md5.state[1] = 0xefcdab89UL;
|
||||
md->md5.state[2] = 0x98badcfeUL;
|
||||
md->md5.state[3] = 0x10325476UL;
|
||||
md->md5.curlen = 0;
|
||||
md->md5.length = 0;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Process a block of memory though the hash
|
||||
@param md The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
HASH_PROCESS(md5_process, md5_compress, md5, 64)
|
||||
|
||||
/**
|
||||
Terminate the hash to get the digest
|
||||
@param md The hash state
|
||||
@param out [out] The destination of the hash (16 bytes)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int md5_done(hash_state * md, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
LTC_ARGCHK(md != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
|
||||
if (md->md5.curlen >= sizeof(md->md5.buf)) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
/* increase the length of the message */
|
||||
md->md5.length += md->md5.curlen * 8;
|
||||
|
||||
/* append the '1' bit */
|
||||
md->md5.buf[md->md5.curlen++] = (unsigned char)0x80;
|
||||
|
||||
/* if the length is currently above 56 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->md5.curlen > 56) {
|
||||
while (md->md5.curlen < 64) {
|
||||
md->md5.buf[md->md5.curlen++] = (unsigned char)0;
|
||||
}
|
||||
md5_compress(md, md->md5.buf);
|
||||
md->md5.curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 56 bytes of zeroes */
|
||||
while (md->md5.curlen < 56) {
|
||||
md->md5.buf[md->md5.curlen++] = (unsigned char)0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
STORE64L(md->md5.length, md->md5.buf+56);
|
||||
md5_compress(md, md->md5.buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 4; i++) {
|
||||
STORE32L(md->md5.state[i], out+(4*i));
|
||||
}
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(md, sizeof(hash_state));
|
||||
#endif
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Self-test the hash
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
|
||||
*/
|
||||
int md5_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const struct {
|
||||
char *msg;
|
||||
unsigned char hash[16];
|
||||
} tests[] = {
|
||||
{ "",
|
||||
{ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
|
||||
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
|
||||
{ "a",
|
||||
{0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
|
||||
0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
|
||||
{ "abc",
|
||||
{ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
|
||||
0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
|
||||
{ "message digest",
|
||||
{ 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
|
||||
0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
|
||||
{ "abcdefghijklmnopqrstuvwxyz",
|
||||
{ 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
|
||||
0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
|
||||
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
{ 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
|
||||
0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
|
||||
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||
{ 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
|
||||
0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } },
|
||||
{ NULL, { 0 } }
|
||||
};
|
||||
|
||||
int i;
|
||||
unsigned char tmp[16];
|
||||
hash_state md;
|
||||
|
||||
for (i = 0; tests[i].msg != NULL; i++) {
|
||||
md5_init(&md);
|
||||
md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
|
||||
md5_done(&md, tmp);
|
||||
if (XMEMCMP(tmp, tests[i].hash, 16) != 0) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
}
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/md5.c,v $ */
|
||||
/* $Revision: 1.10 $ */
|
||||
/* $Date: 2007/05/12 14:25:28 $ */
|
||||
288
src/dep/src/StormLib/src/libtomcrypt/src/hashes/sha1.c
Normal file
288
src/dep/src/StormLib/src/libtomcrypt/src/hashes/sha1.c
Normal file
@ -0,0 +1,288 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file sha1.c
|
||||
LTC_SHA1 code by Tom St Denis
|
||||
*/
|
||||
|
||||
|
||||
#ifdef LTC_SHA1
|
||||
|
||||
const struct ltc_hash_descriptor sha1_desc =
|
||||
{
|
||||
"sha1",
|
||||
2,
|
||||
20,
|
||||
64,
|
||||
|
||||
/* OID */
|
||||
{ 1, 3, 14, 3, 2, 26, },
|
||||
6,
|
||||
|
||||
&sha1_init,
|
||||
&sha1_process,
|
||||
&sha1_done,
|
||||
&sha1_test,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define F0(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define F1(x,y,z) (x ^ y ^ z)
|
||||
#define F2(x,y,z) ((x & y) | (z & (x | y)))
|
||||
#define F3(x,y,z) (x ^ y ^ z)
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int _sha1_compress(hash_state *md, unsigned char *buf)
|
||||
#else
|
||||
static int sha1_compress(hash_state *md, unsigned char *buf)
|
||||
#endif
|
||||
{
|
||||
ulong32 a,b,c,d,e,W[80],i;
|
||||
#ifdef LTC_SMALL_CODE
|
||||
ulong32 t;
|
||||
#endif
|
||||
|
||||
/* copy the state into 512-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++) {
|
||||
LOAD32H(W[i], buf + (4*i));
|
||||
}
|
||||
|
||||
/* copy state */
|
||||
a = md->sha1.state[0];
|
||||
b = md->sha1.state[1];
|
||||
c = md->sha1.state[2];
|
||||
d = md->sha1.state[3];
|
||||
e = md->sha1.state[4];
|
||||
|
||||
/* expand it */
|
||||
for (i = 16; i < 80; i++) {
|
||||
W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
|
||||
}
|
||||
|
||||
/* compress */
|
||||
/* round one */
|
||||
#define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
|
||||
#define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
|
||||
#define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
|
||||
#define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
|
||||
|
||||
#ifdef LTC_SMALL_CODE
|
||||
|
||||
for (i = 0; i < 20; ) {
|
||||
FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 40; ) {
|
||||
FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 60; ) {
|
||||
FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
for (; i < 80; ) {
|
||||
FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
for (i = 0; i < 20; ) {
|
||||
FF0(a,b,c,d,e,i++);
|
||||
FF0(e,a,b,c,d,i++);
|
||||
FF0(d,e,a,b,c,i++);
|
||||
FF0(c,d,e,a,b,i++);
|
||||
FF0(b,c,d,e,a,i++);
|
||||
}
|
||||
|
||||
/* round two */
|
||||
for (; i < 40; ) {
|
||||
FF1(a,b,c,d,e,i++);
|
||||
FF1(e,a,b,c,d,i++);
|
||||
FF1(d,e,a,b,c,i++);
|
||||
FF1(c,d,e,a,b,i++);
|
||||
FF1(b,c,d,e,a,i++);
|
||||
}
|
||||
|
||||
/* round three */
|
||||
for (; i < 60; ) {
|
||||
FF2(a,b,c,d,e,i++);
|
||||
FF2(e,a,b,c,d,i++);
|
||||
FF2(d,e,a,b,c,i++);
|
||||
FF2(c,d,e,a,b,i++);
|
||||
FF2(b,c,d,e,a,i++);
|
||||
}
|
||||
|
||||
/* round four */
|
||||
for (; i < 80; ) {
|
||||
FF3(a,b,c,d,e,i++);
|
||||
FF3(e,a,b,c,d,i++);
|
||||
FF3(d,e,a,b,c,i++);
|
||||
FF3(c,d,e,a,b,i++);
|
||||
FF3(b,c,d,e,a,i++);
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef FF0
|
||||
#undef FF1
|
||||
#undef FF2
|
||||
#undef FF3
|
||||
|
||||
/* store */
|
||||
md->sha1.state[0] = md->sha1.state[0] + a;
|
||||
md->sha1.state[1] = md->sha1.state[1] + b;
|
||||
md->sha1.state[2] = md->sha1.state[2] + c;
|
||||
md->sha1.state[3] = md->sha1.state[3] + d;
|
||||
md->sha1.state[4] = md->sha1.state[4] + e;
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int sha1_compress(hash_state *md, unsigned char *buf)
|
||||
{
|
||||
int err;
|
||||
err = _sha1_compress(md, buf);
|
||||
burn_stack(sizeof(ulong32) * 87);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initialize the hash state
|
||||
@param md The hash state you wish to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int sha1_init(hash_state * md)
|
||||
{
|
||||
LTC_ARGCHK(md != NULL);
|
||||
md->sha1.state[0] = 0x67452301UL;
|
||||
md->sha1.state[1] = 0xefcdab89UL;
|
||||
md->sha1.state[2] = 0x98badcfeUL;
|
||||
md->sha1.state[3] = 0x10325476UL;
|
||||
md->sha1.state[4] = 0xc3d2e1f0UL;
|
||||
md->sha1.curlen = 0;
|
||||
md->sha1.length = 0;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Process a block of memory though the hash
|
||||
@param md The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
|
||||
|
||||
/**
|
||||
Terminate the hash to get the digest
|
||||
@param md The hash state
|
||||
@param out [out] The destination of the hash (20 bytes)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int sha1_done(hash_state * md, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
LTC_ARGCHK(md != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
|
||||
if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* increase the length of the message */
|
||||
md->sha1.length += md->sha1.curlen * 8;
|
||||
|
||||
/* append the '1' bit */
|
||||
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
|
||||
|
||||
/* if the length is currently above 56 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->sha1.curlen > 56) {
|
||||
while (md->sha1.curlen < 64) {
|
||||
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
|
||||
}
|
||||
sha1_compress(md, md->sha1.buf);
|
||||
md->sha1.curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 56 bytes of zeroes */
|
||||
while (md->sha1.curlen < 56) {
|
||||
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
STORE64H(md->sha1.length, md->sha1.buf+56);
|
||||
sha1_compress(md, md->sha1.buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 5; i++) {
|
||||
STORE32H(md->sha1.state[i], out+(4*i));
|
||||
}
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(md, sizeof(hash_state));
|
||||
#endif
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Self-test the hash
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
|
||||
*/
|
||||
int sha1_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const struct {
|
||||
char *msg;
|
||||
unsigned char hash[20];
|
||||
} tests[] = {
|
||||
{ "abc",
|
||||
{ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
|
||||
0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
|
||||
0x9c, 0xd0, 0xd8, 0x9d }
|
||||
},
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
|
||||
0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
|
||||
0xE5, 0x46, 0x70, 0xF1 }
|
||||
}
|
||||
};
|
||||
|
||||
int i;
|
||||
unsigned char tmp[20];
|
||||
hash_state md;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
|
||||
sha1_init(&md);
|
||||
sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
|
||||
sha1_done(&md, tmp);
|
||||
if (XMEMCMP(tmp, tests[i].hash, 20) != 0) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
}
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */
|
||||
/* $Revision: 1.10 $ */
|
||||
/* $Date: 2007/05/12 14:25:28 $ */
|
||||
87
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt.h
Normal file
87
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt.h
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef TOMCRYPT_H_
|
||||
#define TOMCRYPT_H_
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* use configuration data */
|
||||
#include "tomcrypt_custom.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* version */
|
||||
#define CRYPT 0x0117
|
||||
#define SCRYPT "1.17"
|
||||
|
||||
/* max size of either a cipher/hash block or symmetric key [largest of the two] */
|
||||
#define MAXBLOCKSIZE 128
|
||||
|
||||
/* descriptor table size */
|
||||
#define TAB_SIZE 32
|
||||
|
||||
/* error codes [will be expanded in future releases] */
|
||||
enum {
|
||||
CRYPT_OK=0, /* Result OK */
|
||||
CRYPT_ERROR, /* Generic Error */
|
||||
CRYPT_NOP, /* Not a failure but no operation was performed */
|
||||
|
||||
CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
|
||||
CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
|
||||
CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
|
||||
|
||||
CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
|
||||
CRYPT_INVALID_PACKET, /* Invalid input packet given */
|
||||
|
||||
CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
|
||||
CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
|
||||
|
||||
CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
|
||||
CRYPT_INVALID_HASH, /* Invalid hash specified */
|
||||
CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
|
||||
|
||||
CRYPT_MEM, /* Out of memory */
|
||||
|
||||
CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
|
||||
CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
|
||||
|
||||
CRYPT_INVALID_ARG, /* Generic invalid argument */
|
||||
CRYPT_FILE_NOTFOUND, /* File Not Found */
|
||||
|
||||
CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
|
||||
CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
|
||||
CRYPT_PK_DUP, /* Duplicate key already in key ring */
|
||||
CRYPT_PK_NOT_FOUND, /* Key not found in keyring */
|
||||
CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
|
||||
|
||||
CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */
|
||||
CRYPT_PK_INVALID_PADDING /* Invalid padding on input */
|
||||
};
|
||||
|
||||
#include "tomcrypt_cfg.h"
|
||||
#include "tomcrypt_macros.h"
|
||||
#include "tomcrypt_cipher.h"
|
||||
#include "tomcrypt_hash.h"
|
||||
#include "tomcrypt_mac.h"
|
||||
#include "tomcrypt_prng.h"
|
||||
#include "tomcrypt_pk.h"
|
||||
#include "tomcrypt_math.h"
|
||||
#include "tomcrypt_misc.h"
|
||||
#include "tomcrypt_argchk.h"
|
||||
#include "tomcrypt_pkcs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TOMCRYPT_H_ */
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt.h,v $ */
|
||||
/* $Revision: 1.21 $ */
|
||||
/* $Date: 2006/12/16 19:34:05 $ */
|
||||
@ -0,0 +1,38 @@
|
||||
/* Defines the LTC_ARGCHK macro used within the library */
|
||||
/* ARGTYPE is defined in mycrypt_cfg.h */
|
||||
#if ARGTYPE == 0
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
/* this is the default LibTomCrypt macro */
|
||||
void crypt_argchk(char *v, char *s, int d);
|
||||
#define LTC_ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
|
||||
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
|
||||
|
||||
#elif ARGTYPE == 1
|
||||
|
||||
/* fatal type of error */
|
||||
#define LTC_ARGCHK(x) assert((x))
|
||||
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
|
||||
|
||||
#elif ARGTYPE == 2
|
||||
|
||||
#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); }
|
||||
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
|
||||
|
||||
#elif ARGTYPE == 3
|
||||
|
||||
#define LTC_ARGCHK(x)
|
||||
#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
|
||||
|
||||
#elif ARGTYPE == 4
|
||||
|
||||
#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG;
|
||||
#define LTC_ARGCHKVD(x) if (!(x)) return;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_argchk.h,v $ */
|
||||
/* $Revision: 1.5 $ */
|
||||
/* $Date: 2006/08/27 20:50:21 $ */
|
||||
136
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_cfg.h
Normal file
136
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_cfg.h
Normal file
@ -0,0 +1,136 @@
|
||||
/* This is the build config file.
|
||||
*
|
||||
* With this you can setup what to inlcude/exclude automatically during any build. Just comment
|
||||
* out the line that #define's the word for the thing you want to remove. phew!
|
||||
*/
|
||||
|
||||
#ifndef TOMCRYPT_CFG_H
|
||||
#define TOMCRYPT_CFG_H
|
||||
|
||||
#if defined(_WIN32) || defined(_MSC_VER)
|
||||
#define LTC_CALL __cdecl
|
||||
#else
|
||||
#ifndef LTC_CALL
|
||||
#define LTC_CALL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LTC_EXPORT
|
||||
#define LTC_EXPORT
|
||||
#endif
|
||||
|
||||
/* certain platforms use macros for these, making the prototypes broken */
|
||||
#ifndef LTC_NO_PROTOTYPES
|
||||
|
||||
/* you can change how memory allocation works ... */
|
||||
LTC_EXPORT void * LTC_CALL XMALLOC(size_t n);
|
||||
LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n);
|
||||
LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s);
|
||||
LTC_EXPORT void LTC_CALL XFREE(void *p);
|
||||
|
||||
LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
|
||||
|
||||
|
||||
/* change the clock function too */
|
||||
LTC_EXPORT clock_t LTC_CALL XCLOCK(void);
|
||||
|
||||
/* various other functions */
|
||||
LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n);
|
||||
LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n);
|
||||
LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n);
|
||||
|
||||
LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);
|
||||
|
||||
#endif
|
||||
|
||||
/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */
|
||||
#ifndef ARGTYPE
|
||||
#define ARGTYPE 0
|
||||
#endif
|
||||
|
||||
/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code
|
||||
*
|
||||
* Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.
|
||||
* The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST**
|
||||
* use the portable [slower] macros.
|
||||
*/
|
||||
|
||||
/* detect x86-32 machines somewhat */
|
||||
#if !defined(__STRICT_ANSI__) && (defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__))))
|
||||
#define ENDIAN_LITTLE
|
||||
#define ENDIAN_32BITWORD
|
||||
#define LTC_FAST
|
||||
#define LTC_FAST_TYPE unsigned long
|
||||
#endif
|
||||
|
||||
/* detects MIPS R5900 processors (PS2) */
|
||||
#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
|
||||
#define ENDIAN_LITTLE
|
||||
#define ENDIAN_64BITWORD
|
||||
#endif
|
||||
|
||||
/* detect amd64 */
|
||||
#if !defined(__STRICT_ANSI__) && defined(__x86_64__)
|
||||
#define ENDIAN_LITTLE
|
||||
#define ENDIAN_64BITWORD
|
||||
#define LTC_FAST
|
||||
#define LTC_FAST_TYPE unsigned long
|
||||
#endif
|
||||
|
||||
/* detect PPC32 */
|
||||
#if !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
|
||||
#define ENDIAN_BIG
|
||||
#define ENDIAN_32BITWORD
|
||||
#define LTC_FAST
|
||||
#define LTC_FAST_TYPE unsigned long
|
||||
#endif
|
||||
|
||||
/* detect sparc and sparc64 */
|
||||
#if defined(__sparc__)
|
||||
#define ENDIAN_BIG
|
||||
#if defined(__arch64__)
|
||||
#define ENDIAN_64BITWORD
|
||||
#else
|
||||
#define ENDIAN_32BITWORD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LTC_NO_FAST
|
||||
#ifdef LTC_FAST
|
||||
#undef LTC_FAST
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* No asm is a quick way to disable anything "not portable" */
|
||||
#ifdef LTC_NO_ASM
|
||||
#undef ENDIAN_LITTLE
|
||||
#undef ENDIAN_BIG
|
||||
#undef ENDIAN_32BITWORD
|
||||
#undef ENDIAN_64BITWORD
|
||||
#undef LTC_FAST
|
||||
#undef LTC_FAST_TYPE
|
||||
#define LTC_NO_ROLC
|
||||
#define LTC_NO_BSWAP
|
||||
#endif
|
||||
|
||||
/* #define ENDIAN_LITTLE */
|
||||
/* #define ENDIAN_BIG */
|
||||
|
||||
/* #define ENDIAN_32BITWORD */
|
||||
/* #define ENDIAN_64BITWORD */
|
||||
|
||||
#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
|
||||
#error You must specify a word size as well as endianess in tomcrypt_cfg.h
|
||||
#endif
|
||||
|
||||
#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
|
||||
#define ENDIAN_NEUTRAL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cfg.h,v $ */
|
||||
/* $Revision: 1.19 $ */
|
||||
/* $Date: 2006/12/04 02:19:48 $ */
|
||||
@ -0,0 +1,891 @@
|
||||
/* ---- SYMMETRIC KEY STUFF -----
|
||||
*
|
||||
* We put each of the ciphers scheduled keys in their own structs then we put all of
|
||||
* the key formats in one union. This makes the function prototypes easier to use.
|
||||
*/
|
||||
#ifdef LTC_BLOWFISH
|
||||
struct blowfish_key {
|
||||
ulong32 S[4][256];
|
||||
ulong32 K[18];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC5
|
||||
struct rc5_key {
|
||||
int rounds;
|
||||
ulong32 K[50];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC6
|
||||
struct rc6_key {
|
||||
ulong32 K[44];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SAFERP
|
||||
struct saferp_key {
|
||||
unsigned char K[33][16];
|
||||
long rounds;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIJNDAEL
|
||||
struct rijndael_key {
|
||||
ulong32 eK[60], dK[60];
|
||||
int Nr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KSEED
|
||||
struct kseed_key {
|
||||
ulong32 K[32], dK[32];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KASUMI
|
||||
struct kasumi_key {
|
||||
ulong32 KLi1[8], KLi2[8],
|
||||
KOi1[8], KOi2[8], KOi3[8],
|
||||
KIi1[8], KIi2[8], KIi3[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_XTEA
|
||||
struct xtea_key {
|
||||
unsigned long A[32], B[32];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_TWOFISH
|
||||
#ifndef LTC_TWOFISH_SMALL
|
||||
struct twofish_key {
|
||||
ulong32 S[4][256], K[40];
|
||||
};
|
||||
#else
|
||||
struct twofish_key {
|
||||
ulong32 K[40];
|
||||
unsigned char S[32], start;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SAFER
|
||||
#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6
|
||||
#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10
|
||||
#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8
|
||||
#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10
|
||||
#define LTC_SAFER_MAX_NOF_ROUNDS 13
|
||||
#define LTC_SAFER_BLOCK_LEN 8
|
||||
#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS))
|
||||
typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN];
|
||||
typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN];
|
||||
struct safer_key { safer_key_t key; };
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC2
|
||||
struct rc2_key { unsigned xkey[64]; };
|
||||
#endif
|
||||
|
||||
#ifdef LTC_DES
|
||||
struct des_key {
|
||||
ulong32 ek[32], dk[32];
|
||||
};
|
||||
|
||||
struct des3_key {
|
||||
ulong32 ek[3][32], dk[3][32];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CAST5
|
||||
struct cast5_key {
|
||||
ulong32 K[32], keylen;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_NOEKEON
|
||||
struct noekeon_key {
|
||||
ulong32 K[4], dK[4];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SKIPJACK
|
||||
struct skipjack_key {
|
||||
unsigned char key[10];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KHAZAD
|
||||
struct khazad_key {
|
||||
ulong64 roundKeyEnc[8 + 1];
|
||||
ulong64 roundKeyDec[8 + 1];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_ANUBIS
|
||||
struct anubis_key {
|
||||
int keyBits;
|
||||
int R;
|
||||
ulong32 roundKeyEnc[18 + 1][4];
|
||||
ulong32 roundKeyDec[18 + 1][4];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MULTI2
|
||||
struct multi2_key {
|
||||
int N;
|
||||
ulong32 uk[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union Symmetric_key {
|
||||
#ifdef LTC_DES
|
||||
struct des_key des;
|
||||
struct des3_key des3;
|
||||
#endif
|
||||
#ifdef LTC_RC2
|
||||
struct rc2_key rc2;
|
||||
#endif
|
||||
#ifdef LTC_SAFER
|
||||
struct safer_key safer;
|
||||
#endif
|
||||
#ifdef LTC_TWOFISH
|
||||
struct twofish_key twofish;
|
||||
#endif
|
||||
#ifdef LTC_BLOWFISH
|
||||
struct blowfish_key blowfish;
|
||||
#endif
|
||||
#ifdef LTC_RC5
|
||||
struct rc5_key rc5;
|
||||
#endif
|
||||
#ifdef LTC_RC6
|
||||
struct rc6_key rc6;
|
||||
#endif
|
||||
#ifdef LTC_SAFERP
|
||||
struct saferp_key saferp;
|
||||
#endif
|
||||
#ifdef LTC_RIJNDAEL
|
||||
struct rijndael_key rijndael;
|
||||
#endif
|
||||
#ifdef LTC_XTEA
|
||||
struct xtea_key xtea;
|
||||
#endif
|
||||
#ifdef LTC_CAST5
|
||||
struct cast5_key cast5;
|
||||
#endif
|
||||
#ifdef LTC_NOEKEON
|
||||
struct noekeon_key noekeon;
|
||||
#endif
|
||||
#ifdef LTC_SKIPJACK
|
||||
struct skipjack_key skipjack;
|
||||
#endif
|
||||
#ifdef LTC_KHAZAD
|
||||
struct khazad_key khazad;
|
||||
#endif
|
||||
#ifdef LTC_ANUBIS
|
||||
struct anubis_key anubis;
|
||||
#endif
|
||||
#ifdef LTC_KSEED
|
||||
struct kseed_key kseed;
|
||||
#endif
|
||||
#ifdef LTC_KASUMI
|
||||
struct kasumi_key kasumi;
|
||||
#endif
|
||||
#ifdef LTC_MULTI2
|
||||
struct multi2_key multi2;
|
||||
#endif
|
||||
void *data;
|
||||
} symmetric_key;
|
||||
|
||||
#ifdef LTC_ECB_MODE
|
||||
/** A block cipher ECB structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen;
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_ECB;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CFB_MODE
|
||||
/** A block cipher CFB structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen,
|
||||
/** The padding offset */
|
||||
padlen;
|
||||
/** The current IV */
|
||||
unsigned char IV[MAXBLOCKSIZE],
|
||||
/** The pad used to encrypt/decrypt */
|
||||
pad[MAXBLOCKSIZE];
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_CFB;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_OFB_MODE
|
||||
/** A block cipher OFB structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen,
|
||||
/** The padding offset */
|
||||
padlen;
|
||||
/** The current IV */
|
||||
unsigned char IV[MAXBLOCKSIZE];
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_OFB;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CBC_MODE
|
||||
/** A block cipher CBC structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen;
|
||||
/** The current IV */
|
||||
unsigned char IV[MAXBLOCKSIZE];
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_CBC;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LTC_CTR_MODE
|
||||
/** A block cipher CTR structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen,
|
||||
/** The padding offset */
|
||||
padlen,
|
||||
/** The mode (endianess) of the CTR, 0==little, 1==big */
|
||||
mode,
|
||||
/** counter width */
|
||||
ctrlen;
|
||||
|
||||
/** The counter */
|
||||
unsigned char ctr[MAXBLOCKSIZE],
|
||||
/** The pad used to encrypt/decrypt */
|
||||
pad[MAXBLOCKSIZE];
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_CTR;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LTC_LRW_MODE
|
||||
/** A LRW structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen (must be a 128-bit block cipher) */
|
||||
int cipher;
|
||||
|
||||
/** The current IV */
|
||||
unsigned char IV[16],
|
||||
|
||||
/** the tweak key */
|
||||
tweak[16],
|
||||
|
||||
/** The current pad, it's the product of the first 15 bytes against the tweak key */
|
||||
pad[16];
|
||||
|
||||
/** The scheduled symmetric key */
|
||||
symmetric_key key;
|
||||
|
||||
#ifdef LRW_TABLES
|
||||
/** The pre-computed multiplication table */
|
||||
unsigned char PC[16][256][16];
|
||||
#endif
|
||||
} symmetric_LRW;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_F8_MODE
|
||||
/** A block cipher F8 structure */
|
||||
typedef struct {
|
||||
/** The index of the cipher chosen */
|
||||
int cipher,
|
||||
/** The block size of the given cipher */
|
||||
blocklen,
|
||||
/** The padding offset */
|
||||
padlen;
|
||||
/** The current IV */
|
||||
unsigned char IV[MAXBLOCKSIZE],
|
||||
MIV[MAXBLOCKSIZE];
|
||||
/** Current block count */
|
||||
ulong32 blockcnt;
|
||||
/** The scheduled key */
|
||||
symmetric_key key;
|
||||
} symmetric_F8;
|
||||
#endif
|
||||
|
||||
|
||||
/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */
|
||||
extern struct ltc_cipher_descriptor {
|
||||
/** name of cipher */
|
||||
char *name;
|
||||
/** internal ID */
|
||||
unsigned char ID;
|
||||
/** min keysize (octets) */
|
||||
int min_key_length,
|
||||
/** max keysize (octets) */
|
||||
max_key_length,
|
||||
/** block size (octets) */
|
||||
block_length,
|
||||
/** default number of rounds */
|
||||
default_rounds;
|
||||
/** Setup the cipher
|
||||
@param key The input symmetric key
|
||||
@param keylen The length of the input key (octets)
|
||||
@param num_rounds The requested number of rounds (0==default)
|
||||
@param skey [out] The destination of the scheduled key
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
/** Encrypt a block
|
||||
@param pt The plaintext
|
||||
@param ct [out] The ciphertext
|
||||
@param skey The scheduled key
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
/** Decrypt a block
|
||||
@param ct The ciphertext
|
||||
@param pt [out] The plaintext
|
||||
@param skey The scheduled key
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
/** Test the block cipher
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
|
||||
*/
|
||||
int (*test)(void);
|
||||
|
||||
/** Terminate the context
|
||||
@param skey The scheduled key
|
||||
*/
|
||||
void (*done)(symmetric_key *skey);
|
||||
|
||||
/** Determine a key size
|
||||
@param keysize [in/out] The size of the key desired and the suggested size
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*keysize)(int *keysize);
|
||||
|
||||
/** Accelerators **/
|
||||
/** Accelerated ECB encryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey);
|
||||
|
||||
/** Accelerated ECB decryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey);
|
||||
|
||||
/** Accelerated CBC encryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
|
||||
|
||||
/** Accelerated CBC decryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey);
|
||||
|
||||
/** Accelerated CTR encryption
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param mode little or big endian counter (mode=0 or mode=1)
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey);
|
||||
|
||||
/** Accelerated LRW
|
||||
@param pt Plaintext
|
||||
@param ct Ciphertext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param tweak The LRW tweak
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
|
||||
|
||||
/** Accelerated LRW
|
||||
@param ct Ciphertext
|
||||
@param pt Plaintext
|
||||
@param blocks The number of complete blocks to process
|
||||
@param IV The initial value (input/output)
|
||||
@param tweak The LRW tweak
|
||||
@param skey The scheduled key context
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey);
|
||||
|
||||
/** Accelerated CCM packet (one-shot)
|
||||
@param key The secret key to use
|
||||
@param keylen The length of the secret key (octets)
|
||||
@param uskey A previously scheduled key [optional can be NULL]
|
||||
@param nonce The session nonce [use once]
|
||||
@param noncelen The length of the nonce
|
||||
@param header The header for the session
|
||||
@param headerlen The length of the header (octets)
|
||||
@param pt [out] The plaintext
|
||||
@param ptlen The length of the plaintext (octets)
|
||||
@param ct [out] The ciphertext
|
||||
@param tag [out] The destination tag
|
||||
@param taglen [in/out] The max size and resulting size of the authentication tag
|
||||
@param direction Encrypt or Decrypt direction (0 or 1)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*accel_ccm_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
symmetric_key *uskey,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
|
||||
/** Accelerated GCM packet (one shot)
|
||||
@param key The secret key
|
||||
@param keylen The length of the secret key
|
||||
@param IV The initial vector
|
||||
@param IVlen The length of the initial vector
|
||||
@param adata The additional authentication data (header)
|
||||
@param adatalen The length of the adata
|
||||
@param pt The plaintext
|
||||
@param ptlen The length of the plaintext (ciphertext length is the same)
|
||||
@param ct The ciphertext
|
||||
@param tag [out] The MAC tag
|
||||
@param taglen [in/out] The MAC tag length
|
||||
@param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*accel_gcm_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *IV, unsigned long IVlen,
|
||||
const unsigned char *adata, unsigned long adatalen,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
|
||||
/** Accelerated one shot LTC_OMAC
|
||||
@param key The secret key
|
||||
@param keylen The key length (octets)
|
||||
@param in The message
|
||||
@param inlen Length of message (octets)
|
||||
@param out [out] Destination for tag
|
||||
@param outlen [in/out] Initial and final size of out
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*omac_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/** Accelerated one shot XCBC
|
||||
@param key The secret key
|
||||
@param keylen The key length (octets)
|
||||
@param in The message
|
||||
@param inlen Length of message (octets)
|
||||
@param out [out] Destination for tag
|
||||
@param outlen [in/out] Initial and final size of out
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*xcbc_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/** Accelerated one shot F9
|
||||
@param key The secret key
|
||||
@param keylen The key length (octets)
|
||||
@param in The message
|
||||
@param inlen Length of message (octets)
|
||||
@param out [out] Destination for tag
|
||||
@param outlen [in/out] Initial and final size of out
|
||||
@return CRYPT_OK on success
|
||||
@remark Requires manual padding
|
||||
*/
|
||||
int (*f9_memory)(
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
} cipher_descriptor[];
|
||||
|
||||
#ifdef LTC_BLOWFISH
|
||||
int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int blowfish_test(void);
|
||||
void blowfish_done(symmetric_key *skey);
|
||||
int blowfish_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor blowfish_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC5
|
||||
int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int rc5_test(void);
|
||||
void rc5_done(symmetric_key *skey);
|
||||
int rc5_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor rc5_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC6
|
||||
int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int rc6_test(void);
|
||||
void rc6_done(symmetric_key *skey);
|
||||
int rc6_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor rc6_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC2
|
||||
int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int rc2_test(void);
|
||||
void rc2_done(symmetric_key *skey);
|
||||
int rc2_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor rc2_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SAFERP
|
||||
int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int saferp_test(void);
|
||||
void saferp_done(symmetric_key *skey);
|
||||
int saferp_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor saferp_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SAFER
|
||||
int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
|
||||
int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
|
||||
int safer_k64_test(void);
|
||||
int safer_sk64_test(void);
|
||||
int safer_sk128_test(void);
|
||||
void safer_done(symmetric_key *skey);
|
||||
int safer_64_keysize(int *keysize);
|
||||
int safer_128_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIJNDAEL
|
||||
|
||||
/* make aes an alias */
|
||||
#define aes_setup rijndael_setup
|
||||
#define aes_ecb_encrypt rijndael_ecb_encrypt
|
||||
#define aes_ecb_decrypt rijndael_ecb_decrypt
|
||||
#define aes_test rijndael_test
|
||||
#define aes_done rijndael_done
|
||||
#define aes_keysize rijndael_keysize
|
||||
|
||||
#define aes_enc_setup rijndael_enc_setup
|
||||
#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt
|
||||
#define aes_enc_keysize rijndael_enc_keysize
|
||||
|
||||
int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int rijndael_test(void);
|
||||
void rijndael_done(symmetric_key *skey);
|
||||
int rijndael_keysize(int *keysize);
|
||||
int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
void rijndael_enc_done(symmetric_key *skey);
|
||||
int rijndael_enc_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc;
|
||||
extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_XTEA
|
||||
int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int xtea_test(void);
|
||||
void xtea_done(symmetric_key *skey);
|
||||
int xtea_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor xtea_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_TWOFISH
|
||||
int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int twofish_test(void);
|
||||
void twofish_done(symmetric_key *skey);
|
||||
int twofish_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor twofish_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_DES
|
||||
int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int des_test(void);
|
||||
void des_done(symmetric_key *skey);
|
||||
int des_keysize(int *keysize);
|
||||
int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int des3_test(void);
|
||||
void des3_done(symmetric_key *skey);
|
||||
int des3_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor des_desc, des3_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CAST5
|
||||
int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int cast5_test(void);
|
||||
void cast5_done(symmetric_key *skey);
|
||||
int cast5_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor cast5_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_NOEKEON
|
||||
int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int noekeon_test(void);
|
||||
void noekeon_done(symmetric_key *skey);
|
||||
int noekeon_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor noekeon_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SKIPJACK
|
||||
int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int skipjack_test(void);
|
||||
void skipjack_done(symmetric_key *skey);
|
||||
int skipjack_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor skipjack_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KHAZAD
|
||||
int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int khazad_test(void);
|
||||
void khazad_done(symmetric_key *skey);
|
||||
int khazad_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor khazad_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_ANUBIS
|
||||
int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int anubis_test(void);
|
||||
void anubis_done(symmetric_key *skey);
|
||||
int anubis_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor anubis_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KSEED
|
||||
int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int kseed_test(void);
|
||||
void kseed_done(symmetric_key *skey);
|
||||
int kseed_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor kseed_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_KASUMI
|
||||
int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int kasumi_test(void);
|
||||
void kasumi_done(symmetric_key *skey);
|
||||
int kasumi_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor kasumi_desc;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LTC_MULTI2
|
||||
int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
|
||||
int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey);
|
||||
int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey);
|
||||
int multi2_test(void);
|
||||
void multi2_done(symmetric_key *skey);
|
||||
int multi2_keysize(int *keysize);
|
||||
extern const struct ltc_cipher_descriptor multi2_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_ECB_MODE
|
||||
int ecb_start(int cipher, const unsigned char *key,
|
||||
int keylen, int num_rounds, symmetric_ECB *ecb);
|
||||
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb);
|
||||
int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb);
|
||||
int ecb_done(symmetric_ECB *ecb);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CFB_MODE
|
||||
int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key,
|
||||
int keylen, int num_rounds, symmetric_CFB *cfb);
|
||||
int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
|
||||
int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
|
||||
int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb);
|
||||
int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb);
|
||||
int cfb_done(symmetric_CFB *cfb);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_OFB_MODE
|
||||
int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key,
|
||||
int keylen, int num_rounds, symmetric_OFB *ofb);
|
||||
int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
|
||||
int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
|
||||
int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb);
|
||||
int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb);
|
||||
int ofb_done(symmetric_OFB *ofb);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CBC_MODE
|
||||
int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
|
||||
int keylen, int num_rounds, symmetric_CBC *cbc);
|
||||
int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc);
|
||||
int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc);
|
||||
int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);
|
||||
int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
|
||||
int cbc_done(symmetric_CBC *cbc);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CTR_MODE
|
||||
|
||||
#define CTR_COUNTER_LITTLE_ENDIAN 0x0000
|
||||
#define CTR_COUNTER_BIG_ENDIAN 0x1000
|
||||
#define LTC_CTR_RFC3686 0x2000
|
||||
|
||||
int ctr_start( int cipher,
|
||||
const unsigned char *IV,
|
||||
const unsigned char *key, int keylen,
|
||||
int num_rounds, int ctr_mode,
|
||||
symmetric_CTR *ctr);
|
||||
int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
|
||||
int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
|
||||
int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr);
|
||||
int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr);
|
||||
int ctr_done(symmetric_CTR *ctr);
|
||||
int ctr_test(void);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_LRW_MODE
|
||||
|
||||
#define LRW_ENCRYPT 0
|
||||
#define LRW_DECRYPT 1
|
||||
|
||||
int lrw_start( int cipher,
|
||||
const unsigned char *IV,
|
||||
const unsigned char *key, int keylen,
|
||||
const unsigned char *tweak,
|
||||
int num_rounds,
|
||||
symmetric_LRW *lrw);
|
||||
int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw);
|
||||
int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw);
|
||||
int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw);
|
||||
int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw);
|
||||
int lrw_done(symmetric_LRW *lrw);
|
||||
int lrw_test(void);
|
||||
|
||||
/* don't call */
|
||||
int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_F8_MODE
|
||||
int f8_start( int cipher, const unsigned char *IV,
|
||||
const unsigned char *key, int keylen,
|
||||
const unsigned char *salt_key, int skeylen,
|
||||
int num_rounds, symmetric_F8 *f8);
|
||||
int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8);
|
||||
int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8);
|
||||
int f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8);
|
||||
int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8);
|
||||
int f8_done(symmetric_F8 *f8);
|
||||
int f8_test_mode(void);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_XTS_MODE
|
||||
typedef struct {
|
||||
symmetric_key key1, key2;
|
||||
int cipher;
|
||||
} symmetric_xts;
|
||||
|
||||
int xts_start( int cipher,
|
||||
const unsigned char *key1,
|
||||
const unsigned char *key2,
|
||||
unsigned long keylen,
|
||||
int num_rounds,
|
||||
symmetric_xts *xts);
|
||||
|
||||
int xts_encrypt(
|
||||
const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
const unsigned char *tweak,
|
||||
symmetric_xts *xts);
|
||||
int xts_decrypt(
|
||||
const unsigned char *ct, unsigned long ptlen,
|
||||
unsigned char *pt,
|
||||
const unsigned char *tweak,
|
||||
symmetric_xts *xts);
|
||||
|
||||
void xts_done(symmetric_xts *xts);
|
||||
int xts_test(void);
|
||||
void xts_mult_x(unsigned char *I);
|
||||
#endif
|
||||
|
||||
int find_cipher(const char *name);
|
||||
int find_cipher_any(const char *name, int blocklen, int keylen);
|
||||
int find_cipher_id(unsigned char ID);
|
||||
int register_cipher(const struct ltc_cipher_descriptor *cipher);
|
||||
int unregister_cipher(const struct ltc_cipher_descriptor *cipher);
|
||||
int cipher_is_valid(int idx);
|
||||
|
||||
LTC_MUTEX_PROTO(ltc_cipher_mutex)
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cipher.h,v $ */
|
||||
/* $Revision: 1.54 $ */
|
||||
/* $Date: 2007/05/12 14:37:41 $ */
|
||||
@ -0,0 +1,424 @@
|
||||
#ifndef TOMCRYPT_CUSTOM_H_
|
||||
#define TOMCRYPT_CUSTOM_H_
|
||||
|
||||
#define LTC_NO_CIPHERS
|
||||
#define LTC_NO_HASHES
|
||||
#define LTC_NO_MACS
|
||||
#define LTC_NO_PRNGS
|
||||
#define LTC_NO_CURVES
|
||||
#define LTC_NO_MODES
|
||||
#define LTC_NO_PKCS
|
||||
#define LTC_NO_ROLC
|
||||
|
||||
#define LTC_SOURCE
|
||||
#define LTC_SHA1
|
||||
#define LTC_MD5
|
||||
#define LTC_DER
|
||||
#define LTC_RC4
|
||||
|
||||
#define USE_LTM
|
||||
#define LTM_DESC
|
||||
|
||||
/* macros for various libc functions you can change for embedded targets */
|
||||
#ifndef XMALLOC
|
||||
#ifdef malloc
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XMALLOC LibTomMalloc
|
||||
#endif
|
||||
#ifndef XREALLOC
|
||||
#ifdef realloc
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XREALLOC LibTomRealloc
|
||||
#endif
|
||||
#ifndef XCALLOC
|
||||
#ifdef calloc
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XCALLOC LibTomCalloc
|
||||
#endif
|
||||
#ifndef XFREE
|
||||
#ifdef free
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XFREE LibTomFree
|
||||
#endif
|
||||
|
||||
#ifndef XMEMSET
|
||||
#ifdef memset
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XMEMSET memset
|
||||
#endif
|
||||
#ifndef XMEMCPY
|
||||
#ifdef memcpy
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XMEMCPY memcpy
|
||||
#endif
|
||||
#ifndef XMEMCMP
|
||||
#ifdef memcmp
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XMEMCMP memcmp
|
||||
#endif
|
||||
#ifndef XSTRCMP
|
||||
#ifdef strcmp
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XSTRCMP strcmp
|
||||
#endif
|
||||
|
||||
#ifndef XCLOCK
|
||||
#define XCLOCK LibTomClock
|
||||
#endif
|
||||
#ifndef XCLOCKS_PER_SEC
|
||||
#define XCLOCKS_PER_SEC CLOCKS_PER_SEC
|
||||
#endif
|
||||
|
||||
#ifndef XQSORT
|
||||
#ifdef qsort
|
||||
#define LTC_NO_PROTOTYPES
|
||||
#endif
|
||||
#define XQSORT LibTomQsort
|
||||
#endif
|
||||
|
||||
/* Easy button? */
|
||||
#ifdef LTC_EASY
|
||||
#define LTC_NO_CIPHERS
|
||||
#define LTC_RIJNDAEL
|
||||
#define LTC_BLOWFISH
|
||||
#define LTC_DES
|
||||
#define LTC_CAST5
|
||||
|
||||
#define LTC_NO_MODES
|
||||
#define LTC_ECB_MODE
|
||||
#define LTC_CBC_MODE
|
||||
#define LTC_CTR_MODE
|
||||
|
||||
#define LTC_NO_HASHES
|
||||
#define LTC_SHA1
|
||||
#define LTC_SHA512
|
||||
#define LTC_SHA384
|
||||
#define LTC_SHA256
|
||||
#define LTC_SHA224
|
||||
|
||||
#define LTC_NO_MACS
|
||||
#define LTC_HMAC
|
||||
#define LTC_OMAC
|
||||
#define LTC_CCM_MODE
|
||||
|
||||
#define LTC_NO_PRNGS
|
||||
#define LTC_SPRNG
|
||||
#define LTC_YARROW
|
||||
#define LTC_DEVRANDOM
|
||||
#define TRY_URANDOM_FIRST
|
||||
|
||||
#define LTC_NO_PK
|
||||
#define LTC_MRSA
|
||||
#define LTC_MECC
|
||||
#endif
|
||||
|
||||
/* Use small code where possible */
|
||||
/* #define LTC_SMALL_CODE */
|
||||
|
||||
/* Enable self-test test vector checking */
|
||||
#ifndef LTC_NO_TEST
|
||||
#define LTC_TEST
|
||||
#endif
|
||||
|
||||
/* clean the stack of functions which put private information on stack */
|
||||
/* #define LTC_CLEAN_STACK */
|
||||
|
||||
/* disable all file related functions */
|
||||
/* #define LTC_NO_FILE */
|
||||
|
||||
/* disable all forms of ASM */
|
||||
/* #define LTC_NO_ASM */
|
||||
|
||||
/* disable FAST mode */
|
||||
/* #define LTC_NO_FAST */
|
||||
|
||||
/* disable BSWAP on x86 */
|
||||
/* #define LTC_NO_BSWAP */
|
||||
|
||||
/* ---> Symmetric Block Ciphers <--- */
|
||||
#ifndef LTC_NO_CIPHERS
|
||||
|
||||
#define LTC_BLOWFISH
|
||||
#define LTC_RC2
|
||||
#define LTC_RC5
|
||||
#define LTC_RC6
|
||||
#define LTC_SAFERP
|
||||
#define LTC_RIJNDAEL
|
||||
#define LTC_XTEA
|
||||
/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
|
||||
* (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
|
||||
#define LTC_TWOFISH
|
||||
#ifndef LTC_NO_TABLES
|
||||
#define LTC_TWOFISH_TABLES
|
||||
/* #define LTC_TWOFISH_ALL_TABLES */
|
||||
#else
|
||||
#define LTC_TWOFISH_SMALL
|
||||
#endif
|
||||
/* #define LTC_TWOFISH_SMALL */
|
||||
/* LTC_DES includes EDE triple-LTC_DES */
|
||||
#define LTC_DES
|
||||
#define LTC_CAST5
|
||||
#define LTC_NOEKEON
|
||||
#define LTC_SKIPJACK
|
||||
#define LTC_SAFER
|
||||
#define LTC_KHAZAD
|
||||
#define LTC_ANUBIS
|
||||
#define LTC_ANUBIS_TWEAK
|
||||
#define LTC_KSEED
|
||||
#define LTC_KASUMI
|
||||
|
||||
#endif /* LTC_NO_CIPHERS */
|
||||
|
||||
|
||||
/* ---> Block Cipher Modes of Operation <--- */
|
||||
#ifndef LTC_NO_MODES
|
||||
|
||||
#define LTC_CFB_MODE
|
||||
#define LTC_OFB_MODE
|
||||
#define LTC_ECB_MODE
|
||||
#define LTC_CBC_MODE
|
||||
#define LTC_CTR_MODE
|
||||
|
||||
/* F8 chaining mode */
|
||||
#define LTC_F8_MODE
|
||||
|
||||
/* LRW mode */
|
||||
#define LTC_LRW_MODE
|
||||
#ifndef LTC_NO_TABLES
|
||||
/* like GCM mode this will enable 16 8x128 tables [64KB] that make
|
||||
* seeking very fast.
|
||||
*/
|
||||
#define LRW_TABLES
|
||||
#endif
|
||||
|
||||
/* XTS mode */
|
||||
#define LTC_XTS_MODE
|
||||
|
||||
#endif /* LTC_NO_MODES */
|
||||
|
||||
/* ---> One-Way Hash Functions <--- */
|
||||
#ifndef LTC_NO_HASHES
|
||||
|
||||
#define LTC_CHC_HASH
|
||||
#define LTC_WHIRLPOOL
|
||||
#define LTC_SHA512
|
||||
#define LTC_SHA384
|
||||
#define LTC_SHA256
|
||||
#define LTC_SHA224
|
||||
#define LTC_TIGER
|
||||
#define LTC_SHA1
|
||||
#define LTC_MD5
|
||||
#define LTC_MD4
|
||||
#define LTC_MD2
|
||||
#define LTC_RIPEMD128
|
||||
#define LTC_RIPEMD160
|
||||
#define LTC_RIPEMD256
|
||||
#define LTC_RIPEMD320
|
||||
|
||||
#endif /* LTC_NO_HASHES */
|
||||
|
||||
/* ---> MAC functions <--- */
|
||||
#ifndef LTC_NO_MACS
|
||||
|
||||
#define LTC_HMAC
|
||||
#define LTC_OMAC
|
||||
#define LTC_PMAC
|
||||
#define LTC_XCBC
|
||||
#define LTC_F9_MODE
|
||||
#define LTC_PELICAN
|
||||
|
||||
#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL)
|
||||
#error Pelican-MAC requires LTC_RIJNDAEL
|
||||
#endif
|
||||
|
||||
/* ---> Encrypt + Authenticate Modes <--- */
|
||||
|
||||
#define LTC_EAX_MODE
|
||||
#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC))
|
||||
#error LTC_EAX_MODE requires CTR and LTC_OMAC mode
|
||||
#endif
|
||||
|
||||
#define LTC_OCB_MODE
|
||||
#define LTC_CCM_MODE
|
||||
#define LTC_GCM_MODE
|
||||
|
||||
/* Use 64KiB tables */
|
||||
#ifndef LTC_NO_TABLES
|
||||
#define LTC_GCM_TABLES
|
||||
#endif
|
||||
|
||||
/* USE SSE2? requires GCC works on x86_32 and x86_64*/
|
||||
#ifdef LTC_GCM_TABLES
|
||||
/* #define LTC_GCM_TABLES_SSE2 */
|
||||
#endif
|
||||
|
||||
#endif /* LTC_NO_MACS */
|
||||
|
||||
/* Various tidbits of modern neatoness */
|
||||
#define LTC_BASE64
|
||||
|
||||
/* --> Pseudo Random Number Generators <--- */
|
||||
#ifndef LTC_NO_PRNGS
|
||||
|
||||
/* Yarrow */
|
||||
#define LTC_YARROW
|
||||
/* which descriptor of AES to use? */
|
||||
/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */
|
||||
#define LTC_YARROW_AES 0
|
||||
|
||||
#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE)
|
||||
#error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined!
|
||||
#endif
|
||||
|
||||
/* a PRNG that simply reads from an available system source */
|
||||
#define LTC_SPRNG
|
||||
|
||||
/* The LTC_RC4 stream cipher */
|
||||
#define LTC_RC4
|
||||
|
||||
/* Fortuna PRNG */
|
||||
#define LTC_FORTUNA
|
||||
/* reseed every N calls to the read function */
|
||||
#define LTC_FORTUNA_WD 10
|
||||
/* number of pools (4..32) can save a bit of ram by lowering the count */
|
||||
#define LTC_FORTUNA_POOLS 32
|
||||
|
||||
/* Greg's LTC_SOBER128 PRNG ;-0 */
|
||||
#define LTC_SOBER128
|
||||
|
||||
/* the *nix style /dev/random device */
|
||||
#define LTC_DEVRANDOM
|
||||
/* try /dev/urandom before trying /dev/random */
|
||||
#define TRY_URANDOM_FIRST
|
||||
|
||||
#endif /* LTC_NO_PRNGS */
|
||||
|
||||
/* ---> math provider? <--- */
|
||||
#ifndef LTC_NO_MATH
|
||||
|
||||
/* LibTomMath */
|
||||
#define LTM_LTC_DESC
|
||||
|
||||
/* TomsFastMath */
|
||||
//#define TFM_LTC_DESC
|
||||
|
||||
#endif /* LTC_NO_MATH */
|
||||
|
||||
/* ---> Public Key Crypto <--- */
|
||||
#ifndef LTC_NO_PK
|
||||
|
||||
/* Include RSA support */
|
||||
#define LTC_MRSA
|
||||
|
||||
/* Include Katja (a Rabin variant like RSA) */
|
||||
/* #define MKAT */
|
||||
|
||||
/* Digital Signature Algorithm */
|
||||
#define LTC_MDSA
|
||||
|
||||
/* ECC */
|
||||
#define LTC_MECC
|
||||
|
||||
/* use Shamir's trick for point mul (speeds up signature verification) */
|
||||
#define LTC_ECC_SHAMIR
|
||||
|
||||
#if defined(TFM_LTC_DESC) && defined(LTC_MECC)
|
||||
#define LTC_MECC_ACCEL
|
||||
#endif
|
||||
|
||||
/* do we want fixed point ECC */
|
||||
/* #define LTC_MECC_FP */
|
||||
|
||||
/* Timing Resistant? */
|
||||
/* #define LTC_ECC_TIMING_RESISTANT */
|
||||
|
||||
#endif /* LTC_NO_PK */
|
||||
|
||||
/* LTC_PKCS #1 (RSA) and #5 (Password Handling) stuff */
|
||||
#ifndef LTC_NO_PKCS
|
||||
|
||||
#define LTC_PKCS_1
|
||||
#define LTC_PKCS_5
|
||||
|
||||
/* Include ASN.1 DER (required by DSA/RSA) */
|
||||
#define LTC_DER
|
||||
|
||||
#endif /* LTC_NO_PKCS */
|
||||
|
||||
/* cleanup */
|
||||
|
||||
#ifdef LTC_MECC
|
||||
/* Supported ECC Key Sizes */
|
||||
#ifndef LTC_NO_CURVES
|
||||
#define ECC112
|
||||
#define ECC128
|
||||
#define ECC160
|
||||
#define ECC192
|
||||
#define ECC224
|
||||
#define ECC256
|
||||
#define ECC384
|
||||
#define ECC521
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(MKATJA)
|
||||
/* Include the MPI functionality? (required by the PK algorithms) */
|
||||
#define MPI
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MRSA
|
||||
#define LTC_PKCS_1
|
||||
#endif
|
||||
|
||||
#if defined(LTC_DER) && !defined(MPI)
|
||||
#error ASN.1 DER requires MPI functionality
|
||||
#endif
|
||||
|
||||
#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC) || defined(MKATJA)) && !defined(LTC_DER)
|
||||
#error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled
|
||||
#endif
|
||||
|
||||
/* THREAD management */
|
||||
#ifdef LTC_PTHREAD
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
|
||||
#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x;
|
||||
#define LTC_MUTEX_TYPE(x) pthread_mutex_t x;
|
||||
#define LTC_MUTEX_INIT(x) pthread_mutex_init(x, NULL);
|
||||
#define LTC_MUTEX_LOCK(x) pthread_mutex_lock(x);
|
||||
#define LTC_MUTEX_UNLOCK(x) pthread_mutex_unlock(x);
|
||||
|
||||
#else
|
||||
|
||||
/* default no functions */
|
||||
#define LTC_MUTEX_GLOBAL(x)
|
||||
#define LTC_MUTEX_PROTO(x)
|
||||
#define LTC_MUTEX_TYPE(x)
|
||||
#define LTC_MUTEX_INIT(x)
|
||||
#define LTC_MUTEX_LOCK(x)
|
||||
#define LTC_MUTEX_UNLOCK(x)
|
||||
|
||||
#endif
|
||||
|
||||
/* Debuggers */
|
||||
|
||||
/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and LTC_RC4 work (see the code) */
|
||||
/* #define LTC_VALGRIND */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_custom.h,v $ */
|
||||
/* $Revision: 1.73 $ */
|
||||
/* $Date: 2007/05/12 14:37:41 $ */
|
||||
378
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_hash.h
Normal file
378
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_hash.h
Normal file
@ -0,0 +1,378 @@
|
||||
/* ---- HASH FUNCTIONS ---- */
|
||||
#ifdef LTC_SHA512
|
||||
struct sha512_state {
|
||||
ulong64 length, state[8];
|
||||
unsigned long curlen;
|
||||
unsigned char buf[128];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA256
|
||||
struct sha256_state {
|
||||
ulong64 length;
|
||||
ulong32 state[8], curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA1
|
||||
struct sha1_state {
|
||||
ulong64 length;
|
||||
ulong32 state[5], curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD5
|
||||
struct md5_state {
|
||||
ulong64 length;
|
||||
ulong32 state[4], curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD4
|
||||
struct md4_state {
|
||||
ulong64 length;
|
||||
ulong32 state[4], curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_TIGER
|
||||
struct tiger_state {
|
||||
ulong64 state[3], length;
|
||||
unsigned long curlen;
|
||||
unsigned char buf[64];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD2
|
||||
struct md2_state {
|
||||
unsigned char chksum[16], X[48], buf[16];
|
||||
unsigned long curlen;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD128
|
||||
struct rmd128_state {
|
||||
ulong64 length;
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen, state[4];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD160
|
||||
struct rmd160_state {
|
||||
ulong64 length;
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen, state[5];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD256
|
||||
struct rmd256_state {
|
||||
ulong64 length;
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen, state[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD320
|
||||
struct rmd320_state {
|
||||
ulong64 length;
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen, state[10];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_WHIRLPOOL
|
||||
struct whirlpool_state {
|
||||
ulong64 length, state[8];
|
||||
unsigned char buf[64];
|
||||
ulong32 curlen;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CHC_HASH
|
||||
struct chc_state {
|
||||
ulong64 length;
|
||||
unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];
|
||||
ulong32 curlen;
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union Hash_state {
|
||||
#ifdef LTC_CHC_HASH
|
||||
struct chc_state chc;
|
||||
#endif
|
||||
#ifdef LTC_WHIRLPOOL
|
||||
struct whirlpool_state whirlpool;
|
||||
#endif
|
||||
#ifdef LTC_SHA512
|
||||
struct sha512_state sha512;
|
||||
#endif
|
||||
#ifdef LTC_SHA256
|
||||
struct sha256_state sha256;
|
||||
#endif
|
||||
#ifdef LTC_SHA1
|
||||
struct sha1_state sha1;
|
||||
#endif
|
||||
#ifdef LTC_MD5
|
||||
struct md5_state md5;
|
||||
#endif
|
||||
#ifdef LTC_MD4
|
||||
struct md4_state md4;
|
||||
#endif
|
||||
#ifdef LTC_MD2
|
||||
struct md2_state md2;
|
||||
#endif
|
||||
#ifdef LTC_TIGER
|
||||
struct tiger_state tiger;
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD128
|
||||
struct rmd128_state rmd128;
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD160
|
||||
struct rmd160_state rmd160;
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD256
|
||||
struct rmd256_state rmd256;
|
||||
#endif
|
||||
#ifdef LTC_RIPEMD320
|
||||
struct rmd320_state rmd320;
|
||||
#endif
|
||||
void *data;
|
||||
} hash_state;
|
||||
|
||||
/** hash descriptor */
|
||||
extern struct ltc_hash_descriptor {
|
||||
/** name of hash */
|
||||
char *name;
|
||||
/** internal ID */
|
||||
unsigned char ID;
|
||||
/** Size of digest in octets */
|
||||
unsigned long hashsize;
|
||||
/** Input block size in octets */
|
||||
unsigned long blocksize;
|
||||
/** ASN.1 OID */
|
||||
unsigned long OID[16];
|
||||
/** Length of DER encoding */
|
||||
unsigned long OIDlen;
|
||||
|
||||
/** Init a hash state
|
||||
@param hash The hash to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*init)(hash_state *hash);
|
||||
/** Process a block of data
|
||||
@param hash The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen);
|
||||
/** Produce the digest and store it
|
||||
@param hash The hash state
|
||||
@param out [out] The destination of the digest
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*done)(hash_state *hash, unsigned char *out);
|
||||
/** Self-test
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
|
||||
*/
|
||||
int (*test)(void);
|
||||
|
||||
/* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */
|
||||
int (*hmac_block)(const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
} hash_descriptor[];
|
||||
|
||||
#ifdef LTC_CHC_HASH
|
||||
int chc_register(int cipher);
|
||||
int chc_init(hash_state * md);
|
||||
int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int chc_done(hash_state * md, unsigned char *hash);
|
||||
int chc_test(void);
|
||||
extern const struct ltc_hash_descriptor chc_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_WHIRLPOOL
|
||||
int whirlpool_init(hash_state * md);
|
||||
int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int whirlpool_done(hash_state * md, unsigned char *hash);
|
||||
int whirlpool_test(void);
|
||||
extern const struct ltc_hash_descriptor whirlpool_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA512
|
||||
int sha512_init(hash_state * md);
|
||||
int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int sha512_done(hash_state * md, unsigned char *hash);
|
||||
int sha512_test(void);
|
||||
extern const struct ltc_hash_descriptor sha512_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA384
|
||||
#ifndef LTC_SHA512
|
||||
#error LTC_SHA512 is required for LTC_SHA384
|
||||
#endif
|
||||
int sha384_init(hash_state * md);
|
||||
#define sha384_process sha512_process
|
||||
int sha384_done(hash_state * md, unsigned char *hash);
|
||||
int sha384_test(void);
|
||||
extern const struct ltc_hash_descriptor sha384_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA256
|
||||
int sha256_init(hash_state * md);
|
||||
int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int sha256_done(hash_state * md, unsigned char *hash);
|
||||
int sha256_test(void);
|
||||
extern const struct ltc_hash_descriptor sha256_desc;
|
||||
|
||||
#ifdef LTC_SHA224
|
||||
#ifndef LTC_SHA256
|
||||
#error LTC_SHA256 is required for LTC_SHA224
|
||||
#endif
|
||||
int sha224_init(hash_state * md);
|
||||
#define sha224_process sha256_process
|
||||
int sha224_done(hash_state * md, unsigned char *hash);
|
||||
int sha224_test(void);
|
||||
extern const struct ltc_hash_descriptor sha224_desc;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SHA1
|
||||
int sha1_init(hash_state * md);
|
||||
int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int sha1_done(hash_state * md, unsigned char *hash);
|
||||
int sha1_test(void);
|
||||
extern const struct ltc_hash_descriptor sha1_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD5
|
||||
int md5_init(hash_state * md);
|
||||
int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int md5_done(hash_state * md, unsigned char *hash);
|
||||
int md5_test(void);
|
||||
extern const struct ltc_hash_descriptor md5_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD4
|
||||
int md4_init(hash_state * md);
|
||||
int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int md4_done(hash_state * md, unsigned char *hash);
|
||||
int md4_test(void);
|
||||
extern const struct ltc_hash_descriptor md4_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MD2
|
||||
int md2_init(hash_state * md);
|
||||
int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int md2_done(hash_state * md, unsigned char *hash);
|
||||
int md2_test(void);
|
||||
extern const struct ltc_hash_descriptor md2_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_TIGER
|
||||
int tiger_init(hash_state * md);
|
||||
int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int tiger_done(hash_state * md, unsigned char *hash);
|
||||
int tiger_test(void);
|
||||
extern const struct ltc_hash_descriptor tiger_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD128
|
||||
int rmd128_init(hash_state * md);
|
||||
int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int rmd128_done(hash_state * md, unsigned char *hash);
|
||||
int rmd128_test(void);
|
||||
extern const struct ltc_hash_descriptor rmd128_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD160
|
||||
int rmd160_init(hash_state * md);
|
||||
int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int rmd160_done(hash_state * md, unsigned char *hash);
|
||||
int rmd160_test(void);
|
||||
extern const struct ltc_hash_descriptor rmd160_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD256
|
||||
int rmd256_init(hash_state * md);
|
||||
int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int rmd256_done(hash_state * md, unsigned char *hash);
|
||||
int rmd256_test(void);
|
||||
extern const struct ltc_hash_descriptor rmd256_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RIPEMD320
|
||||
int rmd320_init(hash_state * md);
|
||||
int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen);
|
||||
int rmd320_done(hash_state * md, unsigned char *hash);
|
||||
int rmd320_test(void);
|
||||
extern const struct ltc_hash_descriptor rmd320_desc;
|
||||
#endif
|
||||
|
||||
|
||||
int find_hash(const char *name);
|
||||
int find_hash_id(unsigned char ID);
|
||||
int find_hash_oid(const unsigned long *ID, unsigned long IDlen);
|
||||
int find_hash_any(const char *name, int digestlen);
|
||||
int register_hash(const struct ltc_hash_descriptor *hash);
|
||||
int unregister_hash(const struct ltc_hash_descriptor *hash);
|
||||
int hash_is_valid(int idx);
|
||||
|
||||
LTC_MUTEX_PROTO(ltc_hash_mutex)
|
||||
|
||||
int hash_memory(int hash,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen);
|
||||
int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/* a simple macro for making hash "process" functions */
|
||||
#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \
|
||||
int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \
|
||||
{ \
|
||||
unsigned long n; \
|
||||
int err; \
|
||||
LTC_ARGCHK(md != NULL); \
|
||||
LTC_ARGCHK(in != NULL); \
|
||||
if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \
|
||||
return CRYPT_INVALID_ARG; \
|
||||
} \
|
||||
while (inlen > 0) { \
|
||||
if (md-> state_var .curlen == 0 && inlen >= block_size) { \
|
||||
if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \
|
||||
return err; \
|
||||
} \
|
||||
md-> state_var .length += block_size * 8; \
|
||||
in += block_size; \
|
||||
inlen -= block_size; \
|
||||
} else { \
|
||||
n = MIN(inlen, (block_size - md-> state_var .curlen)); \
|
||||
memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \
|
||||
md-> state_var .curlen += n; \
|
||||
in += n; \
|
||||
inlen -= n; \
|
||||
if (md-> state_var .curlen == block_size) { \
|
||||
if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \
|
||||
return err; \
|
||||
} \
|
||||
md-> state_var .length += 8*block_size; \
|
||||
md-> state_var .curlen = 0; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
return CRYPT_OK; \
|
||||
}
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_hash.h,v $ */
|
||||
/* $Revision: 1.22 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
384
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_mac.h
Normal file
384
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_mac.h
Normal file
@ -0,0 +1,384 @@
|
||||
#ifdef LTC_HMAC
|
||||
typedef struct Hmac_state {
|
||||
hash_state md;
|
||||
int hash;
|
||||
hash_state hashstate;
|
||||
unsigned char *key;
|
||||
} hmac_state;
|
||||
|
||||
int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
|
||||
int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen);
|
||||
int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen);
|
||||
int hmac_test(void);
|
||||
int hmac_memory(int hash,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int hmac_memory_multi(int hash,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int hmac_file(int hash, const char *fname, const unsigned char *key,
|
||||
unsigned long keylen,
|
||||
unsigned char *dst, unsigned long *dstlen);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_OMAC
|
||||
|
||||
typedef struct {
|
||||
int cipher_idx,
|
||||
buflen,
|
||||
blklen;
|
||||
unsigned char block[MAXBLOCKSIZE],
|
||||
prev[MAXBLOCKSIZE],
|
||||
Lu[2][MAXBLOCKSIZE];
|
||||
symmetric_key key;
|
||||
} omac_state;
|
||||
|
||||
int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
|
||||
int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen);
|
||||
int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen);
|
||||
int omac_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int omac_memory_multi(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int omac_file(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const char *filename,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int omac_test(void);
|
||||
#endif /* LTC_OMAC */
|
||||
|
||||
#ifdef LTC_PMAC
|
||||
|
||||
typedef struct {
|
||||
unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */
|
||||
Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */
|
||||
Lr[MAXBLOCKSIZE], /* L * x^-1 */
|
||||
block[MAXBLOCKSIZE], /* currently accumulated block */
|
||||
checksum[MAXBLOCKSIZE]; /* current checksum */
|
||||
|
||||
symmetric_key key; /* scheduled key for cipher */
|
||||
unsigned long block_index; /* index # for current block */
|
||||
int cipher_idx, /* cipher idx */
|
||||
block_len, /* length of block */
|
||||
buflen; /* number of bytes in the buffer */
|
||||
} pmac_state;
|
||||
|
||||
int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen);
|
||||
int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen);
|
||||
int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pmac_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *msg, unsigned long msglen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pmac_memory_multi(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
|
||||
int pmac_file(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const char *filename,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pmac_test(void);
|
||||
|
||||
/* internal functions */
|
||||
int pmac_ntz(unsigned long x);
|
||||
void pmac_shift_xor(pmac_state *pmac);
|
||||
|
||||
#endif /* PMAC */
|
||||
|
||||
#ifdef LTC_EAX_MODE
|
||||
|
||||
#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE))
|
||||
#error LTC_EAX_MODE requires LTC_OMAC and CTR
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned char N[MAXBLOCKSIZE];
|
||||
symmetric_CTR ctr;
|
||||
omac_state headeromac, ctomac;
|
||||
} eax_state;
|
||||
|
||||
int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen);
|
||||
|
||||
int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
|
||||
int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);
|
||||
int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);
|
||||
int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int eax_encrypt_authenticate_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen,
|
||||
const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int eax_decrypt_verify_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen,
|
||||
const unsigned char *ct, unsigned long ctlen,
|
||||
unsigned char *pt,
|
||||
unsigned char *tag, unsigned long taglen,
|
||||
int *stat);
|
||||
|
||||
int eax_test(void);
|
||||
#endif /* EAX MODE */
|
||||
|
||||
#ifdef LTC_OCB_MODE
|
||||
typedef struct {
|
||||
unsigned char L[MAXBLOCKSIZE], /* L value */
|
||||
Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */
|
||||
Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */
|
||||
Lr[MAXBLOCKSIZE], /* L * x^-1 */
|
||||
R[MAXBLOCKSIZE], /* R value */
|
||||
checksum[MAXBLOCKSIZE]; /* current checksum */
|
||||
|
||||
symmetric_key key; /* scheduled key for cipher */
|
||||
unsigned long block_index; /* index # for current block */
|
||||
int cipher, /* cipher idx */
|
||||
block_len; /* length of block */
|
||||
} ocb_state;
|
||||
|
||||
int ocb_init(ocb_state *ocb, int cipher,
|
||||
const unsigned char *key, unsigned long keylen, const unsigned char *nonce);
|
||||
|
||||
int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct);
|
||||
int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt);
|
||||
|
||||
int ocb_done_encrypt(ocb_state *ocb,
|
||||
const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int ocb_done_decrypt(ocb_state *ocb,
|
||||
const unsigned char *ct, unsigned long ctlen,
|
||||
unsigned char *pt,
|
||||
const unsigned char *tag, unsigned long taglen, int *stat);
|
||||
|
||||
int ocb_encrypt_authenticate_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce,
|
||||
const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int ocb_decrypt_verify_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *nonce,
|
||||
const unsigned char *ct, unsigned long ctlen,
|
||||
unsigned char *pt,
|
||||
const unsigned char *tag, unsigned long taglen,
|
||||
int *stat);
|
||||
|
||||
int ocb_test(void);
|
||||
|
||||
/* internal functions */
|
||||
void ocb_shift_xor(ocb_state *ocb, unsigned char *Z);
|
||||
int ocb_ntz(unsigned long x);
|
||||
int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode);
|
||||
|
||||
#endif /* LTC_OCB_MODE */
|
||||
|
||||
#ifdef LTC_CCM_MODE
|
||||
|
||||
#define CCM_ENCRYPT 0
|
||||
#define CCM_DECRYPT 1
|
||||
|
||||
int ccm_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
symmetric_key *uskey,
|
||||
const unsigned char *nonce, unsigned long noncelen,
|
||||
const unsigned char *header, unsigned long headerlen,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
|
||||
int ccm_test(void);
|
||||
|
||||
#endif /* LTC_CCM_MODE */
|
||||
|
||||
#if defined(LRW_MODE) || defined(LTC_GCM_MODE)
|
||||
void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c);
|
||||
#endif
|
||||
|
||||
|
||||
/* table shared between GCM and LRW */
|
||||
#if defined(LTC_GCM_TABLES) || defined(LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST))
|
||||
extern const unsigned char gcm_shift_table[];
|
||||
#endif
|
||||
|
||||
#ifdef LTC_GCM_MODE
|
||||
|
||||
#define GCM_ENCRYPT 0
|
||||
#define GCM_DECRYPT 1
|
||||
|
||||
#define LTC_GCM_MODE_IV 0
|
||||
#define LTC_GCM_MODE_AAD 1
|
||||
#define LTC_GCM_MODE_TEXT 2
|
||||
|
||||
typedef struct {
|
||||
symmetric_key K;
|
||||
unsigned char H[16], /* multiplier */
|
||||
X[16], /* accumulator */
|
||||
Y[16], /* counter */
|
||||
Y_0[16], /* initial counter */
|
||||
buf[16]; /* buffer for stuff */
|
||||
|
||||
int cipher, /* which cipher */
|
||||
ivmode, /* Which mode is the IV in? */
|
||||
mode, /* mode the GCM code is in */
|
||||
buflen; /* length of data in buf */
|
||||
|
||||
ulong64 totlen, /* 64-bit counter used for IV and AAD */
|
||||
pttotlen; /* 64-bit counter for the PT */
|
||||
|
||||
#ifdef LTC_GCM_TABLES
|
||||
unsigned char PC[16][256][16] /* 16 tables of 8x128 */
|
||||
#ifdef LTC_GCM_TABLES_SSE2
|
||||
__attribute__ ((aligned (16)))
|
||||
#endif
|
||||
;
|
||||
#endif
|
||||
} gcm_state;
|
||||
|
||||
void gcm_mult_h(gcm_state *gcm, unsigned char *I);
|
||||
|
||||
int gcm_init(gcm_state *gcm, int cipher,
|
||||
const unsigned char *key, int keylen);
|
||||
|
||||
int gcm_reset(gcm_state *gcm);
|
||||
|
||||
int gcm_add_iv(gcm_state *gcm,
|
||||
const unsigned char *IV, unsigned long IVlen);
|
||||
|
||||
int gcm_add_aad(gcm_state *gcm,
|
||||
const unsigned char *adata, unsigned long adatalen);
|
||||
|
||||
int gcm_process(gcm_state *gcm,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
int direction);
|
||||
|
||||
int gcm_done(gcm_state *gcm,
|
||||
unsigned char *tag, unsigned long *taglen);
|
||||
|
||||
int gcm_memory( int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *IV, unsigned long IVlen,
|
||||
const unsigned char *adata, unsigned long adatalen,
|
||||
unsigned char *pt, unsigned long ptlen,
|
||||
unsigned char *ct,
|
||||
unsigned char *tag, unsigned long *taglen,
|
||||
int direction);
|
||||
int gcm_test(void);
|
||||
|
||||
#endif /* LTC_GCM_MODE */
|
||||
|
||||
#ifdef LTC_PELICAN
|
||||
|
||||
typedef struct pelican_state
|
||||
{
|
||||
symmetric_key K;
|
||||
unsigned char state[16];
|
||||
int buflen;
|
||||
} pelican_state;
|
||||
|
||||
int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen);
|
||||
int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen);
|
||||
int pelican_done(pelican_state *pelmac, unsigned char *out);
|
||||
int pelican_test(void);
|
||||
|
||||
int pelican_memory(const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_XCBC
|
||||
|
||||
/* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */
|
||||
#define LTC_XCBC_PURE 0x8000UL
|
||||
|
||||
typedef struct {
|
||||
unsigned char K[3][MAXBLOCKSIZE],
|
||||
IV[MAXBLOCKSIZE];
|
||||
|
||||
symmetric_key key;
|
||||
|
||||
int cipher,
|
||||
buflen,
|
||||
blocksize;
|
||||
} xcbc_state;
|
||||
|
||||
int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen);
|
||||
int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen);
|
||||
int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen);
|
||||
int xcbc_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int xcbc_memory_multi(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int xcbc_file(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const char *filename,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int xcbc_test(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_F9_MODE
|
||||
|
||||
typedef struct {
|
||||
unsigned char akey[MAXBLOCKSIZE],
|
||||
ACC[MAXBLOCKSIZE],
|
||||
IV[MAXBLOCKSIZE];
|
||||
|
||||
symmetric_key key;
|
||||
|
||||
int cipher,
|
||||
buflen,
|
||||
keylen,
|
||||
blocksize;
|
||||
} f9_state;
|
||||
|
||||
int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen);
|
||||
int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen);
|
||||
int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen);
|
||||
int f9_memory(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int f9_memory_multi(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *in, unsigned long inlen, ...);
|
||||
int f9_file(int cipher,
|
||||
const unsigned char *key, unsigned long keylen,
|
||||
const char *filename,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int f9_test(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_mac.h,v $ */
|
||||
/* $Revision: 1.23 $ */
|
||||
/* $Date: 2007/05/12 14:37:41 $ */
|
||||
@ -0,0 +1,424 @@
|
||||
/* fix for MSVC ...evil! */
|
||||
#ifdef _MSC_VER
|
||||
#define CONST64(n) n ## ui64
|
||||
typedef unsigned __int64 ulong64;
|
||||
#else
|
||||
#define CONST64(n) n ## ULL
|
||||
typedef unsigned long long ulong64;
|
||||
#endif
|
||||
|
||||
/* this is the "32-bit at least" data type
|
||||
* Re-define it to suit your platform but it must be at least 32-bits
|
||||
*/
|
||||
#if defined(__x86_64__) || (defined(__sparc__) && defined(__arch64__))
|
||||
typedef unsigned ulong32;
|
||||
#else
|
||||
typedef unsigned long ulong32;
|
||||
#endif
|
||||
|
||||
/* ---- HELPER MACROS ---- */
|
||||
#ifdef ENDIAN_NEUTRAL
|
||||
|
||||
#define STORE32L(x, y) \
|
||||
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD32L(x, y) \
|
||||
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
|
||||
((unsigned long)((y)[2] & 255)<<16) | \
|
||||
((unsigned long)((y)[1] & 255)<<8) | \
|
||||
((unsigned long)((y)[0] & 255)); }
|
||||
|
||||
#define STORE64L(x, y) \
|
||||
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64L(x, y) \
|
||||
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
|
||||
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
|
||||
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
|
||||
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
|
||||
((unsigned long)((y)[1] & 255)<<16) | \
|
||||
((unsigned long)((y)[2] & 255)<<8) | \
|
||||
((unsigned long)((y)[3] & 255)); }
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
|
||||
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
|
||||
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
|
||||
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
|
||||
|
||||
#endif /* ENDIAN_NEUTRAL */
|
||||
|
||||
#ifdef ENDIAN_LITTLE
|
||||
|
||||
#if !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
asm __volatile__ ( \
|
||||
"bswapl %0 \n\t" \
|
||||
"movl %0,(%1)\n\t" \
|
||||
"bswapl %0 \n\t" \
|
||||
::"r"(x), "r"(y));
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
asm __volatile__ ( \
|
||||
"movl (%1),%0\n\t" \
|
||||
"bswapl %0\n\t" \
|
||||
:"=r"(x): "r"(y));
|
||||
|
||||
#else
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
|
||||
((unsigned long)((y)[1] & 255)<<16) | \
|
||||
((unsigned long)((y)[2] & 255)<<8) | \
|
||||
((unsigned long)((y)[3] & 255)); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* x86_64 processor */
|
||||
#if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
asm __volatile__ ( \
|
||||
"bswapq %0 \n\t" \
|
||||
"movq %0,(%1)\n\t" \
|
||||
"bswapq %0 \n\t" \
|
||||
::"r"(x), "r"(y));
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
asm __volatile__ ( \
|
||||
"movq (%1),%0\n\t" \
|
||||
"bswapq %0\n\t" \
|
||||
:"=r"(x): "r"(y));
|
||||
|
||||
#else
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
|
||||
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
|
||||
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
|
||||
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ENDIAN_32BITWORD
|
||||
|
||||
#define STORE32L(x, y) \
|
||||
{ ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
|
||||
|
||||
#define LOAD32L(x, y) \
|
||||
XMEMCPY(&(x), y, 4);
|
||||
|
||||
#define STORE64L(x, y) \
|
||||
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64L(x, y) \
|
||||
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
|
||||
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
|
||||
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
|
||||
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
|
||||
|
||||
#else /* 64-bit words then */
|
||||
|
||||
#define STORE32L(x, y) \
|
||||
{ ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
|
||||
|
||||
#define LOAD32L(x, y) \
|
||||
{ XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }
|
||||
|
||||
#define STORE64L(x, y) \
|
||||
{ ulong64 __t = (x); XMEMCPY(y, &__t, 8); }
|
||||
|
||||
#define LOAD64L(x, y) \
|
||||
{ XMEMCPY(&(x), y, 8); }
|
||||
|
||||
#endif /* ENDIAN_64BITWORD */
|
||||
|
||||
#endif /* ENDIAN_LITTLE */
|
||||
|
||||
#ifdef ENDIAN_BIG
|
||||
#define STORE32L(x, y) \
|
||||
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD32L(x, y) \
|
||||
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
|
||||
((unsigned long)((y)[2] & 255)<<16) | \
|
||||
((unsigned long)((y)[1] & 255)<<8) | \
|
||||
((unsigned long)((y)[0] & 255)); }
|
||||
|
||||
#define STORE64L(x, y) \
|
||||
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64L(x, y) \
|
||||
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
|
||||
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
|
||||
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
|
||||
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
|
||||
|
||||
#ifdef ENDIAN_32BITWORD
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
{ ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
XMEMCPY(&(x), y, 4);
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
|
||||
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
|
||||
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
|
||||
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
|
||||
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
|
||||
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
|
||||
(((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); }
|
||||
|
||||
#else /* 64-bit words then */
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
{ ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
{ XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
{ ulong64 __t = (x); XMEMCPY(y, &__t, 8); }
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
{ XMEMCPY(&(x), y, 8); }
|
||||
|
||||
#endif /* ENDIAN_64BITWORD */
|
||||
#endif /* ENDIAN_BIG */
|
||||
|
||||
#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
|
||||
((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
|
||||
|
||||
|
||||
/* 32-bit Rotates */
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
/* instrinsic rotate */
|
||||
#include <stdlib.h>
|
||||
#pragma intrinsic(_lrotr,_lrotl)
|
||||
#define ROR(x,n) _lrotr(x,n)
|
||||
#define ROL(x,n) _lrotl(x,n)
|
||||
#define RORc(x,n) _lrotr(x,n)
|
||||
#define ROLc(x,n) _lrotl(x,n)
|
||||
|
||||
#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
|
||||
|
||||
static inline unsigned ROL(unsigned word, int i)
|
||||
{
|
||||
asm ("roll %%cl,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"c" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned ROR(unsigned word, int i)
|
||||
{
|
||||
asm ("rorl %%cl,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"c" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifndef LTC_NO_ROLC
|
||||
|
||||
static inline unsigned ROLc(unsigned word, const int i)
|
||||
{
|
||||
asm ("roll %2,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"I" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned RORc(unsigned word, const int i)
|
||||
{
|
||||
asm ("rorl %2,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"I" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define ROLc ROL
|
||||
#define RORc ROR
|
||||
|
||||
#endif
|
||||
|
||||
#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
|
||||
|
||||
static inline unsigned ROL(unsigned word, int i)
|
||||
{
|
||||
asm ("rotlw %0,%0,%2"
|
||||
:"=r" (word)
|
||||
:"0" (word),"r" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned ROR(unsigned word, int i)
|
||||
{
|
||||
asm ("rotlw %0,%0,%2"
|
||||
:"=r" (word)
|
||||
:"0" (word),"r" (32-i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifndef LTC_NO_ROLC
|
||||
|
||||
static inline unsigned ROLc(unsigned word, const int i)
|
||||
{
|
||||
asm ("rotlwi %0,%0,%2"
|
||||
:"=r" (word)
|
||||
:"0" (word),"I" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned RORc(unsigned word, const int i)
|
||||
{
|
||||
asm ("rotrwi %0,%0,%2"
|
||||
:"=r" (word)
|
||||
:"0" (word),"I" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define ROLc ROL
|
||||
#define RORc ROR
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* rotates the hard way */
|
||||
#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* 64-bit Rotates */
|
||||
#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(LTC_NO_ASM)
|
||||
|
||||
static inline unsigned long ROL64(unsigned long word, int i)
|
||||
{
|
||||
asm("rolq %%cl,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"c" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned long ROR64(unsigned long word, int i)
|
||||
{
|
||||
asm("rorq %%cl,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"c" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifndef LTC_NO_ROLC
|
||||
|
||||
static inline unsigned long ROL64c(unsigned long word, const int i)
|
||||
{
|
||||
asm("rolq %2,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"J" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
static inline unsigned long ROR64c(unsigned long word, const int i)
|
||||
{
|
||||
asm("rorq %2,%0"
|
||||
:"=r" (word)
|
||||
:"0" (word),"J" (i));
|
||||
return word;
|
||||
}
|
||||
|
||||
#else /* LTC_NO_ROLC */
|
||||
|
||||
#define ROL64c ROL64
|
||||
#define ROR64c ROR64
|
||||
|
||||
#endif
|
||||
|
||||
#else /* Not x86_64 */
|
||||
|
||||
#define ROL64(x, y) \
|
||||
( (((x)<<((ulong64)(y)&63)) | \
|
||||
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#define ROR64(x, y) \
|
||||
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
|
||||
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#define ROL64c(x, y) \
|
||||
( (((x)<<((ulong64)(y)&63)) | \
|
||||
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#define ROR64c(x, y) \
|
||||
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
|
||||
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(x, y) ( ((x)>(y))?(x):(y) )
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
|
||||
#endif
|
||||
|
||||
/* extract a byte portably */
|
||||
#ifdef _MSC_VER
|
||||
#define byte(x, n) ((unsigned char)((x) >> (8 * (n))))
|
||||
#else
|
||||
#define byte(x, n) (((x) >> (8 * (n))) & 255)
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_macros.h,v $ */
|
||||
/* $Revision: 1.15 $ */
|
||||
/* $Date: 2006/11/29 23:43:57 $ */
|
||||
500
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_math.h
Normal file
500
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_math.h
Normal file
@ -0,0 +1,500 @@
|
||||
/** math functions **/
|
||||
|
||||
#define LTC_MP_LT -1
|
||||
#define LTC_MP_EQ 0
|
||||
#define LTC_MP_GT 1
|
||||
|
||||
#define LTC_MP_NO 0
|
||||
#define LTC_MP_YES 1
|
||||
|
||||
#ifndef LTC_MECC
|
||||
typedef void ecc_point;
|
||||
#endif
|
||||
|
||||
#ifndef LTC_MRSA
|
||||
typedef void rsa_key;
|
||||
#endif
|
||||
|
||||
/** math descriptor */
|
||||
typedef struct {
|
||||
/** Name of the math provider */
|
||||
char *name;
|
||||
|
||||
/** Bits per digit, amount of bits must fit in an unsigned long */
|
||||
int bits_per_digit;
|
||||
|
||||
/* ---- init/deinit functions ---- */
|
||||
|
||||
/** initialize a bignum
|
||||
@param a The number to initialize
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*init)(void **a);
|
||||
|
||||
/** init copy
|
||||
@param dst The number to initialize and write to
|
||||
@param src The number to copy from
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*init_copy)(void **dst, void *src);
|
||||
|
||||
/** deinit
|
||||
@param a The number to free
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
void (*deinit)(void *a);
|
||||
|
||||
/* ---- data movement ---- */
|
||||
|
||||
/** negate
|
||||
@param src The number to negate
|
||||
@param dst The destination
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*neg)(void *src, void *dst);
|
||||
|
||||
/** copy
|
||||
@param src The number to copy from
|
||||
@param dst The number to write to
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*copy)(void *src, void *dst);
|
||||
|
||||
/* ---- trivial low level functions ---- */
|
||||
|
||||
/** set small constant
|
||||
@param a Number to write to
|
||||
@param n Source upto bits_per_digit (actually meant for very small constants)
|
||||
@return CRYPT_OK on succcess
|
||||
*/
|
||||
int (*set_int)(void *a, unsigned long n);
|
||||
|
||||
/** get small constant
|
||||
@param a Number to read, only fetches upto bits_per_digit from the number
|
||||
@return The lower bits_per_digit of the integer (unsigned)
|
||||
*/
|
||||
unsigned long (*get_int)(void *a);
|
||||
|
||||
/** get digit n
|
||||
@param a The number to read from
|
||||
@param n The number of the digit to fetch
|
||||
@return The bits_per_digit sized n'th digit of a
|
||||
*/
|
||||
unsigned long (*get_digit)(void *a, int n);
|
||||
|
||||
/** Get the number of digits that represent the number
|
||||
@param a The number to count
|
||||
@return The number of digits used to represent the number
|
||||
*/
|
||||
int (*get_digit_count)(void *a);
|
||||
|
||||
/** compare two integers
|
||||
@param a The left side integer
|
||||
@param b The right side integer
|
||||
@return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison)
|
||||
*/
|
||||
int (*compare)(void *a, void *b);
|
||||
|
||||
/** compare against int
|
||||
@param a The left side integer
|
||||
@param b The right side integer (upto bits_per_digit)
|
||||
@return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison)
|
||||
*/
|
||||
int (*compare_d)(void *a, unsigned long n);
|
||||
|
||||
/** Count the number of bits used to represent the integer
|
||||
@param a The integer to count
|
||||
@return The number of bits required to represent the integer
|
||||
*/
|
||||
int (*count_bits)(void * a);
|
||||
|
||||
/** Count the number of LSB bits which are zero
|
||||
@param a The integer to count
|
||||
@return The number of contiguous zero LSB bits
|
||||
*/
|
||||
int (*count_lsb_bits)(void *a);
|
||||
|
||||
/** Compute a power of two
|
||||
@param a The integer to store the power in
|
||||
@param n The power of two you want to store (a = 2^n)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*twoexpt)(void *a , int n);
|
||||
|
||||
/* ---- radix conversions ---- */
|
||||
|
||||
/** read ascii string
|
||||
@param a The integer to store into
|
||||
@param str The string to read
|
||||
@param radix The radix the integer has been represented in (2-64)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*read_radix)(void *a, const char *str, int radix);
|
||||
|
||||
/** write number to string
|
||||
@param a The integer to store
|
||||
@param str The destination for the string
|
||||
@param radix The radix the integer is to be represented in (2-64)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*write_radix)(void *a, char *str, int radix);
|
||||
|
||||
/** get size as unsigned char string
|
||||
@param a The integer to get the size (when stored in array of octets)
|
||||
@return The length of the integer
|
||||
*/
|
||||
unsigned long (*unsigned_size)(void *a);
|
||||
|
||||
/** store an integer as an array of octets
|
||||
@param src The integer to store
|
||||
@param dst The buffer to store the integer in
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*unsigned_write)(void *src, unsigned char *dst);
|
||||
|
||||
/** read an array of octets and store as integer
|
||||
@param dst The integer to load
|
||||
@param src The array of octets
|
||||
@param len The number of octets
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*unsigned_read)(void *dst, unsigned char *src, unsigned long len);
|
||||
|
||||
/* ---- basic math ---- */
|
||||
|
||||
/** add two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer
|
||||
@param c The destination of "a + b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*add)(void *a, void *b, void *c);
|
||||
|
||||
|
||||
/** add two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer (single digit of upto bits_per_digit in length)
|
||||
@param c The destination of "a + b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*addi)(void *a, unsigned long b, void *c);
|
||||
|
||||
/** subtract two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer
|
||||
@param c The destination of "a - b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*sub)(void *a, void *b, void *c);
|
||||
|
||||
/** subtract two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer (single digit of upto bits_per_digit in length)
|
||||
@param c The destination of "a - b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*subi)(void *a, unsigned long b, void *c);
|
||||
|
||||
/** multiply two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer (single digit of upto bits_per_digit in length)
|
||||
@param c The destination of "a * b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*mul)(void *a, void *b, void *c);
|
||||
|
||||
/** multiply two integers
|
||||
@param a The first source integer
|
||||
@param b The second source integer (single digit of upto bits_per_digit in length)
|
||||
@param c The destination of "a * b"
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*muli)(void *a, unsigned long b, void *c);
|
||||
|
||||
/** Square an integer
|
||||
@param a The integer to square
|
||||
@param b The destination
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*sqr)(void *a, void *b);
|
||||
|
||||
/** Divide an integer
|
||||
@param a The dividend
|
||||
@param b The divisor
|
||||
@param c The quotient (can be NULL to signify don't care)
|
||||
@param d The remainder (can be NULL to signify don't care)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*mpdiv)(void *a, void *b, void *c, void *d);
|
||||
|
||||
/** divide by two
|
||||
@param a The integer to divide (shift right)
|
||||
@param b The destination
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*div_2)(void *a, void *b);
|
||||
|
||||
/** Get remainder (small value)
|
||||
@param a The integer to reduce
|
||||
@param b The modulus (upto bits_per_digit in length)
|
||||
@param c The destination for the residue
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*modi)(void *a, unsigned long b, unsigned long *c);
|
||||
|
||||
/** gcd
|
||||
@param a The first integer
|
||||
@param b The second integer
|
||||
@param c The destination for (a, b)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*gcd)(void *a, void *b, void *c);
|
||||
|
||||
/** lcm
|
||||
@param a The first integer
|
||||
@param b The second integer
|
||||
@param c The destination for [a, b]
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*lcm)(void *a, void *b, void *c);
|
||||
|
||||
/** Modular multiplication
|
||||
@param a The first source
|
||||
@param b The second source
|
||||
@param c The modulus
|
||||
@param d The destination (a*b mod c)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*mulmod)(void *a, void *b, void *c, void *d);
|
||||
|
||||
/** Modular squaring
|
||||
@param a The first source
|
||||
@param b The modulus
|
||||
@param c The destination (a*a mod b)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*sqrmod)(void *a, void *b, void *c);
|
||||
|
||||
/** Modular inversion
|
||||
@param a The value to invert
|
||||
@param b The modulus
|
||||
@param c The destination (1/a mod b)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*invmod)(void *, void *, void *);
|
||||
|
||||
/* ---- reduction ---- */
|
||||
|
||||
/** setup montgomery
|
||||
@param a The modulus
|
||||
@param b The destination for the reduction digit
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*montgomery_setup)(void *a, void **b);
|
||||
|
||||
/** get normalization value
|
||||
@param a The destination for the normalization value
|
||||
@param b The modulus
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*montgomery_normalization)(void *a, void *b);
|
||||
|
||||
/** reduce a number
|
||||
@param a The number [and dest] to reduce
|
||||
@param b The modulus
|
||||
@param c The value "b" from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*montgomery_reduce)(void *a, void *b, void *c);
|
||||
|
||||
/** clean up (frees memory)
|
||||
@param a The value "b" from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
void (*montgomery_deinit)(void *a);
|
||||
|
||||
/* ---- exponentiation ---- */
|
||||
|
||||
/** Modular exponentiation
|
||||
@param a The base integer
|
||||
@param b The power (can be negative) integer
|
||||
@param c The modulus integer
|
||||
@param d The destination
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*exptmod)(void *a, void *b, void *c, void *d);
|
||||
|
||||
/** Primality testing
|
||||
@param a The integer to test
|
||||
@param b The destination of the result (FP_YES if prime)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*isprime)(void *a, int *b);
|
||||
|
||||
/* ---- (optional) ecc point math ---- */
|
||||
|
||||
/** ECC GF(p) point multiplication (from the NIST curves)
|
||||
@param k The integer to multiply the point by
|
||||
@param G The point to multiply
|
||||
@param R The destination for kG
|
||||
@param modulus The modulus for the field
|
||||
@param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only)
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
|
||||
|
||||
/** ECC GF(p) point addition
|
||||
@param P The first point
|
||||
@param Q The second point
|
||||
@param R The destination of P + Q
|
||||
@param modulus The modulus
|
||||
@param mp The "b" value from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
|
||||
|
||||
/** ECC GF(p) point double
|
||||
@param P The first point
|
||||
@param R The destination of 2P
|
||||
@param modulus The modulus
|
||||
@param mp The "b" value from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp);
|
||||
|
||||
/** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1)
|
||||
@param P The point to map
|
||||
@param modulus The modulus
|
||||
@param mp The "b" value from montgomery_setup()
|
||||
@return CRYPT_OK on success
|
||||
@remark The mapping can be different but keep in mind a ecc_point only has three
|
||||
integers (x,y,z) so if you use a different mapping you have to make it fit.
|
||||
*/
|
||||
int (*ecc_map)(ecc_point *P, void *modulus, void *mp);
|
||||
|
||||
/** Computes kA*A + kB*B = C using Shamir's Trick
|
||||
@param A First point to multiply
|
||||
@param kA What to multiple A by
|
||||
@param B Second point to multiply
|
||||
@param kB What to multiple B by
|
||||
@param C [out] Destination point (can overlap with A or B
|
||||
@param modulus Modulus for curve
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*ecc_mul2add)(ecc_point *A, void *kA,
|
||||
ecc_point *B, void *kB,
|
||||
ecc_point *C,
|
||||
void *modulus);
|
||||
|
||||
/* ---- (optional) rsa optimized math (for internal CRT) ---- */
|
||||
|
||||
/** RSA Key Generation
|
||||
@param prng An active PRNG state
|
||||
@param wprng The index of the PRNG desired
|
||||
@param size The size of the modulus (key size) desired (octets)
|
||||
@param e The "e" value (public key). e==65537 is a good choice
|
||||
@param key [out] Destination of a newly created private key pair
|
||||
@return CRYPT_OK if successful, upon error all allocated ram is freed
|
||||
*/
|
||||
int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key);
|
||||
|
||||
|
||||
/** RSA exponentiation
|
||||
@param in The octet array representing the base
|
||||
@param inlen The length of the input
|
||||
@param out The destination (to be stored in an octet array format)
|
||||
@param outlen The length of the output buffer and the resulting size (zero padded to the size of the modulus)
|
||||
@param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA
|
||||
@param key The RSA key to use
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int (*rsa_me)(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen, int which,
|
||||
rsa_key *key);
|
||||
} ltc_math_descriptor;
|
||||
|
||||
extern ltc_math_descriptor ltc_mp;
|
||||
|
||||
int ltc_init_multi(void **a, ...);
|
||||
void ltc_deinit_multi(void *a, ...);
|
||||
|
||||
#ifdef LTM_DESC
|
||||
extern const ltc_math_descriptor ltm_desc;
|
||||
#endif
|
||||
|
||||
#ifdef TFM_DESC
|
||||
extern const ltc_math_descriptor tfm_desc;
|
||||
#endif
|
||||
|
||||
#ifdef GMP_DESC
|
||||
extern const ltc_math_descriptor gmp_desc;
|
||||
#endif
|
||||
|
||||
#if !defined(DESC_DEF_ONLY) && defined(LTC_SOURCE)
|
||||
|
||||
#define MP_DIGIT_BIT ltc_mp.bits_per_digit
|
||||
|
||||
/* some handy macros */
|
||||
#define mp_init(a) ltc_mp.init(a)
|
||||
#define mp_init_multi ltc_init_multi
|
||||
#define mp_clear(a) ltc_mp.deinit(a)
|
||||
#define mp_clear_multi ltc_deinit_multi
|
||||
#define mp_init_copy(a, b) ltc_mp.init_copy(a, b)
|
||||
|
||||
#define mp_neg(a, b) ltc_mp.neg(a, b)
|
||||
#define mp_copy(a, b) ltc_mp.copy(a, b)
|
||||
|
||||
#define mp_set(a, b) ltc_mp.set_int(a, b)
|
||||
#define mp_set_int(a, b) ltc_mp.set_int(a, b)
|
||||
#define mp_get_int(a) ltc_mp.get_int(a)
|
||||
#define mp_get_digit(a, n) ltc_mp.get_digit(a, n)
|
||||
#define mp_get_digit_count(a) ltc_mp.get_digit_count(a)
|
||||
#define mp_cmp(a, b) ltc_mp.compare(a, b)
|
||||
#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b)
|
||||
#define mp_count_bits(a) ltc_mp.count_bits(a)
|
||||
#define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a)
|
||||
#define mp_2expt(a, b) ltc_mp.twoexpt(a, b)
|
||||
|
||||
#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c)
|
||||
#define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c)
|
||||
#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a)
|
||||
#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b)
|
||||
#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
|
||||
|
||||
#define mp_add(a, b, c) ltc_mp.add(a, b, c)
|
||||
#define mp_add_d(a, b, c) ltc_mp.addi(a, b, c)
|
||||
#define mp_sub(a, b, c) ltc_mp.sub(a, b, c)
|
||||
#define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c)
|
||||
#define mp_mul(a, b, c) ltc_mp.mul(a, b, c)
|
||||
#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c)
|
||||
#define mp_sqr(a, b) ltc_mp.sqr(a, b)
|
||||
#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d)
|
||||
#define mp_div_2(a, b) ltc_mp.div_2(a, b)
|
||||
#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c)
|
||||
#define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c)
|
||||
#define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c)
|
||||
#define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c)
|
||||
|
||||
#define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d)
|
||||
#define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c)
|
||||
#define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c)
|
||||
|
||||
#define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b)
|
||||
#define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b)
|
||||
#define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c)
|
||||
#define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a)
|
||||
|
||||
#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d)
|
||||
#define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, c)
|
||||
|
||||
#define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO)
|
||||
#define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO)
|
||||
#define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0);
|
||||
|
||||
#define mp_tohex(a, b) mp_toradix(a, b, 16)
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_math.h,v $ */
|
||||
/* $Revision: 1.44 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
@ -0,0 +1,23 @@
|
||||
/* ---- LTC_BASE64 Routines ---- */
|
||||
#ifdef LTC_BASE64
|
||||
int base64_encode(const unsigned char *in, unsigned long len,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int base64_decode(const unsigned char *in, unsigned long len,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
#endif
|
||||
|
||||
/* ---- MEM routines ---- */
|
||||
void zeromem(void *dst, size_t len);
|
||||
void burn_stack(unsigned long len);
|
||||
|
||||
const char *error_to_string(int err);
|
||||
|
||||
extern const char *crypt_build_settings;
|
||||
|
||||
/* ---- HMM ---- */
|
||||
int crypt_fsa(void *mp, ...);
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_misc.h,v $ */
|
||||
/* $Revision: 1.5 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
558
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_pk.h
Normal file
558
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_pk.h
Normal file
@ -0,0 +1,558 @@
|
||||
/* ---- NUMBER THEORY ---- */
|
||||
|
||||
enum {
|
||||
PK_PUBLIC=0,
|
||||
PK_PRIVATE=1
|
||||
};
|
||||
|
||||
int rand_prime(void *N, long len, prng_state *prng, int wprng);
|
||||
|
||||
/* ---- RSA ---- */
|
||||
#ifdef LTC_MRSA
|
||||
|
||||
/* Min and Max RSA key sizes (in bits) */
|
||||
#define MIN_RSA_SIZE 1024
|
||||
#define MAX_RSA_SIZE 4096
|
||||
|
||||
/** RSA LTC_PKCS style key */
|
||||
typedef struct Rsa_key {
|
||||
/** Type of key, PK_PRIVATE or PK_PUBLIC */
|
||||
int type;
|
||||
/** The public exponent */
|
||||
void *e;
|
||||
/** The private exponent */
|
||||
void *d;
|
||||
/** The modulus */
|
||||
void *N;
|
||||
/** The p factor of N */
|
||||
void *p;
|
||||
/** The q factor of N */
|
||||
void *q;
|
||||
/** The 1/q mod p CRT param */
|
||||
void *qP;
|
||||
/** The d mod (p - 1) CRT param */
|
||||
void *dP;
|
||||
/** The d mod (q - 1) CRT param */
|
||||
void *dQ;
|
||||
} rsa_key;
|
||||
|
||||
int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
|
||||
|
||||
int rsa_exptmod(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen, int which,
|
||||
rsa_key *key);
|
||||
|
||||
void rsa_free(rsa_key *key);
|
||||
|
||||
/* These use LTC_PKCS #1 v2.0 padding */
|
||||
#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, _key) \
|
||||
rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, LTC_LTC_PKCS_1_OAEP, _key)
|
||||
|
||||
#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _stat, _key) \
|
||||
rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_LTC_PKCS_1_OAEP, _stat, _key)
|
||||
|
||||
#define rsa_sign_hash(_in, _inlen, _out, _outlen, _prng, _prng_idx, _hash_idx, _saltlen, _key) \
|
||||
rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _prng, _prng_idx, _hash_idx, _saltlen, _key)
|
||||
|
||||
#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_idx, _saltlen, _stat, _key) \
|
||||
rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_idx, _saltlen, _stat, _key)
|
||||
|
||||
/* These can be switched between LTC_PKCS #1 v2.x and LTC_PKCS #1 v1.5 paddings */
|
||||
int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key);
|
||||
|
||||
int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
int hash_idx, int padding,
|
||||
int *stat, rsa_key *key);
|
||||
|
||||
int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
int padding,
|
||||
prng_state *prng, int prng_idx,
|
||||
int hash_idx, unsigned long saltlen,
|
||||
rsa_key *key);
|
||||
|
||||
int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int padding,
|
||||
int hash_idx, unsigned long saltlen,
|
||||
int *stat, rsa_key *key);
|
||||
|
||||
/* LTC_PKCS #1 import/export */
|
||||
int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);
|
||||
int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
|
||||
|
||||
/* Ladik: Added for verifying Blizzard strong signature verification */
|
||||
int rsa_verify_simple(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat,
|
||||
rsa_key *key);
|
||||
|
||||
#endif
|
||||
|
||||
/* ---- Katja ---- */
|
||||
#ifdef MKAT
|
||||
|
||||
/* Min and Max KAT key sizes (in bits) */
|
||||
#define MIN_KAT_SIZE 1024
|
||||
#define MAX_KAT_SIZE 4096
|
||||
|
||||
/** Katja LTC_PKCS style key */
|
||||
typedef struct KAT_key {
|
||||
/** Type of key, PK_PRIVATE or PK_PUBLIC */
|
||||
int type;
|
||||
/** The private exponent */
|
||||
void *d;
|
||||
/** The modulus */
|
||||
void *N;
|
||||
/** The p factor of N */
|
||||
void *p;
|
||||
/** The q factor of N */
|
||||
void *q;
|
||||
/** The 1/q mod p CRT param */
|
||||
void *qP;
|
||||
/** The d mod (p - 1) CRT param */
|
||||
void *dP;
|
||||
/** The d mod (q - 1) CRT param */
|
||||
void *dQ;
|
||||
/** The pq param */
|
||||
void *pq;
|
||||
} katja_key;
|
||||
|
||||
int katja_make_key(prng_state *prng, int wprng, int size, katja_key *key);
|
||||
|
||||
int katja_exptmod(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen, int which,
|
||||
katja_key *key);
|
||||
|
||||
void katja_free(katja_key *key);
|
||||
|
||||
/* These use LTC_PKCS #1 v2.0 padding */
|
||||
int katja_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
prng_state *prng, int prng_idx, int hash_idx, katja_key *key);
|
||||
|
||||
int katja_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
int hash_idx, int *stat,
|
||||
katja_key *key);
|
||||
|
||||
/* LTC_PKCS #1 import/export */
|
||||
int katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key *key);
|
||||
int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key);
|
||||
|
||||
#endif
|
||||
|
||||
/* ---- ECC Routines ---- */
|
||||
#ifdef LTC_MECC
|
||||
|
||||
/* size of our temp buffers for exported keys */
|
||||
#define ECC_BUF_SIZE 256
|
||||
|
||||
/* max private key size */
|
||||
#define ECC_MAXSIZE 66
|
||||
|
||||
/** Structure defines a NIST GF(p) curve */
|
||||
typedef struct {
|
||||
/** The size of the curve in octets */
|
||||
int size;
|
||||
|
||||
/** name of curve */
|
||||
char *name;
|
||||
|
||||
/** The prime that defines the field the curve is in (encoded in hex) */
|
||||
char *prime;
|
||||
|
||||
/** The fields B param (hex) */
|
||||
char *B;
|
||||
|
||||
/** The order of the curve (hex) */
|
||||
char *order;
|
||||
|
||||
/** The x co-ordinate of the base point on the curve (hex) */
|
||||
char *Gx;
|
||||
|
||||
/** The y co-ordinate of the base point on the curve (hex) */
|
||||
char *Gy;
|
||||
} ltc_ecc_set_type;
|
||||
|
||||
/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
|
||||
typedef struct {
|
||||
/** The x co-ordinate */
|
||||
void *x;
|
||||
|
||||
/** The y co-ordinate */
|
||||
void *y;
|
||||
|
||||
/** The z co-ordinate */
|
||||
void *z;
|
||||
} ecc_point;
|
||||
|
||||
/** An ECC key */
|
||||
typedef struct {
|
||||
/** Type of key, PK_PRIVATE or PK_PUBLIC */
|
||||
int type;
|
||||
|
||||
/** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */
|
||||
int idx;
|
||||
|
||||
/** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */
|
||||
const ltc_ecc_set_type *dp;
|
||||
|
||||
/** The public key */
|
||||
ecc_point pubkey;
|
||||
|
||||
/** The private key */
|
||||
void *k;
|
||||
} ecc_key;
|
||||
|
||||
/** the ECC params provided */
|
||||
extern const ltc_ecc_set_type ltc_ecc_sets[];
|
||||
|
||||
int ecc_test(void);
|
||||
void ecc_sizes(int *low, int *high);
|
||||
int ecc_get_size(ecc_key *key);
|
||||
|
||||
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
|
||||
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp);
|
||||
void ecc_free(ecc_key *key);
|
||||
|
||||
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
|
||||
int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
|
||||
int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp);
|
||||
|
||||
int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen);
|
||||
int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
|
||||
int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);
|
||||
|
||||
int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, int hash,
|
||||
ecc_key *key);
|
||||
|
||||
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
ecc_key *key);
|
||||
|
||||
int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, ecc_key *key);
|
||||
|
||||
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat, ecc_key *key);
|
||||
|
||||
/* low level functions */
|
||||
ecc_point *ltc_ecc_new_point(void);
|
||||
void ltc_ecc_del_point(ecc_point *p);
|
||||
int ltc_ecc_is_valid_idx(int n);
|
||||
|
||||
/* point ops (mp == montgomery digit) */
|
||||
#if !defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC) || defined(GMP_LTC_DESC)
|
||||
/* R = 2P */
|
||||
int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp);
|
||||
|
||||
/* R = P + Q */
|
||||
int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
|
||||
#endif
|
||||
|
||||
#if defined(LTC_MECC_FP)
|
||||
/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */
|
||||
int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
|
||||
|
||||
/* functions for saving/loading/freeing/adding to fixed point cache */
|
||||
int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen);
|
||||
int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen);
|
||||
void ltc_ecc_fp_free(void);
|
||||
int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock);
|
||||
|
||||
/* lock/unlock all points currently in fixed point cache */
|
||||
void ltc_ecc_fp_tablelock(int lock);
|
||||
#endif
|
||||
|
||||
/* R = kG */
|
||||
int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
|
||||
|
||||
#ifdef LTC_ECC_SHAMIR
|
||||
/* kA*A + kB*B = C */
|
||||
int ltc_ecc_mul2add(ecc_point *A, void *kA,
|
||||
ecc_point *B, void *kB,
|
||||
ecc_point *C,
|
||||
void *modulus);
|
||||
|
||||
#ifdef LTC_MECC_FP
|
||||
/* Shamir's trick with optimized point multiplication using fixed point cache */
|
||||
int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
||||
ecc_point *B, void *kB,
|
||||
ecc_point *C, void *modulus);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* map P to affine from projective */
|
||||
int ltc_ecc_map(ecc_point *P, void *modulus, void *mp);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LTC_MDSA
|
||||
|
||||
/* Max diff between group and modulus size in bytes */
|
||||
#define LTC_MDSA_DELTA 512
|
||||
|
||||
/* Max DSA group size in bytes (default allows 4k-bit groups) */
|
||||
#define LTC_MDSA_MAX_GROUP 512
|
||||
|
||||
/** DSA key structure */
|
||||
typedef struct {
|
||||
/** The key type, PK_PRIVATE or PK_PUBLIC */
|
||||
int type;
|
||||
|
||||
/** The order of the sub-group used in octets */
|
||||
int qord;
|
||||
|
||||
/** The generator */
|
||||
void *g;
|
||||
|
||||
/** The prime used to generate the sub-group */
|
||||
void *q;
|
||||
|
||||
/** The large prime that generats the field the contains the sub-group */
|
||||
void *p;
|
||||
|
||||
/** The private key */
|
||||
void *x;
|
||||
|
||||
/** The public key */
|
||||
void *y;
|
||||
} dsa_key;
|
||||
|
||||
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
|
||||
void dsa_free(dsa_key *key);
|
||||
|
||||
int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
|
||||
void *r, void *s,
|
||||
prng_state *prng, int wprng, dsa_key *key);
|
||||
|
||||
int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, dsa_key *key);
|
||||
|
||||
int dsa_verify_hash_raw( void *r, void *s,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat, dsa_key *key);
|
||||
|
||||
int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat, dsa_key *key);
|
||||
|
||||
int dsa_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, int hash,
|
||||
dsa_key *key);
|
||||
|
||||
int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
dsa_key *key);
|
||||
|
||||
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
|
||||
int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
|
||||
int dsa_verify_key(dsa_key *key, int *stat);
|
||||
|
||||
int dsa_shared_secret(void *private_key, void *base,
|
||||
dsa_key *public_key,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
#endif
|
||||
|
||||
#ifdef LTC_DER
|
||||
/* DER handling */
|
||||
|
||||
enum {
|
||||
LTC_ASN1_EOL,
|
||||
LTC_ASN1_BOOLEAN,
|
||||
LTC_ASN1_INTEGER,
|
||||
LTC_ASN1_SHORT_INTEGER,
|
||||
LTC_ASN1_BIT_STRING,
|
||||
LTC_ASN1_OCTET_STRING,
|
||||
LTC_ASN1_NULL,
|
||||
LTC_ASN1_OBJECT_IDENTIFIER,
|
||||
LTC_ASN1_IA5_STRING,
|
||||
LTC_ASN1_PRINTABLE_STRING,
|
||||
LTC_ASN1_UTF8_STRING,
|
||||
LTC_ASN1_UTCTIME,
|
||||
LTC_ASN1_CHOICE,
|
||||
LTC_ASN1_SEQUENCE,
|
||||
LTC_ASN1_SET,
|
||||
LTC_ASN1_SETOF
|
||||
};
|
||||
|
||||
/** A LTC ASN.1 list type */
|
||||
typedef struct ltc_asn1_list_ {
|
||||
/** The LTC ASN.1 enumerated type identifier */
|
||||
int type;
|
||||
/** The data to encode or place for decoding */
|
||||
void *data;
|
||||
/** The size of the input or resulting output */
|
||||
unsigned long size;
|
||||
/** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */
|
||||
int used;
|
||||
/** prev/next entry in the list */
|
||||
struct ltc_asn1_list_ *prev, *next, *child, *parent;
|
||||
} ltc_asn1_list;
|
||||
|
||||
#define LTC_SET_ASN1(list, index, Type, Data, Size) \
|
||||
do { \
|
||||
int LTC_MACRO_temp = (index); \
|
||||
ltc_asn1_list *LTC_MACRO_list = (list); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].used = 0; \
|
||||
} while (0);
|
||||
|
||||
/* SEQUENCE */
|
||||
int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen, int type_of);
|
||||
|
||||
#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)
|
||||
|
||||
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
|
||||
ltc_asn1_list *list, unsigned long outlen, int ordered);
|
||||
|
||||
#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1)
|
||||
|
||||
int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned long *outlen);
|
||||
|
||||
/* SET */
|
||||
#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0)
|
||||
#define der_length_set der_length_sequence
|
||||
int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/* VA list handy helpers with triplets of <type, size, data> */
|
||||
int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
|
||||
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);
|
||||
|
||||
/* FLEXI DECODER handle unknown list decoder */
|
||||
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);
|
||||
void der_free_sequence_flexi(ltc_asn1_list *list);
|
||||
void der_sequence_free(ltc_asn1_list *in);
|
||||
|
||||
/* BOOLEAN */
|
||||
int der_length_boolean(unsigned long *outlen);
|
||||
int der_encode_boolean(int in,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_boolean(const unsigned char *in, unsigned long inlen,
|
||||
int *out);
|
||||
/* INTEGER */
|
||||
int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num);
|
||||
int der_length_integer(void *num, unsigned long *len);
|
||||
|
||||
/* INTEGER -- handy for 0..2^32-1 values */
|
||||
int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num);
|
||||
int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen);
|
||||
int der_length_short_integer(unsigned long num, unsigned long *outlen);
|
||||
|
||||
/* BIT STRING */
|
||||
int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_length_bit_string(unsigned long nbits, unsigned long *outlen);
|
||||
|
||||
/* OCTET STRING */
|
||||
int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_length_octet_string(unsigned long noctets, unsigned long *outlen);
|
||||
|
||||
/* OBJECT IDENTIFIER */
|
||||
int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
|
||||
unsigned long *words, unsigned long *outlen);
|
||||
int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen);
|
||||
unsigned long der_object_identifier_bits(unsigned long x);
|
||||
|
||||
/* IA5 STRING */
|
||||
int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
|
||||
|
||||
int der_ia5_char_encode(int c);
|
||||
int der_ia5_value_decode(int v);
|
||||
|
||||
/* Printable STRING */
|
||||
int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
|
||||
|
||||
int der_printable_char_encode(int c);
|
||||
int der_printable_value_decode(int v);
|
||||
|
||||
/* UTF-8 */
|
||||
#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR)
|
||||
#include <wchar.h>
|
||||
#else
|
||||
typedef ulong32 wchar_t;
|
||||
#endif
|
||||
|
||||
int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
|
||||
wchar_t *out, unsigned long *outlen);
|
||||
unsigned long der_utf8_charsize(const wchar_t c);
|
||||
int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen);
|
||||
|
||||
|
||||
/* CHOICE */
|
||||
int der_decode_choice(const unsigned char *in, unsigned long *inlen,
|
||||
ltc_asn1_list *list, unsigned long outlen);
|
||||
|
||||
/* UTCTime */
|
||||
typedef struct {
|
||||
unsigned YY, /* year */
|
||||
MM, /* month */
|
||||
DD, /* day */
|
||||
hh, /* hour */
|
||||
mm, /* minute */
|
||||
ss, /* second */
|
||||
off_dir, /* timezone offset direction 0 == +, 1 == - */
|
||||
off_hh, /* timezone offset hours */
|
||||
off_mm; /* timezone offset minutes */
|
||||
} ltc_utctime;
|
||||
|
||||
int der_encode_utctime(ltc_utctime *utctime,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
|
||||
ltc_utctime *out);
|
||||
|
||||
int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pk.h,v $ */
|
||||
/* $Revision: 1.81 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
@ -0,0 +1,89 @@
|
||||
/* LTC_PKCS Header Info */
|
||||
|
||||
/* ===> LTC_PKCS #1 -- RSA Cryptography <=== */
|
||||
#ifdef LTC_PKCS_1
|
||||
|
||||
enum ltc_pkcs_1_v1_5_blocks
|
||||
{
|
||||
LTC_LTC_PKCS_1_EMSA = 1, /* Block type 1 (LTC_PKCS #1 v1.5 signature padding) */
|
||||
LTC_LTC_PKCS_1_EME = 2 /* Block type 2 (LTC_PKCS #1 v1.5 encryption padding) */
|
||||
};
|
||||
|
||||
enum ltc_pkcs_1_paddings
|
||||
{
|
||||
LTC_LTC_PKCS_1_V1_5 = 1, /* LTC_PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */
|
||||
LTC_LTC_PKCS_1_OAEP = 2, /* LTC_PKCS #1 v2.0 encryption padding */
|
||||
LTC_LTC_PKCS_1_PSS = 3 /* LTC_PKCS #1 v2.1 signature padding */
|
||||
};
|
||||
|
||||
int pkcs_1_mgf1( int hash_idx,
|
||||
const unsigned char *seed, unsigned long seedlen,
|
||||
unsigned char *mask, unsigned long masklen);
|
||||
|
||||
int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out);
|
||||
int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen);
|
||||
|
||||
/* *** v1.5 padding */
|
||||
int pkcs_1_v1_5_encode(const unsigned char *msg,
|
||||
unsigned long msglen,
|
||||
int block_type,
|
||||
unsigned long modulus_bitlen,
|
||||
prng_state *prng,
|
||||
int prng_idx,
|
||||
unsigned char *out,
|
||||
unsigned long *outlen);
|
||||
|
||||
int pkcs_1_v1_5_decode(const unsigned char *msg,
|
||||
unsigned long msglen,
|
||||
int block_type,
|
||||
unsigned long modulus_bitlen,
|
||||
unsigned char *out,
|
||||
unsigned long *outlen,
|
||||
int *is_valid);
|
||||
|
||||
/* *** v2.1 padding */
|
||||
int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
unsigned long modulus_bitlen, prng_state *prng,
|
||||
int prng_idx, int hash_idx,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
|
||||
const unsigned char *lparam, unsigned long lparamlen,
|
||||
unsigned long modulus_bitlen, int hash_idx,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
int *res);
|
||||
|
||||
int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
|
||||
unsigned long saltlen, prng_state *prng,
|
||||
int prng_idx, int hash_idx,
|
||||
unsigned long modulus_bitlen,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
|
||||
const unsigned char *sig, unsigned long siglen,
|
||||
unsigned long saltlen, int hash_idx,
|
||||
unsigned long modulus_bitlen, int *res);
|
||||
|
||||
#endif /* LTC_PKCS_1 */
|
||||
|
||||
/* ===> LTC_PKCS #5 -- Password Based Cryptography <=== */
|
||||
#ifdef LTC_PKCS_5
|
||||
|
||||
/* Algorithm #1 (old) */
|
||||
int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
|
||||
const unsigned char *salt,
|
||||
int iteration_count, int hash_idx,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
/* Algorithm #2 (new) */
|
||||
int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
|
||||
const unsigned char *salt, unsigned long salt_len,
|
||||
int iteration_count, int hash_idx,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
#endif /* LTC_PKCS_5 */
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pkcs.h,v $ */
|
||||
/* $Revision: 1.8 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
199
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_prng.h
Normal file
199
src/dep/src/StormLib/src/libtomcrypt/src/headers/tomcrypt_prng.h
Normal file
@ -0,0 +1,199 @@
|
||||
/* ---- PRNG Stuff ---- */
|
||||
#ifdef LTC_YARROW
|
||||
struct yarrow_prng {
|
||||
int cipher, hash;
|
||||
unsigned char pool[MAXBLOCKSIZE];
|
||||
symmetric_CTR ctr;
|
||||
LTC_MUTEX_TYPE(prng_lock)
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC4
|
||||
struct rc4_prng {
|
||||
int x, y;
|
||||
unsigned char buf[256];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_FORTUNA
|
||||
struct fortuna_prng {
|
||||
hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */
|
||||
|
||||
symmetric_key skey;
|
||||
|
||||
unsigned char K[32], /* the current key */
|
||||
IV[16]; /* IV for CTR mode */
|
||||
|
||||
unsigned long pool_idx, /* current pool we will add to */
|
||||
pool0_len, /* length of 0'th pool */
|
||||
wd;
|
||||
|
||||
ulong64 reset_cnt; /* number of times we have reset */
|
||||
LTC_MUTEX_TYPE(prng_lock)
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SOBER128
|
||||
struct sober128_prng {
|
||||
ulong32 R[17], /* Working storage for the shift register */
|
||||
initR[17], /* saved register contents */
|
||||
konst, /* key dependent constant */
|
||||
sbuf; /* partial word encryption buffer */
|
||||
|
||||
int nbuf, /* number of part-word stream bits buffered */
|
||||
flag, /* first add_entropy call or not? */
|
||||
set; /* did we call add_entropy to set key? */
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef union Prng_state {
|
||||
char dummy[1];
|
||||
#ifdef LTC_YARROW
|
||||
struct yarrow_prng yarrow;
|
||||
#endif
|
||||
#ifdef LTC_RC4
|
||||
struct rc4_prng rc4;
|
||||
#endif
|
||||
#ifdef LTC_FORTUNA
|
||||
struct fortuna_prng fortuna;
|
||||
#endif
|
||||
#ifdef LTC_SOBER128
|
||||
struct sober128_prng sober128;
|
||||
#endif
|
||||
} prng_state;
|
||||
|
||||
/** PRNG descriptor */
|
||||
extern struct ltc_prng_descriptor {
|
||||
/** Name of the PRNG */
|
||||
char *name;
|
||||
/** size in bytes of exported state */
|
||||
int export_size;
|
||||
/** Start a PRNG state
|
||||
@param prng [out] The state to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*start)(prng_state *prng);
|
||||
/** Add entropy to the PRNG
|
||||
@param in The entropy
|
||||
@param inlen Length of the entropy (octets)\
|
||||
@param prng The PRNG state
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
/** Ready a PRNG state to read from
|
||||
@param prng The PRNG state to ready
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*ready)(prng_state *prng);
|
||||
/** Read from the PRNG
|
||||
@param out [out] Where to store the data
|
||||
@param outlen Length of data desired (octets)
|
||||
@param prng The PRNG state to read from
|
||||
@return Number of octets read
|
||||
*/
|
||||
unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
/** Terminate a PRNG state
|
||||
@param prng The PRNG state to terminate
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*done)(prng_state *prng);
|
||||
/** Export a PRNG state
|
||||
@param out [out] The destination for the state
|
||||
@param outlen [in/out] The max size and resulting size of the PRNG state
|
||||
@param prng The PRNG to export
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
/** Import a PRNG state
|
||||
@param in The data to import
|
||||
@param inlen The length of the data to import (octets)
|
||||
@param prng The PRNG to initialize/import
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
/** Self-test the PRNG
|
||||
@return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
|
||||
*/
|
||||
int (*test)(void);
|
||||
} prng_descriptor[];
|
||||
|
||||
#ifdef LTC_YARROW
|
||||
int yarrow_start(prng_state *prng);
|
||||
int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int yarrow_ready(prng_state *prng);
|
||||
unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int yarrow_done(prng_state *prng);
|
||||
int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int yarrow_test(void);
|
||||
extern const struct ltc_prng_descriptor yarrow_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_FORTUNA
|
||||
int fortuna_start(prng_state *prng);
|
||||
int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int fortuna_ready(prng_state *prng);
|
||||
unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int fortuna_done(prng_state *prng);
|
||||
int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int fortuna_test(void);
|
||||
extern const struct ltc_prng_descriptor fortuna_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_RC4
|
||||
int rc4_start(prng_state *prng);
|
||||
int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int rc4_ready(prng_state *prng);
|
||||
unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int rc4_done(prng_state *prng);
|
||||
int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int rc4_test(void);
|
||||
extern const struct ltc_prng_descriptor rc4_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SPRNG
|
||||
int sprng_start(prng_state *prng);
|
||||
int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int sprng_ready(prng_state *prng);
|
||||
unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int sprng_done(prng_state *prng);
|
||||
int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int sprng_test(void);
|
||||
extern const struct ltc_prng_descriptor sprng_desc;
|
||||
#endif
|
||||
|
||||
#ifdef LTC_SOBER128
|
||||
int sober128_start(prng_state *prng);
|
||||
int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int sober128_ready(prng_state *prng);
|
||||
unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng);
|
||||
int sober128_done(prng_state *prng);
|
||||
int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
|
||||
int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
|
||||
int sober128_test(void);
|
||||
extern const struct ltc_prng_descriptor sober128_desc;
|
||||
#endif
|
||||
|
||||
int find_prng(const char *name);
|
||||
int register_prng(const struct ltc_prng_descriptor *prng);
|
||||
int unregister_prng(const struct ltc_prng_descriptor *prng);
|
||||
int prng_is_valid(int idx);
|
||||
LTC_MUTEX_PROTO(ltc_prng_mutex)
|
||||
|
||||
/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this
|
||||
* might not work on all platforms as planned
|
||||
*/
|
||||
unsigned long rng_get_bytes(unsigned char *out,
|
||||
unsigned long outlen,
|
||||
void (*callback)(void));
|
||||
|
||||
int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
|
||||
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_prng.h,v $ */
|
||||
/* $Revision: 1.9 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
483
src/dep/src/StormLib/src/libtomcrypt/src/math/ltm_desc.c
Normal file
483
src/dep/src/StormLib/src/libtomcrypt/src/math/ltm_desc.c
Normal file
@ -0,0 +1,483 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
|
||||
*/
|
||||
|
||||
#define DESC_DEF_ONLY
|
||||
#include "../headers/tomcrypt.h"
|
||||
|
||||
#ifdef LTM_DESC
|
||||
|
||||
#include "../../../libtommath/tommath.h"
|
||||
|
||||
static const struct {
|
||||
int mpi_code, ltc_code;
|
||||
} mpi_to_ltc_codes[] = {
|
||||
{ MP_OKAY , CRYPT_OK},
|
||||
{ MP_MEM , CRYPT_MEM},
|
||||
{ MP_VAL , CRYPT_INVALID_ARG},
|
||||
};
|
||||
|
||||
/**
|
||||
Convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no)
|
||||
@param err The error to convert
|
||||
@return The equivalent LTC error code or CRYPT_ERROR if none found
|
||||
*/
|
||||
static int mpi_to_ltc_error(int err)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
|
||||
if (err == mpi_to_ltc_codes[x].mpi_code) {
|
||||
return mpi_to_ltc_codes[x].ltc_code;
|
||||
}
|
||||
}
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
static int init(void **a)
|
||||
{
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(a != NULL);
|
||||
|
||||
*a = XCALLOC(1, sizeof(mp_int));
|
||||
if (*a == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) {
|
||||
XFREE(*a);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void deinit(void *a)
|
||||
{
|
||||
LTC_ARGCHKVD(a != NULL);
|
||||
mp_clear(a);
|
||||
XFREE(a);
|
||||
}
|
||||
|
||||
static int neg(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_neg(a, b));
|
||||
}
|
||||
|
||||
static int copy(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_copy(a, b));
|
||||
}
|
||||
|
||||
static int init_copy(void **a, void *b)
|
||||
{
|
||||
if (init(a) != CRYPT_OK) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
return copy(b, *a);
|
||||
}
|
||||
|
||||
/* ---- trivial ---- */
|
||||
static int set_int(void *a, unsigned long b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mpi_to_ltc_error(mp_set_int(a, b));
|
||||
}
|
||||
|
||||
static unsigned long get_int(void *a)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mp_get_int(a);
|
||||
}
|
||||
|
||||
static unsigned long get_digit(void *a, int n)
|
||||
{
|
||||
mp_int *A;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
A = a;
|
||||
return (n >= A->used || n < 0) ? 0 : A->dp[n];
|
||||
}
|
||||
|
||||
static int get_digit_count(void *a)
|
||||
{
|
||||
mp_int *A;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
A = a;
|
||||
return A->used;
|
||||
}
|
||||
|
||||
static int compare(void *a, void *b)
|
||||
{
|
||||
int ret;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
ret = mp_cmp(a, b);
|
||||
switch (ret) {
|
||||
case MP_LT: return LTC_MP_LT;
|
||||
case MP_EQ: return LTC_MP_EQ;
|
||||
case MP_GT: return LTC_MP_GT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_d(void *a, unsigned long b)
|
||||
{
|
||||
int ret;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
ret = mp_cmp_d(a, b);
|
||||
switch (ret) {
|
||||
case MP_LT: return LTC_MP_LT;
|
||||
case MP_EQ: return LTC_MP_EQ;
|
||||
case MP_GT: return LTC_MP_GT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int count_bits(void *a)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mp_count_bits(a);
|
||||
}
|
||||
|
||||
static int count_lsb_bits(void *a)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mp_cnt_lsb(a);
|
||||
}
|
||||
|
||||
|
||||
static int twoexpt(void *a, int n)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mpi_to_ltc_error(mp_2expt(a, n));
|
||||
}
|
||||
|
||||
/* ---- conversions ---- */
|
||||
|
||||
/* read ascii string */
|
||||
static int read_radix(void *a, const char *b, int radix)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_read_radix(a, b, radix));
|
||||
}
|
||||
|
||||
/* write one */
|
||||
static int write_radix(void *a, char *b, int radix)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_toradix(a, b, radix));
|
||||
}
|
||||
|
||||
/* get size as unsigned char string */
|
||||
static unsigned long unsigned_size(void *a)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
return mp_unsigned_bin_size(a);
|
||||
}
|
||||
|
||||
/* store */
|
||||
static int unsigned_write(void *a, unsigned char *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_to_unsigned_bin(a, b));
|
||||
}
|
||||
|
||||
/* read */
|
||||
static int unsigned_read(void *a, unsigned char *b, unsigned long len)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len));
|
||||
}
|
||||
|
||||
/* add */
|
||||
static int add(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_add(a, b, c));
|
||||
}
|
||||
|
||||
static int addi(void *a, unsigned long b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_add_d(a, b, c));
|
||||
}
|
||||
|
||||
/* sub */
|
||||
static int sub(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_sub(a, b, c));
|
||||
}
|
||||
|
||||
static int subi(void *a, unsigned long b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_sub_d(a, b, c));
|
||||
}
|
||||
|
||||
/* mul */
|
||||
static int mul(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_mul(a, b, c));
|
||||
}
|
||||
|
||||
static int muli(void *a, unsigned long b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_mul_d(a, b, c));
|
||||
}
|
||||
|
||||
/* sqr */
|
||||
static int sqr(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_sqr(a, b));
|
||||
}
|
||||
|
||||
/* div */
|
||||
static int divide(void *a, void *b, void *c, void *d)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_div(a, b, c, d));
|
||||
}
|
||||
|
||||
static int div_2(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_div_2(a, b));
|
||||
}
|
||||
|
||||
/* modi */
|
||||
static int modi(void *a, unsigned long b, unsigned long *c)
|
||||
{
|
||||
mp_digit tmp;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
|
||||
if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
*c = tmp;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/* gcd */
|
||||
static int gcd(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_gcd(a, b, c));
|
||||
}
|
||||
|
||||
/* lcm */
|
||||
static int lcm(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_lcm(a, b, c));
|
||||
}
|
||||
|
||||
static int mulmod(void *a, void *b, void *c, void *d)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
LTC_ARGCHK(d != NULL);
|
||||
return mpi_to_ltc_error(mp_mulmod(a,b,c,d));
|
||||
}
|
||||
|
||||
static int sqrmod(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_sqrmod(a,b,c));
|
||||
}
|
||||
|
||||
/* invmod */
|
||||
static int invmod(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_invmod(a, b, c));
|
||||
}
|
||||
|
||||
/* setup */
|
||||
static int montgomery_setup(void *a, void **b)
|
||||
{
|
||||
int err;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
*b = XCALLOC(1, sizeof(mp_digit));
|
||||
if (*b == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) {
|
||||
XFREE(*b);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* get normalization value */
|
||||
static int montgomery_normalization(void *a, void *b)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b));
|
||||
}
|
||||
|
||||
/* reduce */
|
||||
static int montgomery_reduce(void *a, void *b, void *c)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c)));
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
static void montgomery_deinit(void *a)
|
||||
{
|
||||
XFREE(a);
|
||||
}
|
||||
|
||||
static int exptmod(void *a, void *b, void *c, void *d)
|
||||
{
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
LTC_ARGCHK(c != NULL);
|
||||
LTC_ARGCHK(d != NULL);
|
||||
return mpi_to_ltc_error(mp_exptmod(a,b,c,d));
|
||||
}
|
||||
|
||||
static int isprime(void *a, int *b)
|
||||
{
|
||||
int err;
|
||||
LTC_ARGCHK(a != NULL);
|
||||
LTC_ARGCHK(b != NULL);
|
||||
err = mpi_to_ltc_error(mp_prime_is_prime(a, 8, b));
|
||||
*b = (*b == MP_YES) ? LTC_MP_YES : LTC_MP_NO;
|
||||
return err;
|
||||
}
|
||||
|
||||
const ltc_math_descriptor ltm_desc = {
|
||||
|
||||
"LibTomMath",
|
||||
(int)DIGIT_BIT,
|
||||
|
||||
&init,
|
||||
&init_copy,
|
||||
&deinit,
|
||||
|
||||
&neg,
|
||||
©,
|
||||
|
||||
&set_int,
|
||||
&get_int,
|
||||
&get_digit,
|
||||
&get_digit_count,
|
||||
&compare,
|
||||
&compare_d,
|
||||
&count_bits,
|
||||
&count_lsb_bits,
|
||||
&twoexpt,
|
||||
|
||||
&read_radix,
|
||||
&write_radix,
|
||||
&unsigned_size,
|
||||
&unsigned_write,
|
||||
&unsigned_read,
|
||||
|
||||
&add,
|
||||
&addi,
|
||||
&sub,
|
||||
&subi,
|
||||
&mul,
|
||||
&muli,
|
||||
&sqr,
|
||||
÷,
|
||||
&div_2,
|
||||
&modi,
|
||||
&gcd,
|
||||
&lcm,
|
||||
|
||||
&mulmod,
|
||||
&sqrmod,
|
||||
&invmod,
|
||||
|
||||
&montgomery_setup,
|
||||
&montgomery_normalization,
|
||||
&montgomery_reduce,
|
||||
&montgomery_deinit,
|
||||
|
||||
&exptmod,
|
||||
&isprime,
|
||||
|
||||
#ifdef LTC_MECC
|
||||
#ifdef LTC_MECC_FP
|
||||
<c_ecc_fp_mulmod,
|
||||
#else
|
||||
<c_ecc_mulmod,
|
||||
#endif
|
||||
<c_ecc_projective_add_point,
|
||||
<c_ecc_projective_dbl_point,
|
||||
<c_ecc_map,
|
||||
#ifdef LTC_ECC_SHAMIR
|
||||
#ifdef LTC_MECC_FP
|
||||
<c_ecc_fp_mul2add,
|
||||
#else
|
||||
<c_ecc_mul2add,
|
||||
#endif /* LTC_MECC_FP */
|
||||
#else
|
||||
NULL,
|
||||
#endif /* LTC_ECC_SHAMIR */
|
||||
#else
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
#endif /* LTC_MECC */
|
||||
|
||||
#ifdef LTC_MRSA
|
||||
&rsa_make_key,
|
||||
&rsa_exptmod,
|
||||
#else
|
||||
NULL, NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* $Source: /cvs/libtom/libtomcrypt/src/math/ltm_desc.c,v $ */
|
||||
/* $Revision: 1.31 $ */
|
||||
/* $Date: 2007/05/12 14:32:35 $ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user