From 4c61bc4da822fc89f2e05bdb2c45e6c4dd7a3673 Mon Sep 17 00:00:00 2001 From: Daniel Scharrer Date: Thu, 30 May 2019 23:04:05 +0200 Subject: [PATCH] Add support for ISX versions before 3.0.6.1 This implementation is based on the My Inno Setup Extensions changelog http://web.archive.org/web/20010306024721/http://www.wintax.nl/isx/ as well as source for ISX version 2.0.10 and 3.0.6.1 plus some RE. The oldest ISX version available to be tested was 1.3.10. Fixes: issue #85 --- CHANGELOG | 1 + src/setup/component.cpp | 17 ++++++++++------- src/setup/file.cpp | 4 ++-- src/setup/header.cpp | 41 ++++++++++++++++++++++++++++------------- src/setup/info.cpp | 2 +- src/setup/item.cpp | 10 +++++++--- src/setup/run.cpp | 4 ++-- src/setup/task.cpp | 12 ++++++++++-- src/setup/type.cpp | 2 +- src/setup/version.cpp | 33 ++++++++++++++++++++++++++++----- src/setup/version.hpp | 4 +++- 11 files changed, 93 insertions(+), 37 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index edf35bf..2d70c94 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ innoextract 1.8 (WIP) - Added support for a modified Inno Setup 5.5.7 variant - Added support for a modified Inno Setup 5.5.7 variant with an uppercase (U) in the data version - Added support for Inno Setup 1.3.x installers with x < 24 + - Added support for My Inno Setup Extensions installers older than 3.0.6.1 - Added support for installers using an alternative setup loader magic - Added support for using boost_{zlib,bzip2} when statically linking Boost - Fixed extracting files from slices larger than 2 GiB with 32-bit builds diff --git a/src/setup/component.cpp b/src/setup/component.cpp index a6947da..e576083 100644 --- a/src/setup/component.cpp +++ b/src/setup/component.cpp @@ -63,30 +63,33 @@ void component_entry::load(std::istream & is, const version & version) { } else { languages.clear(); } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { is >> util::encoded_string(check, version.codepage()); } else { check.clear(); } - if(version >= INNO_VERSION(4, 0, 0)) { extra_disk_pace_required = util::load(is); } else { extra_disk_pace_required = util::load(is); } - - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 3))) { level = util::load(is); + } else { + level = 0; + } + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 4))) { used = util::load_bool(is); } else { - level = 0, used = true; + used = true; } winver.load(is, version); if(version >= INNO_VERSION(4, 2, 3)) { options = stored_flags(is).get(); - } else if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + } else if(version >= INNO_VERSION(3, 0, 8) || + (version.is_isx() && version >= INNO_VERSION_EXT(3, 0, 6, 1))) { options = stored_flags(is).get(); } else { options = stored_flags(is).get(); @@ -94,7 +97,7 @@ void component_entry::load(std::istream & is, const version & version) { if(version >= INNO_VERSION(4, 0, 0)) { size = util::load(is); - } else { + } else if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { size = util::load(is); } } diff --git a/src/setup/file.cpp b/src/setup/file.cpp index 4bee001..fb78ba1 100644 --- a/src/setup/file.cpp +++ b/src/setup/file.cpp @@ -125,7 +125,7 @@ void file_entry::load(std::istream & is, const version & version) { flagreader.add(RegisterTypeLib); flagreader.add(SharedFile); } - if(version < INNO_VERSION(2, 0, 0)) { + if(version < INNO_VERSION(2, 0, 0) && !version.is_isx()) { flagreader.add(IsReadmeFile); } flagreader.add(CompareTimeStamp); @@ -154,7 +154,7 @@ void file_entry::load(std::istream & is, const version & version) { flagreader.add(IgnoreVersion); flagreader.add(PromptIfOlder); } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION_EXT(3, 0, 6, 1))) { flagreader.add(DontCopy); } if(version >= INNO_VERSION(4, 0, 5)) { diff --git a/src/setup/header.cpp b/src/setup/header.cpp index 1c5bf8c..3df63ad 100644 --- a/src/setup/header.cpp +++ b/src/setup/header.cpp @@ -213,13 +213,16 @@ void header::load(std::istream & is, const version & version) { } else { default_user_name.clear(), default_user_organisation.clear(); } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION_EXT(3, 0, 6, 1))) { is >> util::encoded_string(default_serial, version.codepage()); - if(version < INNO_VERSION(5, 2, 5)) { - is >> util::binary_string(compiled_code); - } } else { - default_serial.clear(), compiled_code.clear(); + default_serial.clear(); + } + if((version >= INNO_VERSION(4, 0, 0) && version < INNO_VERSION(5, 2, 5)) || + (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { + is >> util::binary_string(compiled_code); + } else { + compiled_code.clear(); } if(version >= INNO_VERSION(4, 2, 4)) { is >> util::encoded_string(app_readme_file, version.codepage()); @@ -297,12 +300,16 @@ void header::load(std::istream & is, const version & version) { permission_count = 0; } - if(version >= INNO_VERSION(2, 0, 0)) { + if(version >= INNO_VERSION(2, 0, 0) || version.is_isx()) { type_count = util::load(is); component_count = util::load(is); + } else { + type_count = 0, component_count = 0; + } + if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 17))) { task_count = util::load(is); } else { - type_count = 0, component_count = 0, task_count = 0; + task_count = 0; } directory_count = util::load(is, version.bits()); @@ -338,7 +345,7 @@ void header::load(std::istream & is, const version & version) { } else { image_back_color = 0; } - if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) { + if((version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) || version.is_isx()) { small_image_back_color = util::load(is); } else { small_image_back_color = 0; @@ -386,7 +393,8 @@ void header::load(std::istream & is, const version & version) { slices_per_disk = 1; } - if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) { + if((version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) || + (version.is_isx() && version >= INNO_VERSION(1, 3, 4))) { install_mode = stored_enum(is).get(); } else { install_mode = NormalInstallMode; @@ -400,7 +408,7 @@ void header::load(std::istream & is, const version & version) { if(version >= INNO_VERSION(5, 0, 0)) { uninstall_style = ModernStyle; - } else if(version >= INNO_VERSION(2, 0, 0)) { + } else if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 13))) { uninstall_style = stored_enum(is).get(); } else { uninstall_style = ClassicStyle; @@ -412,6 +420,11 @@ void header::load(std::istream & is, const version & version) { dir_exists_warning = Auto; } + if(version.is_isx() && version >= INNO_VERSION(2, 0, 10) && version < INNO_VERSION(3, 0, 0)) { + boost::int32_t code_line_offset = util::load(is); + (void)code_line_offset; + } + if(version >= INNO_VERSION(3, 0, 0) && version < INNO_VERSION(3, 0, 3)) { auto_bool val = stored_enum(is).get(); switch(val) { @@ -423,7 +436,7 @@ void header::load(std::istream & is, const version & version) { if(version >= INNO_VERSION(5, 3, 7)) { privileges_required = stored_enum(is).get(); - } else if(version >= INNO_VERSION(3, 0, 4)) { + } else if(version >= INNO_VERSION(3, 0, 4) || (version.is_isx() && version >= INNO_VERSION(3, 0, 3))) { privileges_required = stored_enum(is).get(); } @@ -560,8 +573,10 @@ void header::load(std::istream & is, const version & version) { if(version >= INNO_VERSION(1, 3, 20)) { flagreader.add(UpdateUninstallLogAppName); } - if(version >= INNO_VERSION(2, 0, 0)) { + if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 10))) { flagreader.add(UsePreviousSetupType); + } + if(version >= INNO_VERSION(2, 0, 0)) { flagreader.add(DisableReadyMemo); flagreader.add(AlwaysShowComponentsList); flagreader.add(FlatComponentsList); @@ -589,7 +604,7 @@ void header::load(std::istream & is, const version & version) { if(version >= INNO_VERSION(3, 0, 3)) { flagreader.add(RestartIfNeededByRun); } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 3))) { flagreader.add(ShowTasksTreeLines); } if(version >= INNO_VERSION(4, 0, 0) && version < INNO_VERSION(4, 0, 10)) { diff --git a/src/setup/info.cpp b/src/setup/info.cpp index eb130f0..a72eb99 100644 --- a/src/setup/info.cpp +++ b/src/setup/info.cpp @@ -124,7 +124,7 @@ void load_wizard_and_decompressor(std::istream & is, const setup::version & vers load_wizard_images(is, version, info.wizard_images, entries); - if(version >= INNO_VERSION(2, 0, 0)) { + if(version >= INNO_VERSION(2, 0, 0) || version.is_isx()) { load_wizard_images(is, version, info.wizard_images_small, entries); } diff --git a/src/setup/item.cpp b/src/setup/item.cpp index 7d04792..6bca6ab 100644 --- a/src/setup/item.cpp +++ b/src/setup/item.cpp @@ -27,18 +27,22 @@ namespace setup { void item::load_condition_data(std::istream & is, const version & version) { - if(version >= INNO_VERSION(2, 0, 0)) { + if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 8))) { is >> util::encoded_string(components, version.codepage()); + } else { + components.clear(); + } + if(version >= INNO_VERSION(2, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 17))) { is >> util::encoded_string(tasks, version.codepage()); } else { - components.clear(), tasks.clear(); + tasks.clear(); } if(version >= INNO_VERSION(4, 0, 1)) { is >> util::encoded_string(languages, version.codepage()); } else { languages.clear(); } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { is >> util::encoded_string(check, version.codepage()); } else { check.clear(); diff --git a/src/setup/run.cpp b/src/setup/run.cpp index 7a515af..9541f58 100644 --- a/src/setup/run.cpp +++ b/src/setup/run.cpp @@ -62,7 +62,7 @@ void run_entry::load(std::istream & is, const version & version) { } else { verb.clear(); } - if(version >= INNO_VERSION(2, 0, 0)) { + if(version >= INNO_VERSION(2, 0, 0) || version.is_isx()) { is >> util::encoded_string(description, version.codepage()); } @@ -83,7 +83,7 @@ void run_entry::load(std::istream & is, const version & version) { if(version >= INNO_VERSION(1, 2, 3)) { flagreader.add(ShellExec); } - if(version >= INNO_VERSION(1, 3, 9)) { + if(version >= INNO_VERSION(1, 3, 9) || (version.is_isx() && version >= INNO_VERSION(1, 3, 8))) { flagreader.add(SkipIfDoesntExist); } if(version >= INNO_VERSION(2, 0, 0)) { diff --git a/src/setup/task.cpp b/src/setup/task.cpp index ea74f9c..e12dc18 100644 --- a/src/setup/task.cpp +++ b/src/setup/task.cpp @@ -39,12 +39,20 @@ void task_entry::load(std::istream & is, const version & version) { } else { languages.clear(); } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { is >> util::encoded_string(check, version.codepage()); + } else { + check.clear(); + } + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 3))) { level = util::load(is); + } else { + level = 0; + } + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(3, 0, 4))) { used = util::load_bool(is); } else { - check.clear(), level = 0, used = true; + used = true; } winver.load(is, version); diff --git a/src/setup/type.cpp b/src/setup/type.cpp index 31bf839..6bb81f3 100644 --- a/src/setup/type.cpp +++ b/src/setup/type.cpp @@ -62,7 +62,7 @@ void type_entry::load(std::istream & is, const version & version) { } else { languages.clear(); } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + if(version >= INNO_VERSION(4, 0, 0) || (version.is_isx() && version >= INNO_VERSION(1, 3, 24))) { is >> util::encoded_string(check, version.codepage()); } else { check.clear(); diff --git a/src/setup/version.cpp b/src/setup/version.cpp index 8ae9453..f9740de 100644 --- a/src/setup/version.cpp +++ b/src/setup/version.cpp @@ -28,6 +28,7 @@ #include #include #include +#include "boost/algorithm/string.hpp" #include #include #include @@ -74,25 +75,39 @@ const known_version versions[] = { { "Inno Setup Setup Data (1.3.3)", INNO_VERSION_EXT(1, 3, 3, 0), 0 }, { "Inno Setup Setup Data (1.3.9)", INNO_VERSION_EXT(1, 3, 9, 0), 0 }, { "Inno Setup Setup Data (1.3.10)", INNO_VERSION_EXT(1, 3, 10, 0), 0 }, + { "Inno Setup Setup Data (1.3.10) with ISX (1.3.10)", INNO_VERSION_EXT(1, 3, 10, 0), version::ISX }, + { "Inno Setup Setup Data (1.3.12) with ISX (1.3.12.1)", INNO_VERSION_EXT(1, 3, 12, 1), version::ISX }, { "Inno Setup Setup Data (1.3.21)", /* ambiguous */ INNO_VERSION_EXT(1, 3, 21, 0), 0 }, + { "Inno Setup Setup Data (1.3.21) with ISX (1.3.17)", INNO_VERSION_EXT(1, 3, 21, 0), version::ISX }, { "Inno Setup Setup Data (1.3.24)", INNO_VERSION_EXT(1, 3, 24, 0), 0 }, + { "Inno Setup Setup Data (1.3.21) with ISX (1.3.24)", INNO_VERSION_EXT(1, 3, 24, 0), version::ISX }, { "Inno Setup Setup Data (1.3.25)", INNO_VERSION_EXT(1, 3, 25, 0), 0 }, + { "Inno Setup Setup Data (1.3.25) with ISX (1.3.25)", INNO_VERSION_EXT(1, 3, 25, 0), version::ISX }, { "Inno Setup Setup Data (2.0.0)", INNO_VERSION_EXT(2, 0, 0, 0), 0 }, { "Inno Setup Setup Data (2.0.1)", /* ambiguous */ INNO_VERSION_EXT(2, 0, 1, 0), 0 }, { "Inno Setup Setup Data (2.0.2)", INNO_VERSION_EXT(2, 0, 2, 0), 0 }, { "Inno Setup Setup Data (2.0.5)", INNO_VERSION_EXT(2, 0, 5, 0), 0 }, { "Inno Setup Setup Data (2.0.6a)", INNO_VERSION_EXT(2, 0, 6, 0), 0 }, + { "Inno Setup Setup Data (2.0.6a) with ISX (2.0.3)", INNO_VERSION_EXT(2, 0, 6, 0), version::ISX }, { "Inno Setup Setup Data (2.0.7)", INNO_VERSION_EXT(2, 0, 7, 0), 0 }, { "Inno Setup Setup Data (2.0.8)", INNO_VERSION_EXT(2, 0, 8, 0), 0 }, + { "Inno Setup Setup Data (2.0.8) with ISX (2.0.3)", INNO_VERSION_EXT(2, 0, 8, 0), version::ISX }, + { "Inno Setup Setup Data (2.0.8) with ISX (2.0.10)", INNO_VERSION_EXT(2, 0, 10, 0), version::ISX }, { "Inno Setup Setup Data (2.0.11)", INNO_VERSION_EXT(2, 0, 11, 0), 0 }, + { "Inno Setup Setup Data (2.0.11) with ISX (2.0.11)", INNO_VERSION_EXT(2, 0, 11, 0), version::ISX }, { "Inno Setup Setup Data (2.0.17)", INNO_VERSION_EXT(2, 0, 17, 0), 0 }, + { "Inno Setup Setup Data (2.0.17) with ISX (2.0.11)", INNO_VERSION_EXT(2, 0, 17, 0), version::ISX }, { "Inno Setup Setup Data (2.0.18)", INNO_VERSION_EXT(2, 0, 18, 0), 0 }, + { "Inno Setup Setup Data (2.0.18) with ISX (2.0.11)", INNO_VERSION_EXT(2, 0, 18, 0), version::ISX }, { "Inno Setup Setup Data (3.0.0a)", INNO_VERSION_EXT(3, 0, 0, 0), 0 }, { "Inno Setup Setup Data (3.0.1)", INNO_VERSION_EXT(3, 0, 1, 0), 0 }, + { "Inno Setup Setup Data (3.0.1) with ISX (3.0.0)", INNO_VERSION_EXT(3, 0, 1, 0), version::ISX }, { "Inno Setup Setup Data (3.0.3)", /* ambiguous */ INNO_VERSION_EXT(3, 0, 3, 0), 0 }, + { "Inno Setup Setup Data (3.0.3) with ISX (3.0.3)", INNO_VERSION_EXT(3, 0, 3, 0), version::ISX }, { "Inno Setup Setup Data (3.0.4)", INNO_VERSION_EXT(3, 0, 4, 0), 0 }, + { "My Inno Setup Extensions Setup Data (3.0.4)", INNO_VERSION_EXT(3, 0, 4, 0), version::ISX }, { "Inno Setup Setup Data (3.0.5)", INNO_VERSION_EXT(3, 0, 5, 0), 0 }, - { "My Inno Setup Extensions Setup Data (3.0.6.1)", INNO_VERSION_EXT(3, 0, 6, 1), 0 }, + { "My Inno Setup Extensions Setup Data (3.0.6.1)", INNO_VERSION_EXT(3, 0, 6, 1), version::ISX }, { "Inno Setup Setup Data (4.0.0a)", INNO_VERSION_EXT(4, 0, 0, 0), 0 }, { "Inno Setup Setup Data (4.0.1)", INNO_VERSION_EXT(4, 0, 1, 0), 0 }, { "Inno Setup Setup Data (4.0.3)", INNO_VERSION_EXT(4, 0, 3, 0), 0 }, @@ -181,6 +196,10 @@ std::ostream & operator<<(std::ostream & os, const version & version) { os << " (" << int(version.bits()) << "-bit)"; } + if(version.is_isx()) { + os << " (isx)"; + } + return os; } @@ -261,6 +280,7 @@ void version::load(std::istream & is) { throw version_error(); } + value = 0; size_t bracket = version_str.find('('); for(; bracket != std::string::npos; bracket = version_str.find('(', bracket + 1)) { @@ -308,21 +328,24 @@ void version::load(std::istream & is) { } } - value = INNO_VERSION_EXT(a, b, c, d); - break; + value = std::max(value, INNO_VERSION_EXT(a, b, c, d)); } catch(const boost::bad_lexical_cast &) { continue; } } - if(bracket == std::string::npos) { + if(!value) { throw version_error(); } variant = 0; - if(version_str.find("(u)") != std::string::npos || version_str.find("(U)") != std::string::npos) { + if(boost::contains(version_str, "(u)") || boost::contains(version_str, "(U)")) { variant |= Unicode; } + if(boost::contains(version_str, "My Inno Setup Extensions") || boost::contains(version_str, "with ISX")) { + variant |= ISX; + } + known = false; } diff --git a/src/setup/version.hpp b/src/setup/version.hpp index 2a61f83..4cc54e6 100644 --- a/src/setup/version.hpp +++ b/src/setup/version.hpp @@ -50,7 +50,8 @@ struct version { FLAGS(flags, Bits16, - Unicode + Unicode, + ISX ); version_constant value; @@ -78,6 +79,7 @@ struct version { boost::uint16_t bits() const { return (variant & Bits16) ? 16 : 32; } bool is_unicode() const { return (variant & Unicode); } + bool is_isx() const { return (variant & ISX); } //! \return the Windows codepage used to encode strings boost::uint32_t codepage() const { return boost::uint32_t(is_unicode() ? 1200 : 1252); }