26 changed files with 2713 additions and 483 deletions
@ -0,0 +1,240 @@
|
||||
|
||||
#include <boost/utility/enable_if.hpp> |
||||
#include <boost/integer.hpp> |
||||
#include <boost/integer/static_log2.hpp> |
||||
#include <boost/integer/static_min_max.hpp> |
||||
#include <boost/integer_traits.hpp> |
||||
|
||||
namespace boost { |
||||
template <class T> |
||||
class integer_traits<const T> : public integer_traits<T> { }; |
||||
} |
||||
|
||||
template <size_t N, class Type = void, class Enable = void> |
||||
struct is_power_of_two { |
||||
static const bool value = false; |
||||
}; |
||||
template <size_t N, class Type> |
||||
struct is_power_of_two<N, Type, typename boost::enable_if_c<(N & (N - 1)) == 0>::type> { |
||||
static const bool value = true; |
||||
typedef Type type; |
||||
}; |
||||
|
||||
template <size_t N, class Enable = void> |
||||
struct log_next_power_of_two { |
||||
static const size_t value = boost::static_log2<N>::value + 1; |
||||
}; |
||||
template <size_t N> |
||||
struct log_next_power_of_two<N, typename boost::enable_if<is_power_of_two<N> >::type> { |
||||
static const size_t value = boost::static_log2<N>::value; |
||||
}; |
||||
|
||||
template <size_t N, class Enable = void> |
||||
struct next_power_of_two { |
||||
static const size_t value = size_t(1) << (boost::static_log2<N>::value + 1); |
||||
}; |
||||
template <size_t N> |
||||
struct next_power_of_two<N, typename boost::enable_if<is_power_of_two<N> >::type> { |
||||
static const size_t value = N; |
||||
}; |
||||
|
||||
|
||||
struct fast_integers { |
||||
|
||||
private: |
||||
|
||||
template <size_t Bits, class Dummy = void> struct _impl { }; |
||||
template <class Dummy> struct _impl<8, Dummy> { typedef uint_fast8_t type; }; |
||||
template <class Dummy> struct _impl<16, Dummy> { typedef uint_fast16_t type; }; |
||||
template <class Dummy> struct _impl<32, Dummy> { typedef uint_fast32_t type; }; |
||||
template <class Dummy> struct _impl<64, Dummy> { typedef uint_fast64_t type; }; |
||||
template <class Dummy> struct _impl<128, Dummy> { typedef __uint128_t type; }; |
||||
|
||||
public: |
||||
|
||||
template <size_t Bits> |
||||
struct bits : public _impl<boost::static_unsigned_max<8, next_power_of_two<Bits>::value>::value> { }; |
||||
|
||||
}; |
||||
|
||||
struct exact_integers { |
||||
|
||||
private: |
||||
|
||||
template <size_t Bits, class Dummy = void> struct _impl { }; |
||||
template <class Dummy> struct _impl<8, Dummy> { typedef uint8_t type; }; |
||||
template <class Dummy> struct _impl<16, Dummy> { typedef uint16_t type; }; |
||||
template <class Dummy> struct _impl<32, Dummy> { typedef uint32_t type; }; |
||||
template <class Dummy> struct _impl<64, Dummy> { typedef uint64_t type; }; |
||||
template <class Dummy> struct _impl<128, Dummy> { typedef __uint128_t type; }; |
||||
|
||||
public: |
||||
|
||||
template <size_t Bits> |
||||
struct bits : public _impl<boost::static_unsigned_max<8, next_power_of_two<Bits>::value>::value> { }; |
||||
|
||||
}; |
||||
|
||||
struct bitset_types { |
||||
|
||||
template <size_t Bits> |
||||
struct bits { |
||||
typedef std::bitset<Bits> type; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
|
||||
/*!
|
||||
* Converter that rearranges bits in an integer. |
||||
* |
||||
* Conversion is reduced to a minimal number of mask & shift operations at compile-time.
|
||||
* |
||||
* Usage: |
||||
* |
||||
* bitset_converter<> is an empty converter list (cannot be used without adding at least one mappings). |
||||
* (list)::add::map<from, to> maps the from'th input bit to the to'th output bit. |
||||
* |
||||
* Convenience function to add a continous region of mappings: |
||||
* bitset_converter<>::add::value<to2> is equivalent to bitset_converter<>::add::map<0, to2> |
||||
* (list)::add::map<from, to>::add::value<to2> is equivalent to ::add::map<from, to>::add::map<from + 1, to2> |
||||
* |
||||
* Inut bits without a corresponding "from" entry are ignored. |
||||
* Output bit without a corresponding "to" entry are always zero. |
||||
* |
||||
* The same input/output bit can appear in multiple mappings. |
||||
* |
||||
* Invoke the converter: (list)::convert(integer) |
||||
* |
||||
* Limitations: |
||||
* |
||||
* Input bits must fit in a native integer type provided by in_types::bits<bits>. |
||||
* |
||||
* Output bits must fit in an integer type selected by out_types::bits<bits>. |
||||
* |
||||
* Example: |
||||
* |
||||
* // Create a converter that swaps the first two bits, keeps the next one and ignores all others.
|
||||
* typedef bitset_converter<>::add::map<0, 1>::add::map<1, 0>::add::value<2> Converter; |
||||
* |
||||
* // Convert something.
|
||||
* Converter::convert(3); |
||||
*
|
||||
*/ |
||||
template <class out_types = fast_integers, class in_types = fast_integers> |
||||
struct bitset_converter { |
||||
|
||||
private: |
||||
|
||||
typedef ptrdiff_t shift_type; |
||||
typedef size_t index_type; |
||||
|
||||
template <class Combiner, class Entry> |
||||
struct IterateEntries { |
||||
static const typename Combiner::type value = Combiner::template combine<Entry, (IterateEntries<Combiner, typename Entry::next>::value)>::value; |
||||
}; |
||||
template <class Combiner> struct IterateEntries<Combiner, void> { static const typename Combiner::type value = Combiner::base; }; |
||||
template <class Type, Type Base> struct Combiner { typedef Type type; static const Type base = Base; }; |
||||
|
||||
template<class Getter, class Type> |
||||
struct MaxCombiner : public Combiner<Type, boost::integer_traits<Type>::const_min> { |
||||
template <class Entry, Type accumulator> |
||||
struct combine { static const Type value = boost::static_signed_max<Getter::template get<Entry>::value, accumulator>::value; }; |
||||
}; |
||||
|
||||
template<class Getter, class Type> |
||||
struct MinCombiner : public Combiner<Type, boost::integer_traits<Type>::const_max> { |
||||
template <class Entry, Type accumulator> |
||||
struct combine { static const Type value = boost::static_signed_min<Getter::template get<Entry>::value, accumulator>::value; }; |
||||
}; |
||||
|
||||
struct ShiftGetter { template<class Entry> struct get { static const shift_type value = Entry::shift; }; }; |
||||
struct FromGetter { template<class Entry> struct get { static const index_type value = Entry::from; }; }; |
||||
struct ToGetter { template<class Entry> struct get { static const index_type value = Entry::to; }; }; |
||||
|
||||
template<shift_type Shift, class Type> |
||||
struct ShiftMaskCombiner : public Combiner<Type, Type(0)> { |
||||
template <class Entry, Type mask> |
||||
struct combine { static const Type value = mask | ( (Entry::shift == Shift) ? (Type(1) << Entry::from) : Type(0) ); }; |
||||
}; |
||||
|
||||
template<class List> |
||||
struct Builder; |
||||
|
||||
template<index_type From, index_type To, class Next = void> |
||||
struct Entry { |
||||
|
||||
typedef Entry<From, To, Next> This; |
||||
|
||||
static const index_type from = From; |
||||
static const index_type to = To; |
||||
typedef Next next; |
||||
|
||||
static const shift_type shift = shift_type(from) - shift_type(to); |
||||
|
||||
static const shift_type max_shift = IterateEntries<MaxCombiner<ShiftGetter, shift_type>, This>::value; |
||||
static const shift_type min_shift = IterateEntries<MinCombiner<ShiftGetter, shift_type>, This>::value; |
||||
|
||||
static const index_type in_bits = IterateEntries<MaxCombiner<FromGetter, index_type>, This>::value + 1; |
||||
typedef typename in_types::template bits<in_bits>::type in_type; |
||||
|
||||
static const index_type out_bits = IterateEntries<MaxCombiner<ToGetter, index_type>, This>::value + 1; |
||||
typedef typename out_types::template bits<out_bits>::type out_type; |
||||
|
||||
template<shift_type Shift> |
||||
struct ShiftMask { static const in_type value = IterateEntries<ShiftMaskCombiner<Shift, in_type>, This>::value; }; |
||||
|
||||
template <shift_type Shift> |
||||
inline static typename boost::enable_if_c<(Shift >= shift_type(0)), out_type>::type evaluate(in_type value) { |
||||
return out_type((value & ShiftMask<Shift>::value) >> Shift); |
||||
} |
||||
template <shift_type Shift> |
||||
inline static typename boost::enable_if_c<(Shift < shift_type(0)), out_type>::type evaluate(in_type value) { |
||||
return out_type(value & ShiftMask<Shift>::value) << (-Shift);
|
||||
} |
||||
|
||||
template<shift_type Shift, class Enable = void> |
||||
struct NextShift { static const shift_type value = Shift + 1; }; |
||||
template<shift_type Shift> |
||||
struct NextShift<Shift, typename boost::enable_if_c<Shift != max_shift && ShiftMask<Shift + 1>::value == in_type(0)>::type > { |
||||
static const shift_type value = NextShift<Shift + 1>::value; |
||||
}; |
||||
|
||||
template <shift_type Shift> |
||||
inline static typename boost::enable_if_c<(NextShift<Shift>::value != max_shift + 1), out_type>::type map(in_type value) { |
||||
return evaluate<Shift>(value) | (map<NextShift<Shift>::value>(value)); |
||||
} |
||||
template <shift_type Shift> |
||||
inline static typename boost::enable_if_c<(NextShift<Shift>::value == max_shift + 1), out_type>::type map(in_type value) { |
||||
return evaluate<Shift>(value); |
||||
} |
||||
|
||||
public: |
||||
|
||||
typedef Builder<This> add; |
||||
|
||||
static out_type convert(in_type value) { |
||||
return map<min_shift>(value); |
||||
} |
||||
|
||||
}; |
||||
|
||||
template<class List> |
||||
struct Builder { |
||||
|
||||
template<index_type From, index_type To> |
||||
struct map : public Entry<From, To, List> { }; |
||||
|
||||
template<index_type To, class Current = List> |
||||
struct value : public Entry<Current::from + 1, To, Current> { }; |
||||
|
||||
template<index_type To> |
||||
struct value<To, void> : public Entry<0, To> { }; |
||||
|
||||
}; |
||||
|
||||
public: |
||||
|
||||
typedef Builder<void> add; |
||||
|
||||
}; |
||||
@ -1,10 +1,17 @@
|
||||
|
||||
#ifndef INNOEXTRACT_BLOCKREADER_HPP |
||||
#define INNOEXTRACT_BLOCKREADER_HPP |
||||
|
||||
#include <iostream> |
||||
|
||||
#include "Version.hpp" |
||||
|
||||
class BlockReader { |
||||
|
||||
public: |
||||
|
||||
static std::istream * get(std::istream & base); |
||||
static std::istream * get(std::istream & base, const InnoVersion & version); |
||||
|
||||
}; |
||||
|
||||
#endif // INNOEXTRACT_BLOCKREADER_HPP
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
|
||||
#ifndef INNOEXTRACT_ENUM_HPP |
||||
#define INNOEXTRACT_ENUM_HPP |
||||
|
||||
#include <iostream> |
||||
#include <boost/static_assert.hpp> |
||||
#include "Utils.hpp" |
||||
#include "Flags.hpp" |
||||
#include "Output.hpp" |
||||
|
||||
template <class Enum> |
||||
struct EnumNames { |
||||
|
||||
const size_t count; |
||||
|
||||
const char * name; |
||||
|
||||
const char * names[0]; |
||||
|
||||
}; |
||||
|
||||
#define NAMED_ENUM(Enum) \ |
||||
template <> struct EnumNames<Enum> { \
|
||||
static const char * name; \
|
||||
static const char * names[]; \
|
||||
static const size_t count; \
|
||||
}; \
|
||||
std::ostream & operator<<(std::ostream & os, Enum value); |
||||
|
||||
#define ENUM_NAMES(Enum, Name, ...) \ |
||||
const char * EnumNames<Enum>::name = (Name); \
|
||||
const char * EnumNames<Enum>::names[] = { __VA_ARGS__ }; \
|
||||
const size_t EnumNames<Enum>::count = ARRAY_SIZE(EnumNames<Enum>::names); \
|
||||
std::ostream & operator<<(std::ostream & os, Enum value) { \
|
||||
if(value < EnumNames<Enum>::count) { \
|
||||
return os << EnumNames<Enum>::names[value]; \
|
||||
} else { \
|
||||
return os << "(unknown:" << int(value) << ')'; \
|
||||
} \
|
||||
} |
||||
|
||||
template <class Enum> |
||||
std::ostream & operator<<(std::ostream & os, Flags<Enum> flags) { |
||||
color::shell_command prev = color::current; |
||||
if(flags) { |
||||
bool first = true; |
||||
for(size_t i = 0; i < Flags<Enum>::bits; i++) { |
||||
if(flags & Enum(i)) { |
||||
if(first) { |
||||
first = false; |
||||
} else { |
||||
os << color::dim_white << ", " << prev; |
||||
} |
||||
os << Enum(i); |
||||
} |
||||
} |
||||
return os; |
||||
} else { |
||||
return os << color::dim_white << "(none)" << prev; |
||||
} |
||||
} |
||||
|
||||
#endif // INNOEXTRACT_ENUM_HPP
|
||||
@ -0,0 +1,171 @@
|
||||
|
||||
#ifndef INNOEXTRACT_FLAGS_HPP |
||||
#define INNOEXTRACT_FLAGS_HPP |
||||
|
||||
#include <bitset> |
||||
|
||||
// loosely based on QFlags from Qt
|
||||
|
||||
template <typename Enum> |
||||
class EnumSize { static const size_t value = 32; }; |
||||
|
||||
/*!
|
||||
* A typesafe way to define flags as a combination of enum values. |
||||
*
|
||||
* This type should not be used directly, only through DECLARE_FLAGS. |
||||
*/ |
||||
template <typename _Enum> |
||||
class Flags { |
||||
|
||||
public: |
||||
|
||||
typedef _Enum Enum; |
||||
static const size_t bits = EnumSize<Enum>::value; |
||||
typedef std::bitset<bits> Type; |
||||
|
||||
private: |
||||
|
||||
typedef void ** Zero; |
||||
typedef void(*TypesafeBoolean)(); |
||||
|
||||
Type flags; |
||||
|
||||
inline Flags(Type flag) : flags(flag) { } |
||||
|
||||
public: |
||||
|
||||
inline Flags(Enum flag) : flags(Type().set(size_t(flag))) { } |
||||
|
||||
inline Flags(Zero = 0) : flags() { } |
||||
|
||||
inline Flags(const Flags & o) : flags(o.flags) { } |
||||
|
||||
static inline Flags load(Type flags) { |
||||
return Flags(flags, true); |
||||
} |
||||
|
||||
inline bool has(Enum flag) const { |
||||
return flags.test(size_t(flag)); |
||||
} |
||||
|
||||
inline bool hasAll(Flags o) const { |
||||
return (flags & o.flags) == o.flags; |
||||
} |
||||
|
||||
inline operator TypesafeBoolean() const { |
||||
return reinterpret_cast<TypesafeBoolean>(flags.any()); |
||||
} |
||||
|
||||
inline Flags operator~() const { |
||||
return Flags(~flags); |
||||
} |
||||
|
||||
inline bool operator!() const { |
||||
return flags.none(); |
||||
} |
||||
|
||||
inline Flags operator&(Flags o) const { |
||||
return Flags(flags & o.flags); |
||||
} |
||||
|
||||
inline Flags operator|(Flags o) const { |
||||
return Flags(flags | o.flags); |
||||
} |
||||
|
||||
inline Flags operator^(Flags o) const { |
||||
return Flags(flags ^ o.flags); |
||||
} |
||||
|
||||
inline Flags & operator&=(const Flags & o) { |
||||
flags &= o.flags; |
||||
return *this; |
||||
} |
||||
|
||||
inline Flags & operator|=(Flags o) { |
||||
flags |= o.flags; |
||||
return *this; |
||||
} |
||||
|
||||
inline Flags & operator^=(Flags o) { |
||||
flags ^= o.flags; |
||||
return *this; |
||||
} |
||||
|
||||
inline Flags operator&(Enum flag) const { |
||||
return operator&(Flags(flag)); |
||||
} |
||||
|
||||
inline Flags operator|(Enum flag) const { |
||||
return operator|(Flags(flag)); |
||||
} |
||||
|
||||
inline Flags operator^(Enum flag) const { |
||||
return operator^(Flags(flag)); |
||||
} |
||||
|
||||
inline Flags & operator&=(Enum flag) { |
||||
|
||||
return operator&=(Flags(flag)); |
||||
} |
||||
|
||||
inline Flags & operator|=(Enum flag) { |
||||
return operator|=(Flags(flag)); |
||||
} |
||||
|
||||
inline Flags & operator^=(Enum flag) { |
||||
return operator^=(flag); |
||||
} |
||||
|
||||
inline Flags & operator=(Flags o) { |
||||
flags = o.flags; |
||||
return *this; |
||||
} |
||||
|
||||
static inline Flags all() { |
||||
return Flags(Type().flip()); |
||||
} |
||||
|
||||
}; |
||||
|
||||
/*!
|
||||
* Declare a flag type using values from a given enum. |
||||
* This should always be used instead of using Flags<Enum> directly. |
||||
*
|
||||
* @param Enum should be an enum with values that have exactly one bit set. |
||||
* @param Flagname is the name for the flag type to be defined. |
||||
*/ |
||||
#define DECLARE_FLAGS_SIZE(Enum, Flagname, Size) \ |
||||
template <> \
|
||||
struct EnumSize<Enum> { \
|
||||
static const size_t value = (Size); \
|
||||
}; \
|
||||
typedef Flags<Enum> Flagname; |
||||
#define FLAGS_ENUM_END_HELPER(Enum) Enum ## __End |
||||
#define FLAGS_ENUM_END(Enum) FLAGS_ENUM_END_HELPER(Enum) |
||||
#define DECLARE_FLAGS(Enum, Flagname) DECLARE_FLAGS_SIZE(Enum, Flagname, FLAGS_ENUM_END(Enum)) |
||||
|
||||
/*!
|
||||
* Declare overloaded operators for a given flag type. |
||||
*/ |
||||
#define DECLARE_FLAGS_OPERATORS(Flagname) \ |
||||
inline Flagname operator|(Flagname::Enum a, Flagname::Enum b) { \
|
||||
return Flagname(a) | b; \
|
||||
} \
|
||||
inline Flagname operator|(Flagname::Enum a, Flagname b) { \
|
||||
return b | a; \
|
||||
} \
|
||||
inline Flagname operator~(Flagname::Enum a) { \
|
||||
return ~Flagname(a); \
|
||||
} |
||||
// TODO prevent combination with integers!
|
||||
|
||||
#define FLAGS_ENUM(Flagname) Flagname ## __Enum |
||||
#define FLAGS(Flagname, ...) \ |
||||
enum FLAGS_ENUM(Flagname) { \
|
||||
__VA_ARGS__ \
|
||||
FLAGS_ENUM_END(Flagname) \
|
||||
}; \
|
||||
DECLARE_FLAGS_SIZE(FLAGS_ENUM(Flagname), Flagname, FLAGS_ENUM_END(Flagname)) \
|
||||
DECLARE_FLAGS_OPERATORS(Flagname) |
||||
|
||||
#endif // INNOEXTRACT_FLAGS_HPP
|
||||
@ -0,0 +1,87 @@
|
||||
|
||||
#include "LoadingUtils.hpp" |
||||
|
||||
#include <iterator> |
||||
|
||||
#include <iconv.h> |
||||
#include <errno.h> |
||||
|
||||
#include "Output.hpp" |
||||
#include "Utils.hpp" |
||||
|
||||
void BinaryString::loadInto(std::istream & is, std::string & target) { |
||||
|
||||
size_t length = loadNumber<u32>(is); |
||||
if(is.fail()) { |
||||
return; |
||||
} |
||||
|
||||
target.resize(length); |
||||
is.read(&target[0], length); |
||||
} |
||||
|
||||
static void convert(iconv_t converter, const std::string & from, std::string & to) { |
||||
|
||||
const char * inbuf = from.data(); |
||||
size_t insize = from.size(); |
||||
|
||||
size_t outbase = 0; |
||||
|
||||
if(!insize) { |
||||
to.clear(); |
||||
return; |
||||
} |
||||
|
||||
iconv(converter, NULL, NULL, NULL, NULL); |
||||
|
||||
while(insize) { |
||||
|
||||
to.resize(outbase + insize); |
||||
|
||||
char * outbuf = &to[0] + outbase; |
||||
size_t outsize = to.size() - outbase; |
||||
|
||||
size_t ret = iconv(converter, const_cast<char**>(&inbuf), &insize, &outbuf, &outsize); |
||||
if(ret == size_t(-1) && errno != E2BIG) { |
||||
error << "iconv error"; |
||||
to.clear(); |
||||
return; |
||||
} |
||||
|
||||
outbase = to.size() - outsize; |
||||
} |
||||
|
||||
} |
||||
|
||||
void AnsiString::loadInto(std::istream & is, std::string & target) { |
||||
|
||||
std::string temp; |
||||
BinaryString::loadInto(is, temp); |
||||
|
||||
static iconv_t converter = NULL; |
||||
if(!converter) { |
||||
converter = iconv_open("UTF-8", "CP1252"); |
||||
if(!converter) { |
||||
error << "missing CP1252 -> UTF-8 converter"; |
||||
} |
||||
} |
||||
|
||||
convert(converter, temp, target); |
||||
} |
||||
|
||||
void WideString::loadInto(std::istream & is, std::string & target) { |
||||
|
||||
std::string temp; |
||||
BinaryString::loadInto(is, temp); |
||||
|
||||
static iconv_t converter = NULL; |
||||
if(!converter) { |
||||
converter = iconv_open("UTF-8", "UTF-16"); |
||||
if(!converter) { |
||||
error << "missing UTF-16 -> UTF-8 converter"; |
||||
} |
||||
} |
||||
|
||||
convert(converter, temp, target); |
||||
|
||||
} |
||||
@ -0,0 +1,119 @@
|
||||
|
||||
#ifndef INNOEXTRACT_LOADINGUTILS_HPP |
||||
#define INNOEXTRACT_LOADINGUTILS_HPP |
||||
|
||||
#include <iostream> |
||||
#include <string> |
||||
#include <limits> |
||||
#include <boost/detail/endian.hpp> |
||||
#include "Types.h" |
||||
|
||||
inline u8 fromLittleEndian(u8 value) { return value; } |
||||
inline s8 fromLittleEndian(s8 value) { return value; } |
||||
|
||||
#ifdef BOOST_LITTLE_ENDIAN |
||||
|
||||
inline u16 fromLittleEndian(u16 value) { return value; } |
||||
inline u32 fromLittleEndian(u32 value) { return value; } |
||||
inline u64 fromLittleEndian(u64 value) { return value; } |
||||
inline s16 fromLittleEndian(s16 value) { return value; } |
||||
inline s32 fromLittleEndian(s32 value) { return value; } |
||||
inline s64 fromLittleEndian(s64 value) { return value; } |
||||
|
||||
#else |
||||
|
||||
// TODO implement!
|
||||
#error "Host endianness not supported!" |
||||
|
||||
#endif |
||||
|
||||
struct BinaryString { |
||||
|
||||
std::string & data; |
||||
|
||||
inline BinaryString(std::string & target) : data(target) { } |
||||
|
||||
static void loadInto(std::istream & is, std::string & target); |
||||
|
||||
}; |
||||
inline std::istream & operator>>(std::istream & is, const BinaryString & str) { |
||||
BinaryString::loadInto(is, str.data); |
||||
return is; |
||||
} |
||||
|
||||
struct AnsiString { |
||||
|
||||
std::string & data; |
||||
|
||||
inline AnsiString(std::string & target) : data(target) { } |
||||
|
||||
static void loadInto(std::istream & is, std::string & target); |
||||
|
||||
}; |
||||
|
||||
inline std::istream & operator>>(std::istream & is, const AnsiString & str) { |
||||
AnsiString::loadInto(is, str.data); |
||||
return is; |
||||
} |
||||
|
||||
struct WideString { |
||||
|
||||
std::string & data; |
||||
bool wide; |
||||
|
||||
inline WideString(std::string & target, bool _wide /*= true*/) : data(target), wide(_wide) { } |
||||
|
||||
static void loadInto(std::istream & is, std::string & target); |
||||
|
||||
}; |
||||
|
||||
inline std::istream & operator>>(std::istream & is, const WideString & str) { |
||||
str.wide ? WideString::loadInto(is, str.data) : AnsiString::loadInto(is, str.data); |
||||
return is; |
||||
} |
||||
|
||||
template <class T> |
||||
inline T load(std::istream & is) { |
||||
T value; |
||||
is.read(reinterpret_cast<char *>(&value), sizeof(value)); |
||||
return value; |
||||
} |
||||
|
||||
template <class T> |
||||
inline T loadNumber(std::istream & is) { |
||||
return fromLittleEndian(load<T>(is)); |
||||
} |
||||
|
||||
template <class Base, size_t Bits, bool Signed = std::numeric_limits<Base>::is_signed> |
||||
struct compatible_integer { typedef void type; }; |
||||
template <class Base> |
||||
struct compatible_integer<Base, 8, false> { typedef u8 type; }; |
||||
template <class Base> |
||||
struct compatible_integer<Base, 8, true> { typedef s8 type; }; |
||||
template <class Base> |
||||
struct compatible_integer<Base, 16, false> { typedef u16 type; }; |
||||
template <class Base> |
||||
struct compatible_integer<Base, 16, true> { typedef s16 type; }; |
||||
template <class Base> |
||||
struct compatible_integer<Base, 32, false> { typedef u32 type; }; |
||||
template <class Base> |
||||
struct compatible_integer<Base, 32, true> { typedef s32 type; }; |
||||
template <class Base> |
||||
struct compatible_integer<Base, 64, false> { typedef u64 type; }; |
||||
template <class Base> |
||||
struct compatible_integer<Base, 64, true> { typedef s64 type; }; |
||||
|
||||
template <class T> |
||||
T loadNumber(std::istream & is, size_t bits) { |
||||
if(bits == 8) { |
||||
return loadNumber<typename compatible_integer<T, 8>::type>(is); |
||||
} else if(bits == 16) { |
||||
return loadNumber<typename compatible_integer<T, 16>::type>(is); |
||||
} else if(bits == 32) { |
||||
return loadNumber<typename compatible_integer<T, 32>::type>(is); |
||||
} else { |
||||
return loadNumber<typename compatible_integer<T, 64>::type>(is); |
||||
} |
||||
} |
||||
|
||||
#endif // INNOEXTRACT_LOADINGUTILS_HPP
|
||||
@ -0,0 +1,8 @@
|
||||
|
||||
#include "Output.hpp" |
||||
|
||||
namespace color { |
||||
|
||||
shell_command current = color::reset; |
||||
|
||||
} |
||||
@ -0,0 +1,66 @@
|
||||
|
||||
#ifndef INNOEXTRACT_COLOROUT_HPP |
||||
#define INNOEXTRACT_COLOROUT_HPP |
||||
|
||||
#include <iostream> |
||||
#include <iomanip> |
||||
|
||||
namespace color { |
||||
|
||||
struct shell_command { |
||||
|
||||
int c0; |
||||
int c1; |
||||
|
||||
}; |
||||
|
||||
const shell_command reset = { 0, 0 }; |
||||
|
||||
const shell_command black = { 1, 30 }; |
||||
const shell_command red = { 1, 31 }; |
||||
const shell_command green = { 1, 32 }; |
||||
const shell_command yellow = { 1, 33 }; |
||||
const shell_command blue = { 1, 34 }; |
||||
const shell_command magenta = { 1, 35 }; |
||||
const shell_command cyan = { 1, 36 }; |
||||
const shell_command white = { 1, 37 }; |
||||
|
||||
const shell_command dim_black = { 0, 30 }; |
||||
const shell_command dim_red = { 0, 31 }; |
||||
const shell_command dim_green = { 0, 32 }; |
||||
const shell_command dim_yellow = { 0, 33 }; |
||||
const shell_command dim_blue = { 0, 34 }; |
||||
const shell_command dim_magenta = { 0, 35 }; |
||||
const shell_command dim_cyan = { 0, 36 }; |
||||
const shell_command dim_white = { 0, 37 }; |
||||
|
||||
extern shell_command current; |
||||
|
||||
}; |
||||
|
||||
inline std::ostream & operator<<(std::ostream & os, const color::shell_command command) { |
||||
color::current = command; |
||||
std::ios_base::fmtflags old = os.flags(); |
||||
os << "\x1B[" << std::dec << command.c0 << ';' << command.c1 << 'm'; |
||||
os.setf(old, std::ios_base::basefield); |
||||
return os; |
||||
} |
||||
|
||||
struct error_base { |
||||
|
||||
color::shell_command previous; |
||||
|
||||
inline error_base(color::shell_command type) : previous(color::current) { |
||||
std::cerr << type << "!! "; |
||||
} |
||||
|
||||
inline ~error_base() { |
||||
std::cerr << previous << std::endl; |
||||
} |
||||
|
||||
}; |
||||
|
||||
#define error (error_base(color::red), std::cerr) |
||||
#define warning (error_base(color::yellow), std::cerr) |
||||
|
||||
#endif // INNOEXTRACT_COLOROUT_HPP
|
||||
@ -0,0 +1,586 @@
|
||||
|
||||
#include "SetupHeader.hpp" |
||||
|
||||
#include <cstdio> |
||||
#include <cstring> |
||||
#include <boost/static_assert.hpp> |
||||
|
||||
#include "LoadingUtils.hpp" |
||||
#include "SetupHeaderFormat.hpp" |
||||
#include "Utils.hpp" |
||||
|
||||
void SetupVersionData::load(std::istream & is, const InnoVersion & version) { |
||||
|
||||
if(version <= INNO_VERSION(1, 2, 16)) { // in 1.2.16, not in 1.3.25
|
||||
winVersion = loadNumber<u16>(is); |
||||
ntVersion = loadNumber<u16>(is); |
||||
ntServicePack = 0; |
||||
} else { |
||||
winVersion = loadNumber<u32>(is); |
||||
ntVersion = loadNumber<u32>(is); |
||||
ntServicePack = loadNumber<u16>(is); |
||||
} |
||||
|
||||
} |
||||
|
||||
std::ostream & operator<<(std::ostream & os, const SetupVersionData & svd) { |
||||
return os << " win " << svd.winVersion << " nt " << svd.ntVersion << " service pack " << svd.ntServicePack; |
||||
} |
||||
|
||||
void SetupHeader::load(std::istream & is, const InnoVersion & version) { |
||||
|
||||
options = 0; |
||||
|
||||
if(version <= INNO_VERSION(1, 2, 16)) { |
||||
loadNumber<u32>(is); // uncompressed size of the setup header structure
|
||||
} |
||||
|
||||
is >> WideString(appName, version.unicode); |
||||
is >> WideString(appVerName, version.unicode); |
||||
if(version > INNO_VERSION(1, 2, 16)) { // not in 1.2.16, in 1.3.25
|
||||
is >> WideString(appId, version.unicode); |
||||
} |
||||
is >> WideString(appCopyright, version.unicode); |
||||
if(version > INNO_VERSION(1, 2, 16)) { // not in 1.2.16, in 1.3.25
|
||||
is >> WideString(appPublisher, version.unicode); |
||||
is >> WideString(appPublisherURL, version.unicode); |
||||
} else { |
||||
appPublisher.clear(), appPublisherURL.clear(); |
||||
} |
||||
if(version >= INNO_VERSION(5, 1, 13)) { |
||||
is >> WideString(appSupportPhone, version.unicode); |
||||
} else { |
||||
appSupportPhone.clear(); |
||||
} |
||||
if(version > INNO_VERSION(1, 2, 16)) { // not in 1.2.16, in 1.3.25
|
||||
is >> WideString(appSupportURL, version.unicode); |
||||
is >> WideString(appUpdatesURL, version.unicode); |
||||
is >> WideString(appVersion, version.unicode); |
||||
} else { |
||||
appSupportURL.clear(), appUpdatesURL.clear(), appVersion.clear(); |
||||
} |
||||
is >> WideString(defaultDirName, version.unicode); |
||||
is >> WideString(defaultGroupName, version.unicode); |
||||
if(version < INNO_VERSION(3, 0, 0)) { |
||||
is >> AnsiString(uninstallIconName); |
||||
} else { |
||||
uninstallIconName.clear(); |
||||
} |
||||
is >> WideString(baseFilename, version.unicode); |
||||
if(version > INNO_VERSION(1, 2, 16)) { // not in 1.2.16, in 1.3.25
|
||||
if(version < INNO_VERSION(5, 2, 5)) { |
||||
is >> AnsiString(licenseText); |
||||
is >> AnsiString(infoBeforeText); |
||||
is >> AnsiString(infoAfterText); |
||||
} |
||||
is >> WideString(uninstallFilesDir, version.unicode); |
||||
is >> WideString(uninstallDisplayName, version.unicode); |
||||
is >> WideString(uninstallDisplayIcon, version.unicode); |
||||
is >> WideString(appMutex, version.unicode); |
||||
} else { |
||||
licenseText.clear(), infoBeforeText.clear(), infoAfterText.clear(); |
||||
uninstallFilesDir.clear(), uninstallDisplayName.clear(); |
||||
uninstallDisplayIcon.clear(), appMutex.clear(); |
||||
} |
||||
if(version >= INNO_VERSION(3, 0, 0)) { |
||||
is >> WideString(defaultUserInfoName, version.unicode); |
||||
is >> WideString(defaultUserInfoOrg, version.unicode); |
||||
} else { |
||||
defaultUserInfoName.clear(), defaultUserInfoOrg.clear(); |
||||
} |
||||
if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { |
||||
is >> WideString(defaultUserInfoSerial, version.unicode); |
||||
if(version < INNO_VERSION(5, 2, 5)) { |
||||
is >> BinaryString(compiledCodeText); |
||||
} |
||||
} else { |
||||
defaultUserInfoSerial.clear(), compiledCodeText.clear(); |
||||
} |
||||
if(version >= INNO_VERSION(4, 2, 4)) { |
||||
is >> WideString(appReadmeFile, version.unicode); |
||||
is >> WideString(appContact, version.unicode); |
||||
is >> WideString(appComments, version.unicode); |
||||
is >> WideString(appModifyPath, version.unicode); |
||||
} else { |
||||
appReadmeFile.clear(), appContact.clear(); |
||||
appComments.clear(), appModifyPath.clear(); |
||||
} |
||||
if(version >= INNO_VERSION(5, 3, 8)) { |
||||
is >> WideString(createUninstallRegKey, version.unicode); |
||||
} else { |
||||
createUninstallRegKey.clear(); |
||||
} |
||||
if(version >= INNO_VERSION(5, 3, 10)) { |
||||
is >> WideString(uninstallable, version.unicode); |
||||
} else { |
||||
uninstallable.clear(); |
||||
} |
||||
if(version >= INNO_VERSION(5, 2, 5)) { |
||||
is >> AnsiString(licenseText); |
||||
is >> AnsiString(infoBeforeText); |
||||
is >> AnsiString(infoAfterText); |
||||
} |
||||
if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) { |
||||
is >> BinaryString(signedUninstallerSignature); |
||||
} else { |
||||
signedUninstallerSignature.clear(); |
||||
} |
||||
if(version >= INNO_VERSION(5, 2, 5)) { |
||||
is >> BinaryString(compiledCodeText); |
||||
} |
||||
|
||||
if(version > INNO_VERSION(1, 3, 26) && !version.unicode) { |
||||
leadBytes = CharSet(is).getBitSet(); |
||||
} else { |
||||
leadBytes = 0; |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 0, 0)) { |
||||
numLanguageEntries = loadNumber<u32>(is); |
||||
} else { |
||||
numLanguageEntries = 0; |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 2, 1)) { |
||||
numCustomMessageEntries = loadNumber<u32>(is); |
||||
} else { |
||||
numCustomMessageEntries = 0; |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 1, 0)) { |
||||
numPermissionEntries = loadNumber<u32>(is); |
||||
} else { |
||||
numPermissionEntries = 0; |
||||
} |
||||
|
||||
if(version > INNO_VERSION(1, 3, 26)) { // not in 1.3.26, in 2.0.8
|
||||
numTypeEntries = loadNumber<u32>(is); |
||||
numComponentEntries = loadNumber<u32>(is); |
||||
numTaskEntries = loadNumber<u32>(is); |
||||
} else { |
||||
numTypeEntries = 0, numComponentEntries = 0, numTaskEntries = 0; |
||||
} |
||||
|
||||
numDirEntries = loadNumber<u32>(is, version.bits); |
||||
numFileEntries = loadNumber<u32>(is, version.bits); |
||||
numFileLocationEntries = loadNumber<u32>(is, version.bits); |
||||
numIconEntries = loadNumber<u32>(is, version.bits); |
||||
numIniEntries = loadNumber<u32>(is, version.bits); |
||||
numRegistryEntries = loadNumber<u32>(is, version.bits); |
||||
numInstallDeleteEntries = loadNumber<u32>(is, version.bits); |
||||
numUninstallDeleteEntries = loadNumber<u32>(is, version.bits); |
||||
numRunEntries = loadNumber<u32>(is, version.bits); |
||||
numUninstallRunEntries = loadNumber<u32>(is, version.bits); |
||||
|
||||
if(version <= INNO_VERSION(1, 2, 16)) { // in 1.2.16, not in 1.3.25
|
||||
licenseSize = loadNumber<u32>(is, version.bits); |
||||
infoBeforeSize = loadNumber<u32>(is, version.bits); |
||||
infoAfterSize = loadNumber<u32>(is, version.bits); |
||||
} else { |
||||
licenseSize = infoBeforeSize = infoAfterSize = 0; |
||||
} |
||||
|
||||
minVersion.load(is, version); |
||||
onlyBelowVersion.load(is, version); |
||||
|
||||
backColor = loadNumber<u32>(is); |
||||
if(version > INNO_VERSION(1, 2, 16)) { // not in 1.2.16, in 1.3.25
|
||||
backColor2 = loadNumber<u32>(is); |
||||
} else { |
||||
backColor2 = 0; |
||||
} |
||||
wizardImageBackColor = loadNumber<u32>(is); |
||||
if(version > INNO_VERSION(1, 3, 26) && version < INNO_VERSION(5, 0, 4)) { // not in 1.3.26, in 2.0.8
|
||||
wizardSmallImageBackColor = loadNumber<u32>(is); |
||||
} else { |
||||
wizardSmallImageBackColor = 0; |
||||
} |
||||
|
||||
if(version < INNO_VERSION(4, 2, 0)) { |
||||
password = loadNumber<s32>(is), passwordType = PlainPassword; |
||||
} else if(version < INNO_VERSION(5, 3, 9)) { |
||||
is.read(passwordMd5, sizeof(passwordMd5)), passwordType = Md5Password; |
||||
} else { |
||||
is.read(passwordSha1, sizeof(passwordSha1)), passwordType = Sha1Password; |
||||
} |
||||
if(version >= INNO_VERSION(4, 2, 2)) { |
||||
is.read(passwordSalt, sizeof(passwordSalt)); |
||||
} else { |
||||
memset(passwordSalt, 0, sizeof(passwordSalt)); |
||||
} |
||||
|
||||
if(version < INNO_VERSION(4, 0, 0)) { |
||||
extraDiskSpaceRequired = loadNumber<s32>(is); |
||||
slicesPerDisk = 0; |
||||
} else { |
||||
extraDiskSpaceRequired = loadNumber<s64>(is); |
||||
slicesPerDisk = loadNumber<s32>(is); |
||||
} |
||||
|
||||
if(version > INNO_VERSION(1, 3, 26) && version < INNO_VERSION(5, 0, 0)) { |
||||
// removed in 5.0.0, not in 1.2.10, not in 1.3.25
|
||||
installMode = StoredEnum<StoredInstallMode>(is).get(); |
||||
} else { |
||||
installMode = NormalInstallMode; |
||||
} |
||||
|
||||
if(version > INNO_VERSION(1, 2, 16)) { // not in 1.2.16, in 1.3.25
|
||||
uninstallLogMode = StoredEnum<StoredUninstallLogMode>(is).get(); |
||||
} else { |
||||
uninstallLogMode = AppendLog; |
||||
} |
||||
|
||||
if(version > INNO_VERSION(1, 3, 26) && version < INNO_VERSION(5, 0, 0)) { |
||||
uninstallStyle = StoredEnum<StoredUninstallStyle>(is).get(); |
||||
} else { |
||||
uninstallStyle = (version < INNO_VERSION(5, 0, 0)) ? ClassicStyle : ModernStyle; |
||||
} |
||||
|
||||
if(version > INNO_VERSION(1, 2, 16)) { // not in 1.2.16, in 1.3.25
|
||||
dirExistsWarning = StoredEnum<StoredDirExistsWarning>(is).get(); |
||||
} else { |
||||
dirExistsWarning = Auto; |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(3, 0, 0) && version < INNO_VERSION(3, 0, 3)) { // only in [3.0.0, 3.0.3)?
|
||||
AutoBoolean val = StoredEnum<StoredRestartComputer>(is).get(); |
||||
switch(val) { |
||||
case Yes: options |= shAlwaysRestart; break; |
||||
case Auto: options |= shRestartIfNeededByRun; break; |
||||
case No: break; |
||||
} |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 3, 7)) { |
||||
privilegesRequired = StoredEnum<StoredPrivileges1>(is).get(); |
||||
} else if(version >= INNO_VERSION(3, 0, 4)) { |
||||
privilegesRequired = StoredEnum<StoredPrivileges0>(is).get(); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 0, 10)) { |
||||
showLanguageDialog = StoredEnum<StoredShowLanguageDialog>(is).get(); |
||||
languageDetectionMethod = StoredEnum<StoredLanguageDetectionMethod>(is).get(); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 3, 9)) { |
||||
compressMethod = StoredEnum<StoredCompressionMethod3>(is).get(); |
||||
} else if(version >= INNO_VERSION(4, 2, 6)) { |
||||
compressMethod = StoredEnum<StoredCompressionMethod2>(is).get(); |
||||
} else if(version >= INNO_VERSION(4, 2, 5)) { |
||||
compressMethod = StoredEnum<StoredCompressionMethod1>(is).get(); |
||||
} else if(version >= INNO_VERSION(4, 1, 5)) { |
||||
compressMethod = StoredEnum<StoredCompressionMethod0>(is).get(); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 0, 2)) { |
||||
architecturesAllowed = StoredFlags<StoredArchitectures>(is).get(); |
||||
architecturesInstallIn64BitMode = StoredFlags<StoredArchitectures>(is).get(); |
||||
} else { |
||||
architecturesAllowed = Architectures::all(); |
||||
architecturesInstallIn64BitMode = Architectures::all(); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) { |
||||
signedUninstallerOrigSize = loadNumber<s32>(is); |
||||
signedUninstallerHdrChecksum = loadNumber<u32>(is); |
||||
} else { |
||||
signedUninstallerOrigSize = signedUninstallerHdrChecksum = 0; |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 3, 3)) { |
||||
disableDirPage = StoredEnum<StoredDisablePage>(is).get(); |
||||
disableProgramGroupPage = StoredEnum<StoredDisablePage>(is).get(); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 3, 6)) { |
||||
uninstallDisplaySize = loadNumber<u32>(is); |
||||
} else { |
||||
uninstallDisplaySize = 0; |
||||
} |
||||
|
||||
|
||||
StoredFlagReader<SetupHeaderOptions> flags; |
||||
|
||||
flags.add(shDisableStartupPrompt); |
||||
if(version < INNO_VERSION(5, 3, 10)) { |
||||
flags.add(shUninstallable); |
||||
} |
||||
flags.add(shCreateAppDir); |
||||
if(version < INNO_VERSION(5, 3, 3)) { |
||||
flags.add(shDisableDirPage); |
||||
} |
||||
if(version <= INNO_VERSION(1, 2, 16)) { |
||||
flags.add(shDisableDirExistsWarning); // only in 1.2.10, not in 1.3.25
|
||||
} |
||||
if(version < INNO_VERSION(5, 3, 3)) { |
||||
flags.add(shDisableProgramGroupPage); |
||||
} |
||||
flags.add(shAllowNoIcons); |
||||
if(version < INNO_VERSION(3, 0, 0) || version >= INNO_VERSION(3, 0, 3)) { |
||||
flags.add(shAlwaysRestart); |
||||
} |
||||
if(version <= INNO_VERSION(1, 2, 16)) { |
||||
flags.add(shBackSolid); // only in 1.2.10, not in 1.3.25
|
||||
} |
||||
flags.add(shAlwaysUsePersonalGroup); |
||||
flags.add(shWindowVisible); |
||||
flags.add(shWindowShowCaption); |
||||
flags.add(shWindowResizable); |
||||
flags.add(shWindowStartMaximized); |
||||
flags.add(shEnableDirDoesntExistWarning); |
||||
if(version < INNO_VERSION(4, 1, 2)) { |
||||
flags.add(shDisableAppendDir); |
||||
} |
||||
flags.add(shPassword); |
||||
flags.add(shAllowRootDirectory); |
||||
flags.add(shDisableFinishedPage); |
||||
|
||||
if(version.bits != 16) { |
||||
if(version < INNO_VERSION(3, 0, 4)) { |
||||
flags.add(shAdminPrivilegesRequired); |
||||
} |
||||
if(version < INNO_VERSION(3, 0, 0)) { |
||||
flags.add(shAlwaysCreateUninstallIcon); |
||||
} |
||||
if(version <= INNO_VERSION(1, 2, 16)) { |
||||
flags.add(shOverwriteUninstRegEntries); // only in 1.2.10, win32-only); not in 1.3.25
|
||||
} |
||||
flags.add(shChangesAssociations); |
||||
} |
||||
|
||||
if(version > INNO_VERSION(1, 2, 16)) { // new after 1.2.16); in 1.3.25
|
||||
if(version < INNO_VERSION(5, 3, 8)) { |
||||
flags.add(shCreateUninstallRegKey); |
||||
} |
||||
flags.add(shUsePreviousAppDir); |
||||
flags.add(shBackColorHorizontal); |
||||
flags.add(shUsePreviousGroup); |
||||
flags.add(shUpdateUninstallLogAppName); |
||||
} |
||||
|
||||
if(version > INNO_VERSION(1, 3, 26)) { // new after 1.3.26
|
||||
flags.add(shUsePreviousSetupType); |
||||
flags.add(shDisableReadyMemo); |
||||
flags.add(shAlwaysShowComponentsList); |
||||
flags.add(shFlatComponentsList); |
||||
flags.add(shShowComponentSizes); |
||||
flags.add(shUsePreviousTasks); |
||||
flags.add(shDisableReadyPage); |
||||
flags.add(shAlwaysShowDirOnReadyPage); |
||||
flags.add(shAlwaysShowGroupOnReadyPage); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(2, 0, 17) && version < INNO_VERSION(4, 1, 5)) { |
||||
flags.add(shBzipUsed); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(2, 0, 18)) { |
||||
flags.add(shAllowUNCPath); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(3, 0, 0)) { |
||||
flags.add(shUserInfoPage); |
||||
flags.add(shUsePreviousUserInfo); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(3, 0, 1)) { |
||||
flags.add(shUninstallRestartComputer); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(3, 0, 3)) { |
||||
flags.add(shRestartIfNeededByRun); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { |
||||
flags.add(shShowTasksTreeLines); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 0, 0) && version < INNO_VERSION(4, 0, 10)) { |
||||
flags.add(shShowLanguageDialog); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 0, 1) && version < INNO_VERSION(4, 0, 10)) { |
||||
flags.add(shDetectLanguageUsingLocale); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 0, 9)) { |
||||
flags.add(shAllowCancelDuringInstall); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 1, 3)) { |
||||
flags.add(shWizardImageStretch); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 1, 8)) { |
||||
flags.add(shAppendDefaultDirName); |
||||
flags.add(shAppendDefaultGroupName); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(4, 2, 2)) { |
||||
flags.add(shEncryptionUsed); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 0, 4)) { |
||||
flags.add(shChangesEnvironment); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 1, 7) && !version.unicode) { |
||||
flags.add(shShowUndisplayableLanguages); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 1, 13)) { |
||||
flags.add(shSetupLogging); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 2, 1)) { |
||||
flags.add(shSignedUninstaller); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 3, 8)) { |
||||
flags.add(shUsePreviousLanguage); |
||||
} |
||||
|
||||
if(version >= INNO_VERSION(5, 3, 9)) { |
||||
flags.add(shDisableWelcomePage); |
||||
} |
||||
|
||||
options |= flags.get(is); |
||||
|
||||
if(version < INNO_VERSION(3, 0, 4)) { |
||||
privilegesRequired = (options & shAdminPrivilegesRequired) ? AdminPriviliges : NoPrivileges; |
||||
} |
||||
|
||||
if(version < INNO_VERSION(4, 0, 10)) { |
||||
showLanguageDialog = (options & shShowLanguageDialog) ? Yes : No; |
||||
languageDetectionMethod = (options & shDetectLanguageUsingLocale) ? LocaleLanguage : UILanguage; |
||||
} |
||||
|
||||
if(version < INNO_VERSION(4, 1, 5)) { |
||||
compressMethod = (options & shBzipUsed) ? BZip2 : Zlib; |
||||
} |
||||
|
||||
if(version < INNO_VERSION(5, 3, 3)) { |
||||
disableDirPage = (options & shDisableDirPage) ? Yes : No; |
||||
disableProgramGroupPage = (options & shDisableProgramGroupPage) ? Yes : No; |
||||
} |
||||
|
||||
} |
||||
|
||||
ENUM_NAMES(SetupHeaderOptions::Enum, "Setup Option", |
||||
"disable startup prompt", |
||||
"create app dir", |
||||
"allow no icons", |
||||
"always restart", |
||||
"always use personal group", |
||||
"window visible", |
||||
"window show caption", |
||||
"window resizable", |
||||
"window start maximized", |
||||
"enable dir doesn't exist warning", |
||||
"password", |
||||
"allow root directory", |
||||
"disable finished page", |
||||
"changes associations", |
||||
"use previous app dir", |
||||
"back color horizontal", |
||||
"use previous group", |
||||
"update uninstall log app name", |
||||
"use previous setup type", |
||||
"disable ready memo", |
||||
"always show components list", |
||||
"flat components list", |
||||
"show component sizes", |
||||
"use previous tasks", |
||||
"disable ready page", |
||||
"always show dir on ready page", |
||||
"always show group on ready page", |
||||
"allow unc path", |
||||
"user info page", |
||||
"use previous user info", |
||||
"uninstall restart computer", |
||||
"restart if needed by run", |
||||
"show tasks tree lines", |
||||
"allow cancel during install", |
||||
"wizard image stretch", |
||||
"append default dir name", |
||||
"append default group name", |
||||
"encrypted", |
||||
"changes environment", |
||||
"show undisplayable languages", |
||||
"setup logging", |
||||
"signed uninstaller", |
||||
"use previous language", |
||||
"disable welcome page", |
||||
"uninstallable", |
||||
"disable dir page", |
||||
"disable program group page", |
||||
"disable append dir", |
||||
"admin privilegesrequired", |
||||
"always create uninstall icon", |
||||
"create uninstall reg key", |
||||
"bzip used", |
||||
"show language dialog", |
||||
"detect language using locale", |
||||
"disable dir exists warning", |
||||
"back solid", |
||||
"overwrite uninst reg entries", |
||||
) |
||||
BOOST_STATIC_ASSERT(EnumSize<SetupHeaderOptions::Enum>::value == EnumNames<SetupHeaderOptions::Enum>::count); |
||||
|
||||
ENUM_NAMES(Architectures::Enum, "Architecture", |
||||
"unknown", |
||||
"x86", |
||||
"amd64", |
||||
"IA64", |
||||
) |
||||
|
||||
ENUM_NAMES(SetupHeader::PasswordType, "Password Type", |
||||
"plain", |
||||
"MD5", |
||||
"SHA1", |
||||
) |
||||
|
||||
ENUM_NAMES(SetupHeader::InstallMode, "Install Mode", |
||||
"normal", |
||||
"silent", |
||||
"very silent", |
||||
) |
||||
|
||||
ENUM_NAMES(SetupHeader::UninstallLogMode, "Uninstall Log Mode", |
||||
"append", |
||||
"new log", |
||||
"overwrite", |
||||
) |
||||
|
||||
ENUM_NAMES(SetupHeader::UninstallStyle, "Uninstall Style", |
||||
"classic", |
||||
"modern", |
||||
) |
||||
|
||||
ENUM_NAMES(SetupHeader::AutoBoolean, "Auto Boolean", |
||||
"auto", |
||||
"no", |
||||
"yes", |
||||
) |
||||
|
||||
ENUM_NAMES(SetupHeader::Privileges, "Privileges", |
||||
"none", |
||||
"power user", |
||||
"admin", |
||||
"lowest", |
||||
) |
||||
|
||||
ENUM_NAMES(SetupHeader::LanguageDetection, "Language Detection", |
||||
"ui language", |
||||
"locale", |
||||
"none", |
||||
) |
||||
|
||||
ENUM_NAMES(SetupHeader::CompressionMethod, "Compression Method", |
||||
"stored", |
||||
"zlib", |
||||
"bzip2", |
||||
"lzma1", |
||||
"lzma2", |
||||
"unknown", |
||||
) |
||||
@ -0,0 +1,307 @@
|
||||
|
||||
#ifndef INNOEXTRACT_SETUPHEADER_HPP |
||||
#define INNOEXTRACT_SETUPHEADER_HPP |
||||
|
||||
#include <stddef.h> |
||||
#include <bitset> |
||||
#include <string> |
||||
#include <iostream> |
||||
#include "Types.h" |
||||
#include "Flags.hpp" |
||||
#include "Enum.hpp" |
||||
#include "Version.hpp" |
||||
|
||||
struct SetupVersionData { |
||||
|
||||
s32 winVersion, ntVersion; // Cardinal
|
||||
s16 ntServicePack; // Word
|
||||
|
||||
void load(std::istream & is, const InnoVersion & version); |
||||
|
||||
}; |
||||
|
||||
std::ostream & operator<<(std::ostream & os, const SetupVersionData & svd); |
||||
|
||||
typedef char MD5Digest[16]; |
||||
typedef char SHA1Digest[20]; |
||||
typedef char SetupSalt[8]; |
||||
|
||||
FLAGS(SetupHeaderOptions, |
||||
|
||||
shDisableStartupPrompt, |
||||
shCreateAppDir, |
||||
shAllowNoIcons, |
||||
shAlwaysRestart, // TODO missing in [3.0.0, 3.0.3)
|
||||
shAlwaysUsePersonalGroup, |
||||
shWindowVisible, |
||||
shWindowShowCaption, |
||||
shWindowResizable, |
||||
shWindowStartMaximized, |
||||
shEnableDirDoesntExistWarning, |
||||
shPassword, |
||||
shAllowRootDirectory, |
||||
shDisableFinishedPage, |
||||
shChangesAssociations, |
||||
shUsePreviousAppDir, |
||||
shBackColorHorizontal, |
||||
shUsePreviousGroup, |
||||
shUpdateUninstallLogAppName, |
||||
shUsePreviousSetupType, |
||||
shDisableReadyMemo, |
||||
shAlwaysShowComponentsList, |
||||
shFlatComponentsList, |
||||
shShowComponentSizes, |
||||
shUsePreviousTasks, |
||||
shDisableReadyPage, |
||||
shAlwaysShowDirOnReadyPage, |
||||
shAlwaysShowGroupOnReadyPage, |
||||
|
||||
// new in 2.0.18
|
||||
shAllowUNCPath, |
||||
|
||||
// new in 3.0.0
|
||||
shUserInfoPage, |
||||
shUsePreviousUserInfo, |
||||
|
||||
// new in 3.0.1
|
||||
shUninstallRestartComputer, |
||||
|
||||
// new in 3.0.3
|
||||
shRestartIfNeededByRun, |
||||
|
||||
// new in 3.0.8
|
||||
shShowTasksTreeLines, |
||||
|
||||
// new in 4.0.9
|
||||
shAllowCancelDuringInstall, |
||||
|
||||
// new in 4.1.3
|
||||
shWizardImageStretch, |
||||
|
||||
// new in 4.1.8
|
||||
shAppendDefaultDirName, |
||||
shAppendDefaultGroupName, |
||||
|
||||
// new in 4.2.2
|
||||
shEncryptionUsed, |
||||
|
||||
// new in 5.0.4
|
||||
shChangesEnvironment, |
||||
|
||||
// new in 5.1.7
|
||||
shShowUndisplayableLanguages, // TODO 5.2.5+: only if not unicode
|
||||
|
||||
// new in 5.1.13
|
||||
shSetupLogging, |
||||
|
||||
// new in 5.2.1
|
||||
shSignedUninstaller, |
||||
|
||||
// new in 5.3.8
|
||||
shUsePreviousLanguage, |
||||
|
||||
// new in 5.3.9
|
||||
shDisableWelcomePage, |
||||
|
||||
// Obsolete flags
|
||||
shUninstallable, // TODO removed in 5.3.10
|
||||
shDisableDirPage, // TODO removed in 5.3.3
|
||||
shDisableProgramGroupPage, // TODO removed in 5.3.3
|
||||
shDisableAppendDir, // TODO removed in 4.1.2
|
||||
shAdminPrivilegesRequired, // TODO removed in 3.0.4
|
||||
shAlwaysCreateUninstallIcon, // TODO removed in 3.0.0
|
||||
shCreateUninstallRegKey, // TODO removed in 5.3.8
|
||||
shBzipUsed, // only in [2.0.17, 4.1.5)
|
||||
shShowLanguageDialog, // only in [4.0.0, 4.0.10)
|
||||
shDetectLanguageUsingLocale, // only in [4.0.1, 4.0.10)
|
||||
|
||||
// only in very old versions:
|
||||
shDisableDirExistsWarning, |
||||
shBackSolid, |
||||
shOverwriteUninstRegEntries, |
||||
) |
||||
|
||||
NAMED_ENUM(SetupHeaderOptions::Enum) |
||||
|
||||
FLAGS(Architectures, |
||||
ArchitectureUnknown, |
||||
ArchitectureX86, |
||||
ArchitectureAmd64, |
||||
ArchitectureIA64, |
||||
) |
||||
|
||||
NAMED_ENUM(Architectures::Enum) |
||||
|
||||
struct SetupHeader { |
||||
|
||||
// Setup data header.
|
||||
|
||||
std::string appName; |
||||
std::string appVerName; |
||||
std::string appId; |
||||
std::string appCopyright; |
||||
std::string appPublisher; |
||||
std::string appPublisherURL; |
||||
std::string appSupportPhone; |
||||
std::string appSupportURL; |
||||
std::string appUpdatesURL; |
||||
std::string appVersion; |
||||
std::string defaultDirName; |
||||
std::string defaultGroupName; |
||||
std::string uninstallIconName; |
||||
std::string baseFilename; |
||||
std::string uninstallFilesDir; |
||||
std::string uninstallDisplayName; |
||||
std::string uninstallDisplayIcon; |
||||
std::string appMutex; |
||||
std::string defaultUserInfoName; |
||||
std::string defaultUserInfoOrg; |
||||
std::string defaultUserInfoSerial; |
||||
std::string appReadmeFile; |
||||
std::string appContact; |
||||
std::string appComments; |
||||
std::string appModifyPath; |
||||
std::string createUninstallRegKey; |
||||
std::string uninstallable; |
||||
std::string licenseText; |
||||
std::string infoBeforeText; |
||||
std::string infoAfterText; |
||||
std::string signedUninstallerSignature; |
||||
std::string compiledCodeText; |
||||
|
||||
std::bitset<256> leadBytes; |
||||
|
||||
size_t numLanguageEntries; |
||||
size_t numCustomMessageEntries; |
||||
size_t numPermissionEntries; |
||||
size_t numTypeEntries; |
||||
size_t numComponentEntries; |
||||
size_t numTaskEntries; |
||||
size_t numDirEntries; |
||||
size_t numFileEntries; |
||||
size_t numFileLocationEntries; |
||||
size_t numIconEntries; |
||||
size_t numIniEntries; |
||||
size_t numRegistryEntries; |
||||
size_t numInstallDeleteEntries; |
||||
size_t numUninstallDeleteEntries; |
||||
size_t numRunEntries; |
||||
size_t numUninstallRunEntries; |
||||
|
||||
size_t licenseSize; |
||||
size_t infoBeforeSize; |
||||
size_t infoAfterSize; |
||||
|
||||
SetupVersionData minVersion; |
||||
SetupVersionData onlyBelowVersion; |
||||
|
||||
Color backColor; |
||||
Color backColor2; |
||||
Color wizardImageBackColor; |
||||
Color wizardSmallImageBackColor; |
||||
|
||||
enum PasswordType { |
||||
PlainPassword, |
||||
Md5Password, |
||||
Sha1Password |
||||
}; |
||||
union { |
||||
s32 password; // probably CRC32
|
||||
MD5Digest passwordMd5; |
||||
SHA1Digest passwordSha1; |
||||
}; |
||||
PasswordType passwordType; |
||||
SetupSalt passwordSalt;
|
||||
|
||||
s64 extraDiskSpaceRequired; |
||||
size_t slicesPerDisk; |
||||
|
||||
enum InstallMode { |
||||
NormalInstallMode, |
||||
SilentInstallMode, |
||||
VerySilentInstallMode, |
||||
}; |
||||
InstallMode installMode; |
||||
|
||||
enum UninstallLogMode { |
||||
AppendLog, |
||||
NewLog, |
||||
OverwriteLog |
||||
}; |
||||
UninstallLogMode uninstallLogMode; |
||||
|
||||
enum UninstallStyle { |
||||
ClassicStyle, |
||||
ModernStyle |
||||
}; |
||||
UninstallStyle uninstallStyle; |
||||
|
||||
enum AutoBoolean { |
||||
Auto, |
||||
No, |
||||
Yes |
||||
}; |
||||
|
||||
AutoBoolean dirExistsWarning; |
||||
|
||||
enum Privileges { |
||||
NoPrivileges, |
||||
PowerUserPrivileges, |
||||
AdminPriviliges, |
||||
LowestPrivileges |
||||
}; |
||||
Privileges privilegesRequired; |
||||
|
||||
AutoBoolean showLanguageDialog; |
||||
|
||||
enum LanguageDetection { |
||||
UILanguage, |
||||
LocaleLanguage, |
||||
NoLanguageDetection |
||||
}; |
||||
LanguageDetection languageDetectionMethod; |
||||
|
||||
enum CompressionMethod { |
||||
Stored, |
||||
Zlib, |
||||
BZip2, |
||||
LZMA1, |
||||
LZMA2, |
||||
Unknown |
||||
}; |
||||
CompressionMethod compressMethod; |
||||
|
||||
Architectures architecturesAllowed; |
||||
Architectures architecturesInstallIn64BitMode; |
||||
|
||||
u64 signedUninstallerOrigSize; |
||||
u32 signedUninstallerHdrChecksum; |
||||
|
||||
AutoBoolean disableDirPage; |
||||
AutoBoolean disableProgramGroupPage; |
||||
|
||||
size_t uninstallDisplaySize; |
||||
|
||||
SetupHeaderOptions options; |
||||
|
||||
void load(std::istream & is, const InnoVersion & version); |
||||
|
||||
}; |
||||
|
||||
NAMED_ENUM(SetupHeader::PasswordType) |
||||
|
||||
NAMED_ENUM(SetupHeader::InstallMode) |
||||
|
||||
NAMED_ENUM(SetupHeader::UninstallLogMode) |
||||
|
||||
NAMED_ENUM(SetupHeader::UninstallStyle) |
||||
|
||||
NAMED_ENUM(SetupHeader::AutoBoolean) |
||||
|
||||
NAMED_ENUM(SetupHeader::Privileges) |
||||
|
||||
NAMED_ENUM(SetupHeader::LanguageDetection) |
||||
|
||||
NAMED_ENUM(SetupHeader::CompressionMethod) |
||||
|
||||
#endif // INNOEXTRACT_SETUPHEADER_HPP
|
||||
@ -0,0 +1,181 @@
|
||||
|
||||
#include "Version.hpp" |
||||
|
||||
#include <cstring> |
||||
|
||||
#include <boost/static_assert.hpp> |
||||
|
||||
#include "Utils.hpp" |
||||
|
||||
typedef char StoredLegacySetupDataVersion[12]; |
||||
|
||||
struct KnownLegacySetupDataVersion { |
||||
|
||||
char name[13]; // terminating 0 byte is ignored
|
||||
|
||||
InnoVersionConstant version; |
||||
|
||||
unsigned char bits; |
||||
|
||||
}; |
||||
|
||||
const KnownLegacySetupDataVersion knownLegacySetupDataVersions[] = { |
||||
{ "i1.2.10--16\x1a", INNO_VERSION(1, 2, 10), 16 }, |
||||
{ "i1.2.10--32\x1a", INNO_VERSION(1, 2, 10), 32 }, |
||||
}; |
||||
|
||||
typedef char StoredSetupDataVersion[64]; |
||||
|
||||
struct KnownSetupDataVersion { |
||||
|
||||
StoredSetupDataVersion name; |
||||
|
||||
InnoVersionConstant version; |
||||
bool unicode; |
||||
|
||||
}; |
||||
|
||||
const KnownSetupDataVersion knownSetupDataVersions[] = { |
||||
{ "Inno Setup Setup Data (1.3.25)", INNO_VERSION_EXT(1, 3, 25, 0) }, |
||||
{ "Inno Setup Setup Data (2.0.8)", INNO_VERSION_EXT(2, 0, 8, 0) }, |
||||
{ "Inno Setup Setup Data (2.0.11)", INNO_VERSION_EXT(2, 0, 11, 0) }, |
||||
{ "Inno Setup Setup Data (2.0.17)", INNO_VERSION_EXT(2, 0, 17, 0) }, |
||||
{ "Inno Setup Setup Data (2.0.18)", INNO_VERSION_EXT(2, 0, 18, 0) }, |
||||
{ "Inno Setup Setup Data (3.0.0a)", INNO_VERSION_EXT(3, 0, 0, 0) }, |
||||
{ "Inno Setup Setup Data (3.0.1)", INNO_VERSION_EXT(3, 0, 1, 0) }, |
||||
{ "Inno Setup Setup Data (3.0.3)", INNO_VERSION_EXT(3, 0, 3, 0) }, |
||||
{ "Inno Setup Setup Data (3.0.5)", INNO_VERSION_EXT(3, 0, 5, 0) }, |
||||
{ "My Inno Setup Extensions Setup Data (3.0.6.1)", INNO_VERSION_EXT(3, 0, 6, 1) }, |
||||
{ "Inno Setup Setup Data (4.0.0a)", INNO_VERSION_EXT(4, 0, 0, 0) }, |
||||
{ "Inno Setup Setup Data (4.0.1)", INNO_VERSION_EXT(4, 0, 1, 0) }, |
||||
{ "Inno Setup Setup Data (4.0.3)", INNO_VERSION_EXT(4, 0, 3, 0) }, |
||||
{ "Inno Setup Setup Data (4.0.5)", INNO_VERSION_EXT(4, 0, 5, 0) }, |
||||
{ "Inno Setup Setup Data (4.0.9)", INNO_VERSION_EXT(4, 0, 9, 0) }, |
||||
{ "Inno Setup Setup Data (4.0.10)", INNO_VERSION_EXT(4, 0, 10, 0) }, |
||||
{ "Inno Setup Setup Data (4.0.11)", INNO_VERSION_EXT(4, 0, 11, 0) }, |
||||
{ "Inno Setup Setup Data (4.1.0)", INNO_VERSION_EXT(4, 1, 0, 0) }, |
||||
{ "Inno Setup Setup Data (4.1.2)", INNO_VERSION_EXT(4, 1, 2, 0) }, |
||||
{ "Inno Setup Setup Data (4.1.3)", INNO_VERSION_EXT(4, 1, 3, 0) }, |
||||
{ "Inno Setup Setup Data (4.1.4)", INNO_VERSION_EXT(4, 1, 4, 0) }, |
||||
{ "Inno Setup Setup Data (4.1.5)", INNO_VERSION_EXT(4, 1, 5, 0) }, |
||||
{ "Inno Setup Setup Data (4.1.6)", INNO_VERSION_EXT(4, 1, 6, 0) }, |
||||
{ "Inno Setup Setup Data (4.1.8)", INNO_VERSION_EXT(4, 1, 8, 0) }, |
||||
{ "Inno Setup Setup Data (4.2.0)", INNO_VERSION_EXT(4, 2, 0, 0) }, |
||||
{ "Inno Setup Setup Data (4.2.1)", INNO_VERSION_EXT(4, 2, 1, 0) }, |
||||
{ "Inno Setup Setup Data (4.2.2)", INNO_VERSION_EXT(4, 2, 2, 0) }, |
||||
{ "Inno Setup Setup Data (4.2.3)", INNO_VERSION_EXT(4, 2, 3, 0) }, |
||||
{ "Inno Setup Setup Data (4.2.5)", INNO_VERSION_EXT(4, 2, 5, 0) }, |
||||
{ "Inno Setup Setup Data (4.2.6)", INNO_VERSION_EXT(4, 2, 6, 0) }, |
||||
{ "Inno Setup Setup Data (5.0.0)", INNO_VERSION_EXT(5, 0, 0, 0) }, |
||||
{ "Inno Setup Setup Data (5.0.1)", INNO_VERSION_EXT(5, 0, 1, 0) }, |
||||
{ "Inno Setup Setup Data (5.0.3)", INNO_VERSION_EXT(5, 0, 3, 0) }, |
||||
{ "Inno Setup Setup Data (5.0.4)", INNO_VERSION_EXT(5, 0, 4, 0) }, |
||||
{ "Inno Setup Setup Data (5.1.0)", INNO_VERSION_EXT(5, 1, 0, 0) }, |
||||
{ "Inno Setup Setup Data (5.1.2)", INNO_VERSION_EXT(5, 1, 2, 0) }, |
||||
{ "Inno Setup Setup Data (5.1.7)", INNO_VERSION_EXT(5, 1, 7, 0) }, |
||||
{ "Inno Setup Setup Data (5.1.10)", INNO_VERSION_EXT(5, 1, 10, 0) }, |
||||
{ "Inno Setup Setup Data (5.1.13)", INNO_VERSION_EXT(5, 1, 13, 0) }, |
||||
{ "Inno Setup Setup Data (5.2.0)", INNO_VERSION_EXT(5, 2, 0, 0) }, |
||||
{ "Inno Setup Setup Data (5.2.1)", INNO_VERSION_EXT(5, 2, 1, 0) }, |
||||
{ "Inno Setup Setup Data (5.2.3)", INNO_VERSION_EXT(5, 2, 3, 0) }, |
||||
{ "Inno Setup Setup Data (5.2.5)", INNO_VERSION_EXT(5, 2, 5, 0) }, |
||||
{ "Inno Setup Setup Data (5.2.5) (u)", INNO_VERSION_EXT(5, 2, 5, 0), true }, |
||||
{ "Inno Setup Setup Data (5.3.0)", INNO_VERSION_EXT(5, 3, 0, 0) }, |
||||
{ "Inno Setup Setup Data (5.3.0) (u)", INNO_VERSION_EXT(5, 3, 0, 0), true }, |
||||
{ "Inno Setup Setup Data (5.3.3)", INNO_VERSION_EXT(5, 3, 3, 0) }, |
||||
{ "Inno Setup Setup Data (5.3.3) (u)", INNO_VERSION_EXT(5, 3, 3, 0), true }, |
||||
{ "Inno Setup Setup Data (5.3.5)", INNO_VERSION_EXT(5, 3, 5, 0) }, |
||||
{ "Inno Setup Setup Data (5.3.5) (u)", INNO_VERSION_EXT(5, 3, 5, 0), true }, |
||||
{ "Inno Setup Setup Data (5.3.6)", INNO_VERSION_EXT(5, 3, 6, 0) }, |
||||
{ "Inno Setup Setup Data (5.3.6) (u)", INNO_VERSION_EXT(5, 3, 6, 0), true }, |
||||
{ "Inno Setup Setup Data (5.3.7)", INNO_VERSION_EXT(5, 3, 7, 0) }, |
||||
{ "Inno Setup Setup Data (5.3.7) (u)", INNO_VERSION_EXT(5, 3, 7, 0), true }, |
||||
{ "Inno Setup Setup Data (5.3.8)", INNO_VERSION_EXT(5, 3, 8, 0) }, |
||||
{ "Inno Setup Setup Data (5.3.8) (u)", INNO_VERSION_EXT(5, 3, 8, 0), true }, |
||||
{ "Inno Setup Setup Data (5.3.9)", INNO_VERSION_EXT(5, 3, 9, 0) }, |
||||
{ "Inno Setup Setup Data (5.3.9) (u)", INNO_VERSION_EXT(5, 3, 9, 0), true }, |
||||
{ "Inno Setup Setup Data (5.3.10)", INNO_VERSION_EXT(5, 3, 10, 0) }, |
||||
{ "Inno Setup Setup Data (5.3.10) (u)", INNO_VERSION_EXT(5, 3, 10, 0), true }, |
||||
{ "Inno Setup Setup Data (5.4.2)", INNO_VERSION_EXT(5, 4, 2, 0) }, |
||||
{ "Inno Setup Setup Data (5.4.2) (u)", INNO_VERSION_EXT(5, 4, 2, 0), true }, |
||||
}; |
||||
using std::cout; |
||||
using std::string; |
||||
using std::endl; |
||||
|
||||
std::ostream & operator<<(std::ostream & os, const InnoVersion & v) { |
||||
|
||||
os << (v.version >> 24) << '.' << ((v.version >> 16) & 0xff) << '.' << ((v.version >> 8) & 0xff); |
||||
if(v.version & 0xff) { |
||||
os << '.' << (v.version & 0xff); |
||||
} |
||||
|
||||
if(v.unicode) { |
||||
os << " (unicode)"; |
||||
} |
||||
|
||||
if(v.bits != 32) { |
||||
os << " (" << int(v.bits) << "-bit)"; |
||||
} |
||||
|
||||
if(!v.known) { |
||||
os << " [unsupported]"; |
||||
} |
||||
|
||||
return os; |
||||
} |
||||
|
||||
void InnoVersion::load(std::istream & is) { |
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(StoredLegacySetupDataVersion) <= sizeof(StoredSetupDataVersion)); |
||||
|
||||
StoredLegacySetupDataVersion legacyVersion; |
||||
is.read(legacyVersion, sizeof(legacyVersion)); |
||||
|
||||
if(legacyVersion[0] == 'i' && legacyVersion[sizeof(legacyVersion) - 1] == '\x1a') { |
||||
|
||||
cout << "found legacy version: \"" << safestring(legacyVersion, sizeof(legacyVersion) - 1) << '"' << endl; |
||||
|
||||
for(size_t i = 0; i < ARRAY_SIZE(knownLegacySetupDataVersions); i++) { |
||||
if(!memcmp(legacyVersion, knownLegacySetupDataVersions[i].name, sizeof(legacyVersion))) { |
||||
version = knownLegacySetupDataVersions[i].version; |
||||
bits = knownLegacySetupDataVersions[i].bits; |
||||
unicode = false; |
||||
known = true; |
||||
cout << "-> version is known" << endl; |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// TODO autodetect version
|
||||
|
||||
known = false; |
||||
|
||||
cout << "-> unknown version" << endl; |
||||
throw new string("bad version"); |
||||
} |
||||
|
||||
StoredSetupDataVersion storedVersion; |
||||
memcpy(storedVersion, legacyVersion, sizeof(legacyVersion)); |
||||
is.read(storedVersion + sizeof(legacyVersion), sizeof(storedVersion) - sizeof(legacyVersion)); |
||||
|
||||
cout << "found version: \"" << safestring(storedVersion) << '"' << endl; |
||||
|
||||
for(size_t i = 0; i < ARRAY_SIZE(knownSetupDataVersions); i++) { |
||||
if(!memcmp(storedVersion, knownSetupDataVersions[i].name, sizeof(storedVersion))) { |
||||
version = knownSetupDataVersions[i].version; |
||||
bits = 32; |
||||
unicode = knownSetupDataVersions[i].unicode; |
||||
known = true; |
||||
cout << "-> version is known" << endl; |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// TODO autodetect version
|
||||
|
||||
known = false; |
||||
|
||||
cout << "-> unknown version" << endl; |
||||
throw new string("bad version"); |
||||
} |
||||
@ -0,0 +1,64 @@
|
||||
|
||||
#ifndef INNOEXTRACT_VERSION_HPP |
||||
#define INNOEXTRACT_VERSION_HPP |
||||
|
||||
#include <iostream> |
||||
#include <utility> |
||||
|
||||
#include "Types.h" |
||||
|
||||
typedef u32 InnoVersionConstant; |
||||
#define INNO_VERSION_EXT(a, b, c, d) ((u32(a) << 24) | (u32(b) << 16) | (u32(c) << 8) | u32(d)) |
||||
#define INNO_VERSION(a, b, c) INNO_VERSION_EXT(a, b, c, 0) |
||||
|
||||
struct InnoVersion { |
||||
|
||||
InnoVersionConstant version; |
||||
|
||||
char bits; // 16 or 32
|
||||
|
||||
bool unicode; |
||||
|
||||
bool known; |
||||
|
||||
|
||||
inline InnoVersion() : known(false) { }; |
||||
|
||||
inline InnoVersion(InnoVersionConstant _version, bool _unicode = false, bool _known = false, char _bits = 32) : version(_version), unicode(_unicode), known(_known), bits(_bits) { }; |
||||
|
||||
|
||||
inline InnoVersion(char a, char b, char c, char d = 0, bool _unicode = false, bool _known = false, char _bits = 32) : version(INNO_VERSION_EXT(a, b, c, d)), unicode(_unicode), known(_known), bits(_bits) { }; |
||||
|
||||
inline int a() { return version >> 24; } |
||||
inline int b() { return (version >> 16) & 0xff; } |
||||
inline int c() { return (version >> 8) & 0xff; } |
||||
inline int d() { return version & 0xff; } |
||||
|
||||
void load(std::istream & is); |
||||
|
||||
}; |
||||
|
||||
inline bool operator==(const InnoVersion & a, const InnoVersion & b) { return a.version == b.version; } |
||||
inline bool operator!=(const InnoVersion & a, const InnoVersion & b) { return !operator==(a, b); } |
||||
inline bool operator< (const InnoVersion & a, const InnoVersion & b) { return a.version < b.version; } |
||||
inline bool operator> (const InnoVersion & a, const InnoVersion & b) { return operator< (b, a); } |
||||
inline bool operator<=(const InnoVersion & a, const InnoVersion & b) { return !operator> (a, b); } |
||||
inline bool operator>=(const InnoVersion & a, const InnoVersion & b) { return !operator< (a, b); } |
||||
|
||||
inline bool operator==(const InnoVersion & a, InnoVersionConstant b) { return a.version == b; } |
||||
inline bool operator!=(const InnoVersion & a, InnoVersionConstant b) { return !operator==(a, b); } |
||||
inline bool operator< (const InnoVersion & a, InnoVersionConstant b) { return a.version < b; } |
||||
inline bool operator> (const InnoVersion & a, InnoVersionConstant b) { return operator< (b, a); } |
||||
inline bool operator<=(const InnoVersion & a, InnoVersionConstant b) { return !operator> (a, b); } |
||||
inline bool operator>=(const InnoVersion & a, InnoVersionConstant b) { return !operator< (a, b); } |
||||
|
||||
inline bool operator==(InnoVersionConstant a, const InnoVersion & b) { return a == b.version; } |
||||
inline bool operator!=(InnoVersionConstant a, const InnoVersion & b) { return !operator==(a, b); } |
||||
inline bool operator< (InnoVersionConstant a, const InnoVersion & b) { return a < b.version; } |
||||
inline bool operator> (InnoVersionConstant a, const InnoVersion & b) { return operator< (b, a); } |
||||
inline bool operator<=(InnoVersionConstant a, const InnoVersion & b) { return !operator> (a, b); } |
||||
inline bool operator>=(InnoVersionConstant a, const InnoVersion & b) { return !operator< (a, b); } |
||||
|
||||
std::ostream & operator<<(std::ostream & os, const InnoVersion & version); |
||||
|
||||
#endif // INNOEXTRACT_VERSION_HPP
|
||||
Loading…
Reference in new issue