From eba41e0f51cddb4d74dee21311a0af7750c3e45e Mon Sep 17 00:00:00 2001 From: Daniel Scharrer Date: Wed, 30 Nov 2011 04:35:19 +0100 Subject: [PATCH] Cleanup setup header loading, implement version number parsing. --- CMakeLists.txt | 26 +- src/InnoExtract.cpp | 468 ++++++------ src/crypto/checksum.cpp | 2 +- src/loader/offsets.cpp | 4 +- src/setup/IconEntry.hpp | 59 -- src/setup/IniEntry.hpp | 37 - src/setup/LanguageEntry.cpp | 67 -- src/setup/LanguageEntry.hpp | 40 -- src/setup/PermissionEntry.cpp | 12 - src/setup/PermissionEntry.hpp | 20 - src/setup/RunEntry.hpp | 57 -- src/setup/SetupComponentEntry.cpp | 83 --- src/setup/SetupComponentEntry.hpp | 51 -- src/setup/SetupHeader.cpp | 664 ------------------ src/setup/SetupHeader.hpp | 243 ------- src/setup/SetupItem.hpp | 32 - src/setup/SetupTaskEntry.hpp | 47 -- src/setup/SetupTypeEntry.cpp | 60 -- src/setup/SetupTypeEntry.hpp | 52 -- src/setup/WindowsVersion.cpp | 128 ---- src/setup/WindowsVersion.hpp | 67 -- src/setup/component.cpp | 87 +++ src/setup/component.hpp | 54 ++ src/setup/data.cpp | 57 +- src/setup/data.hpp | 24 +- src/setup/delete.cpp | 5 +- src/setup/delete.hpp | 9 +- src/setup/directory.cpp | 5 +- src/setup/directory.hpp | 12 +- src/setup/file.cpp | 9 +- src/setup/file.hpp | 13 +- src/setup/header.cpp | 655 +++++++++++++++++ src/setup/header.hpp | 238 +++++++ src/setup/{IconEntry.cpp => icon.cpp} | 43 +- src/setup/icon.hpp | 62 ++ src/setup/{IniEntry.cpp => ini.cpp} | 25 +- src/setup/ini.hpp | 41 ++ src/setup/{SetupItem.cpp => item.cpp} | 20 +- src/setup/item.hpp | 38 + src/setup/language.cpp | 67 ++ src/setup/language.hpp | 44 ++ src/setup/{MessageEntry.cpp => message.cpp} | 9 +- src/setup/{MessageEntry.hpp => message.hpp} | 16 +- src/setup/permission.cpp | 16 + src/setup/permission.hpp | 24 + src/setup/{RegistryEntry.cpp => registry.cpp} | 61 +- src/setup/{RegistryEntry.hpp => registry.hpp} | 40 +- src/setup/{RunEntry.cpp => run.cpp} | 39 +- src/setup/run.hpp | 60 ++ src/setup/{SetupTaskEntry.cpp => task.cpp} | 18 +- src/setup/task.hpp | 50 ++ src/setup/type.cpp | 75 ++ src/setup/type.hpp | 49 ++ src/setup/version.cpp | 205 ++++-- src/setup/version.hpp | 88 +-- src/setup/windows.cpp | 145 ++++ src/setup/windows.hpp | 81 +++ src/stream/block.cpp | 8 +- src/stream/block.hpp | 4 +- src/stream/chunk.cpp | 17 +- src/stream/chunk.hpp | 24 +- src/stream/file.cpp | 43 +- src/stream/file.hpp | 28 +- src/util/enum.hpp | 6 +- 64 files changed, 2527 insertions(+), 2306 deletions(-) delete mode 100644 src/setup/IconEntry.hpp delete mode 100644 src/setup/IniEntry.hpp delete mode 100644 src/setup/LanguageEntry.cpp delete mode 100644 src/setup/LanguageEntry.hpp delete mode 100644 src/setup/PermissionEntry.cpp delete mode 100644 src/setup/PermissionEntry.hpp delete mode 100644 src/setup/RunEntry.hpp delete mode 100644 src/setup/SetupComponentEntry.cpp delete mode 100644 src/setup/SetupComponentEntry.hpp delete mode 100644 src/setup/SetupHeader.cpp delete mode 100644 src/setup/SetupHeader.hpp delete mode 100644 src/setup/SetupItem.hpp delete mode 100644 src/setup/SetupTaskEntry.hpp delete mode 100644 src/setup/SetupTypeEntry.cpp delete mode 100644 src/setup/SetupTypeEntry.hpp delete mode 100644 src/setup/WindowsVersion.cpp delete mode 100644 src/setup/WindowsVersion.hpp create mode 100644 src/setup/component.cpp create mode 100644 src/setup/component.hpp create mode 100644 src/setup/header.cpp create mode 100644 src/setup/header.hpp rename src/setup/{IconEntry.cpp => icon.cpp} (58%) create mode 100644 src/setup/icon.hpp rename src/setup/{IniEntry.cpp => ini.cpp} (61%) create mode 100644 src/setup/ini.hpp rename src/setup/{SetupItem.cpp => item.cpp} (54%) create mode 100644 src/setup/item.hpp create mode 100644 src/setup/language.cpp create mode 100644 src/setup/language.hpp rename src/setup/{MessageEntry.cpp => message.cpp} (57%) rename src/setup/{MessageEntry.hpp => message.hpp} (51%) create mode 100644 src/setup/permission.cpp create mode 100644 src/setup/permission.hpp rename src/setup/{RegistryEntry.cpp => registry.cpp} (61%) rename src/setup/{RegistryEntry.hpp => registry.hpp} (54%) rename src/setup/{RunEntry.cpp => run.cpp} (66%) create mode 100644 src/setup/run.hpp rename src/setup/{SetupTaskEntry.cpp => task.cpp} (73%) create mode 100644 src/setup/task.hpp create mode 100644 src/setup/type.cpp create mode 100644 src/setup/type.hpp create mode 100644 src/setup/windows.cpp create mode 100644 src/setup/windows.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e480bd..58479f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,24 +87,24 @@ set(INNOEXTRACT_SOURCES src/loader/exereader.cpp src/loader/offsets.cpp + src/setup/component.cpp src/setup/data.cpp src/setup/delete.cpp src/setup/directory.cpp src/setup/file.cpp - src/setup/IconEntry.cpp - src/setup/IniEntry.cpp - src/setup/LanguageEntry.cpp - src/setup/MessageEntry.cpp - src/setup/PermissionEntry.cpp - src/setup/RegistryEntry.cpp - src/setup/RunEntry.cpp - src/setup/SetupComponentEntry.cpp - src/setup/SetupHeader.cpp - src/setup/SetupItem.cpp - src/setup/SetupTaskEntry.cpp - src/setup/SetupTypeEntry.cpp + src/setup/header.cpp + src/setup/icon.cpp + src/setup/ini.cpp + src/setup/item.cpp + src/setup/language.cpp + src/setup/message.cpp + src/setup/permission.cpp + src/setup/registry.cpp + src/setup/run.cpp + src/setup/task.cpp + src/setup/type.cpp src/setup/version.cpp - src/setup/WindowsVersion.cpp + src/setup/windows.cpp src/stream/block.cpp src/stream/chunk.cpp diff --git a/src/InnoExtract.cpp b/src/InnoExtract.cpp index 1e77e51..dbaf4a1 100644 --- a/src/InnoExtract.cpp +++ b/src/InnoExtract.cpp @@ -22,21 +22,21 @@ #include "loader/offsets.hpp" +#include "setup/component.hpp" #include "setup/data.hpp" #include "setup/delete.hpp" #include "setup/directory.hpp" #include "setup/file.hpp" -#include "setup/MessageEntry.hpp" -#include "setup/IconEntry.hpp" -#include "setup/IniEntry.hpp" -#include "setup/LanguageEntry.hpp" -#include "setup/PermissionEntry.hpp" -#include "setup/RegistryEntry.hpp" -#include "setup/RunEntry.hpp" -#include "setup/SetupComponentEntry.hpp" -#include "setup/SetupHeader.hpp" -#include "setup/SetupTaskEntry.hpp" -#include "setup/SetupTypeEntry.hpp" +#include "setup/header.hpp" +#include "setup/icon.hpp" +#include "setup/ini.hpp" +#include "setup/language.hpp" +#include "setup/message.hpp" +#include "setup/permission.hpp" +#include "setup/registry.hpp" +#include "setup/run.hpp" +#include "setup/task.hpp" +#include "setup/type.hpp" #include "setup/version.hpp" #include "stream/block.hpp" @@ -58,48 +58,43 @@ using std::setfill; namespace io = boost::iostreams; namespace fs = boost::filesystem; -struct FileLocationComparer { +static void print(std::ostream & os, const setup::windows_version_range & winver, + const setup::header & header) { - const std::vector & locations; + const setup::windows_version_range & def = header.winver; - explicit FileLocationComparer(const std::vector & loc) : locations(loc) { } - FileLocationComparer(const FileLocationComparer & o) : locations(o.locations) { } - - bool operator()(size_t a, size_t b) { - return (locations[a].file_offset < locations[b].file_offset); - } - -}; + os << if_not_equal(" Min version", winver.begin, def.begin); + os << if_not_equal(" Only below version", winver.end, def.end); +} -static void print(std::ostream & os, const SetupItem & item, const SetupHeader & header) { +static void print(std::ostream & os, const setup::item & item, + const setup::header & header) { os << if_not_empty(" Componenets", item.components); os << if_not_empty(" Tasks", item.tasks); os << if_not_empty(" Languages", item.languages); os << if_not_empty(" Check", item.check); - os << if_not_empty(" After install", item.afterInstall); - os << if_not_empty(" Before install", item.beforeInstall); - - os << if_not_equal(" Min version", item.minVersion, header.minVersion); - os << if_not_equal(" Only below version", item.onlyBelowVersion, header.onlyBelowVersion); + os << if_not_empty(" After install", item.after_install); + os << if_not_empty(" Before install", item.before_install); + print(os, item.winver, header); } -static void print(std::ostream & os, const RunEntry & entry, const SetupHeader & header) { +static void print(std::ostream & os, const setup::run_entry & entry, const setup::header & header) { os << " - " << quoted(entry.name) << ':' << endl; os << if_not_empty(" Parameters", entry.parameters); - os << if_not_empty(" Working directory", entry.workingDir); - os << if_not_empty(" Run once id", entry.runOnceId); - os << if_not_empty(" Status message", entry.statusMessage); + os << if_not_empty(" Working directory", entry.working_dir); + os << if_not_empty(" Run once id", entry.run_once_id); + os << if_not_empty(" Status message", entry.status_message); os << if_not_empty(" Verb", entry.verb); os << if_not_empty(" Description", entry.verb); - print(cout, static_cast(entry), header); + print(cout, static_cast(entry), header); - os << if_not_equal(" Show command", entry.showCmd, 1); - os << if_not_equal(" Wait", entry.wait, RunEntry::WaitUntilTerminated); + os << if_not_equal(" Show command", entry.show_command, 1); + os << if_not_equal(" Wait", entry.wait, setup::run_entry::WaitUntilTerminated); os << if_not_zero(" Options", entry.options); @@ -150,8 +145,8 @@ static void dump(std::istream & is, const string & file) { ofs << data; }; -static void readWizardImageAndDecompressor(std::istream & is, const inno_version & version, - const SetupHeader & header) { +static void readWizardImageAndDecompressor(std::istream & is, const setup::version & version, + const setup::header & header) { cout << endl; @@ -161,9 +156,9 @@ static void readWizardImageAndDecompressor(std::istream & is, const inno_version dump(is, "wizard_small"); } - if(header.compressMethod == stream::chunk::BZip2 - || (header.compressMethod == stream::chunk::LZMA1 && version == INNO_VERSION(4, 1, 5)) - || (header.compressMethod == stream::chunk::Zlib && version >= INNO_VERSION(4, 2, 6))) { + if(header.compression == stream::BZip2 + || (header.compression == stream::LZMA1 && version == INNO_VERSION(4, 1, 5)) + || (header.compression == stream::Zlib && version >= INNO_VERSION(4, 2, 6))) { dump(is, "decompressor"); } @@ -215,18 +210,13 @@ int main(int argc, char * argv[]) { ifs.seekg(offsets.header_offset); - inno_version version; + setup::version version; version.load(ifs); if(ifs.fail()) { log_error << "error reading setup data version!"; return 1; } - if(!version.known) { - log_error << "unknown version!"; - return 1; // TODO - } - cout << "version: " << color::white << version << color::reset << endl; stream::block_reader::pointer is = stream::block_reader::get(ifs, version); @@ -237,7 +227,7 @@ int main(int argc, char * argv[]) { is->exceptions(std::ios_base::badbit | std::ios_base::failbit); - SetupHeader header; + setup::header header; header.load(*is, version); if(is->fail()) { log_error << "error reading setup data header!"; @@ -246,142 +236,142 @@ int main(int argc, char * argv[]) { cout << endl; - cout << if_not_empty("App name", header.appName); - cout << if_not_empty("App ver name", header.appVerName); - cout << if_not_empty("App id", header.appId); - cout << if_not_empty("Copyright", header.appCopyright); - cout << if_not_empty("Publisher", header.appPublisher); - cout << if_not_empty("Publisher URL", header.appPublisherURL); - cout << if_not_empty("Support phone", header.appSupportPhone); - cout << if_not_empty("Support URL", header.appSupportURL); - cout << if_not_empty("Updates URL", header.appUpdatesURL); - cout << if_not_empty("Version", header.appVersion); - cout << if_not_empty("Default dir name", header.defaultDirName); - cout << if_not_empty("Default group name", header.defaultGroupName); - cout << if_not_empty("Uninstall icon name", header.uninstallIconName); - cout << if_not_empty("Base filename", header.baseFilename); - cout << if_not_empty("Uninstall files dir", header.uninstallFilesDir); - cout << if_not_empty("Uninstall display name", header.uninstallDisplayName); - cout << if_not_empty("Uninstall display icon", header.uninstallDisplayIcon); - cout << if_not_empty("App mutex", header.appMutex); - cout << if_not_empty("Default user name", header.defaultUserInfoName); - cout << if_not_empty("Default user org", header.defaultUserInfoOrg); - cout << if_not_empty("Default user serial", header.defaultUserInfoSerial); - cout << if_not_empty("Readme", header.appReadmeFile); - cout << if_not_empty("Contact", header.appContact); - cout << if_not_empty("Comments", header.appComments); - cout << if_not_empty("Modify path", header.appModifyPath); - cout << if_not_empty("Uninstall reg key", header.createUninstallRegKey); + cout << if_not_empty("App name", header.app_name); + cout << if_not_empty("App ver name", header.app_versioned_name); + cout << if_not_empty("App id", header.app_id); + cout << if_not_empty("Copyright", header.app_copyright); + cout << if_not_empty("Publisher", header.app_publisher); + cout << if_not_empty("Publisher URL", header.app_publisher_url); + cout << if_not_empty("Support phone", header.app_support_phone); + cout << if_not_empty("Support URL", header.app_support_url); + cout << if_not_empty("Updates URL", header.app_updates_url); + cout << if_not_empty("Version", header.app_version); + cout << if_not_empty("Default dir name", header.default_dir_name); + cout << if_not_empty("Default group name", header.default_group_name); + cout << if_not_empty("Uninstall icon name", header.uninstall_icon_name); + cout << if_not_empty("Base filename", header.base_filename); + cout << if_not_empty("Uninstall files dir", header.uninstall_files_dir); + cout << if_not_empty("Uninstall display name", header.uninstall_name); + cout << if_not_empty("Uninstall display icon", header.uninstall_icon); + cout << if_not_empty("App mutex", header.app_mutex); + cout << if_not_empty("Default user name", header.default_user_name); + cout << if_not_empty("Default user org", header.default_user_organisation); + cout << if_not_empty("Default user serial", header.default_serial); + cout << if_not_empty("Readme", header.app_readme_file); + cout << if_not_empty("Contact", header.app_contact); + cout << if_not_empty("Comments", header.app_comments); + cout << if_not_empty("Modify path", header.app_modify_path); + cout << if_not_empty("Uninstall reg key", header.create_uninstall_registry_key); cout << if_not_empty("Uninstallable", header.uninstallable); - cout << if_not_empty("License", header.licenseText); - cout << if_not_empty("Info before text", header.infoBeforeText); - cout << if_not_empty("Info after text", header.infoAfterText); - cout << if_not_empty("Uninstaller signature", header.signedUninstallerSignature); - cout << if_not_empty("Compiled code", header.compiledCodeText); - - cout << if_not_zero("Lead bytes", header.leadBytes); - - cout << if_not_zero("Language entries", header.numLanguageEntries); - cout << if_not_zero("Custom message entries", header.numCustomMessageEntries); - cout << if_not_zero("Permission entries", header.numPermissionEntries); - cout << if_not_zero("Type entries", header.numTypeEntries); - cout << if_not_zero("Component entries", header.numComponentEntries); - cout << if_not_zero("Task entries", header.numTaskEntries); - cout << if_not_zero("Dir entries", header.numDirectoryEntries); - cout << if_not_zero("File entries", header.numFileEntries); - cout << if_not_zero("File location entries", header.numFileLocationEntries); - cout << if_not_zero("Icon entries", header.numIconEntries); - cout << if_not_zero("Ini entries", header.numIniEntries); - cout << if_not_zero("Registry entries", header.numRegistryEntries); - cout << if_not_zero("Delete entries", header.numDeleteEntries); - cout << if_not_zero("Uninstall delete entries", header.numUninstallDeleteEntries); - cout << if_not_zero("Run entries", header.numRunEntries); - cout << if_not_zero("Uninstall run entries", header.numUninstallRunEntries); - - cout << if_not_equal("Min version", header.minVersion, WindowsVersion::none); - cout << if_not_equal("Only below version", header.onlyBelowVersion, WindowsVersion::none); + cout << if_not_empty("License", header.license_text); + cout << if_not_empty("Info before text", header.info_before); + cout << if_not_empty("Info after text", header.info_after); + cout << if_not_empty("Uninstaller signature", header.uninstaller_signature); + cout << if_not_empty("Compiled code", header.compiled_code); + + cout << if_not_zero("Lead bytes", header.lead_bytes); + + cout << if_not_zero("Language entries", header.language_count); + cout << if_not_zero("Custom message entries", header.message_count); + cout << if_not_zero("Permission entries", header.permission_count); + cout << if_not_zero("Type entries", header.type_count); + cout << if_not_zero("Component entries", header.component_count); + cout << if_not_zero("Task entries", header.task_count); + cout << if_not_zero("Dir entries", header.directory_count); + cout << if_not_zero("File entries", header.file_count); + cout << if_not_zero("File location entries", header.data_entry_count); + cout << if_not_zero("Icon entries", header.icon_count); + cout << if_not_zero("Ini entries", header.ini_entry_count); + cout << if_not_zero("Registry entries", header.registry_entry_count); + cout << if_not_zero("Delete entries", header.delete_entry_count); + cout << if_not_zero("Uninstall delete entries", header.uninstall_delete_entry_count); + cout << if_not_zero("Run entries", header.run_entry_count); + cout << if_not_zero("Uninstall run entries", header.uninstall_run_entry_count); + + cout << if_not_equal("Min version", header.winver.begin, setup::windows_version::none); + cout << if_not_equal("Only below version", header.winver.end, setup::windows_version::none); cout << std::hex; - cout << if_not_zero("Back color", header.backColor); - cout << if_not_zero("Back color2", header.backColor2); - cout << if_not_zero("Wizard image back color", header.wizardImageBackColor); - cout << if_not_zero("Wizard small image back color", header.wizardSmallImageBackColor); + cout << if_not_zero("Back color", header.back_color); + cout << if_not_zero("Back color2", header.back_color2); + cout << if_not_zero("Wizard image back color", header.image_back_color); + cout << if_not_zero("Wizard small image back color", header.small_image_back_color); cout << std::dec; - if(header.options & (SetupHeader::Password | SetupHeader::EncryptionUsed)) { + if(header.options & (setup::header::Password | setup::header::EncryptionUsed)) { cout << "Password: " << color::cyan << header.password << color::reset << endl; // TODO print salt } - cout << if_not_zero("Extra disk space required", header.extraDiskSpaceRequired); - cout << if_not_zero("Slices per disk", header.slicesPerDisk); + cout << if_not_zero("Extra disk space required", header.extra_disk_space_required); + cout << if_not_zero("Slices per disk", header.slices_per_disk); - cout << if_not_equal("Install mode", header.installMode, SetupHeader::NormalInstallMode); - cout << "Uninstall log mode: " << color::cyan << header.uninstallLogMode + cout << if_not_equal("Install mode", header.install_mode, setup::header::NormalInstallMode); + cout << "Uninstall log mode: " << color::cyan << header.uninstall_log_mode << color::reset << endl; - cout << "Uninstall style: " << color::cyan << header.uninstallStyle << color::reset << endl; - cout << "Dir exists warning: " << color::cyan << header.dirExistsWarning + cout << "Uninstall style: " << color::cyan << header.uninstall_style << color::reset << endl; + cout << "Dir exists warning: " << color::cyan << header.dir_exists_warning << color::reset << endl; - cout << if_not_equal("Privileges required", header.privilegesRequired, SetupHeader::NoPrivileges); - cout << "Show language dialog: " << color::cyan << header.showLanguageDialog + cout << if_not_equal("Privileges required", header.privileges_required, setup::header::NoPrivileges); + cout << "Show language dialog: " << color::cyan << header.show_language_dialog << color::reset << endl; - cout << if_not_equal("Danguage detection", header.languageDetectionMethod, - SetupHeader::NoLanguageDetection); - cout << "Compression: " << color::cyan << header.compressMethod << color::reset << endl; - cout << "Architectures allowed: " << color::cyan << header.architecturesAllowed + cout << if_not_equal("Danguage detection", header.language_detection, + setup::header::NoLanguageDetection); + cout << "Compression: " << color::cyan << header.compression << color::reset << endl; + cout << "Architectures allowed: " << color::cyan << header.architectures_allowed << color::reset << endl; cout << "Architectures installed in 64-bit mode: " << color::cyan - << header.architecturesInstallIn64BitMode << color::reset << endl; + << header.architectures_installed_in_64bit_mode << color::reset << endl; - if(header.options & SetupHeader::SignedUninstaller) { - cout << if_not_zero("Size before signing uninstaller", header.signedUninstallerOrigSize); - cout << if_not_zero("Uninstaller header checksum", header.signedUninstallerHdrChecksum); + if(header.options & setup::header::SignedUninstaller) { + cout << if_not_zero("Size before signing uninstaller", header.signed_uninstaller_original_size); + cout << if_not_zero("Uninstaller header checksum", header.signed_uninstaller_header_checksum); } - cout << "Disable dir page: " << color::cyan << header.disableDirPage << color::reset << endl; - cout << "Disable program group page: " << color::cyan << header.disableProgramGroupPage + cout << "Disable dir page: " << color::cyan << header.disable_dir_page << color::reset << endl; + cout << "Disable program group page: " << color::cyan << header.disable_program_group_page << color::reset << endl; - cout << if_not_zero("Uninstall display size", header.uninstallDisplaySize); + cout << if_not_zero("Uninstall display size", header.uninstall_display_size); cout << "Options: " << color::green << header.options << color::reset << endl; cout << color::reset; - if(header.numLanguageEntries) { + if(header.language_count) { cout << endl << "Language entries:" << endl; } - std::vector languages; - languages.resize(header.numLanguageEntries); - for(size_t i = 0; i < header.numLanguageEntries; i++) { + std::vector languages; + languages.resize(header.language_count); + for(size_t i = 0; i < header.language_count; i++) { - LanguageEntry & entry = languages[i]; + setup::language_entry & entry = languages[i]; entry.load(*is, version); if(is->fail()) { log_error << "error reading language entry #" << i; } cout << " - " << quoted(entry.name) << ':' << endl; - cout << if_not_empty(" Language name", entry.languageName); - cout << if_not_empty(" Dialog font", entry.dialogFontName); - cout << if_not_empty(" Title font", entry.titleFontName); - cout << if_not_empty(" Welcome font", entry.welcomeFontName); - cout << if_not_empty(" Copyright font", entry.copyrightFontName); + cout << if_not_empty(" Language name", entry.language_name); + cout << if_not_empty(" Dialog font", entry.dialog_font); + cout << if_not_empty(" Title font", entry.title_font); + cout << if_not_empty(" Welcome font", entry.welcome_font); + cout << if_not_empty(" Copyright font", entry.copyright_font); cout << if_not_empty(" Data", entry.data); - cout << if_not_empty(" License", entry.licenseText); - cout << if_not_empty(" Info before text", entry.infoBeforeText); - cout << if_not_empty(" Info after text", entry.infoAfterText); + cout << if_not_empty(" License", entry.license_text); + cout << if_not_empty(" Info before text", entry.info_before); + cout << if_not_empty(" Info after text", entry.info_after); - cout << " Language id: " << color::cyan << std::hex << entry.languageId << std::dec + cout << " Language id: " << color::cyan << std::hex << entry.language_id << std::dec << color::reset << endl; cout << if_not_zero(" Codepage", entry.codepage); - cout << if_not_zero(" Dialog font size", entry.dialogFontSize); - cout << if_not_zero(" Dialog font standard height", entry.dialogFontStandardHeight); - cout << if_not_zero(" Title font size", entry.titleFontSize); - cout << if_not_zero(" Welcome font size", entry.welcomeFontSize); - cout << if_not_zero(" Copyright font size", entry.copyrightFontSize); - cout << if_not_equal(" Right to left", entry.rightToLeft, false); + cout << if_not_zero(" Dialog font size", entry.dialog_font_size); + cout << if_not_zero(" Dialog font standard height", entry.dialog_font_standard_height); + cout << if_not_zero(" Title font size", entry.title_font_size); + cout << if_not_zero(" Welcome font size", entry.welcome_font_size); + cout << if_not_zero(" Copyright font size", entry.copyright_font_size); + cout << if_not_equal(" Right to left", entry.right_to_left, false); }; @@ -389,12 +379,12 @@ int main(int argc, char * argv[]) { readWizardImageAndDecompressor(*is, version, header); } - if(header.numCustomMessageEntries) { + if(header.message_count) { cout << endl << "Message entries:" << endl; } - for(size_t i = 0; i < header.numCustomMessageEntries; i++) { + for(size_t i = 0; i < header.message_count; i++) { - MessageEntry entry; + setup::message_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading custom message entry #" << i; @@ -425,12 +415,12 @@ int main(int argc, char * argv[]) { } - if(header.numPermissionEntries) { + if(header.permission_count) { cout << endl << "Permission entries:" << endl; } - for(size_t i = 0; i < header.numPermissionEntries; i++) { + for(size_t i = 0; i < header.permission_count; i++) { - PermissionEntry entry; + setup::permission_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading permission entry #" << i; @@ -440,12 +430,12 @@ int main(int argc, char * argv[]) { } - if(header.numTypeEntries) { + if(header.type_count) { cout << endl << "Type entries:" << endl; } - for(size_t i = 0; i < header.numTypeEntries; i++) { + for(size_t i = 0; i < header.type_count; i++) { - SetupTypeEntry entry; + setup::type_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading type entry #" << i; @@ -456,21 +446,20 @@ int main(int argc, char * argv[]) { cout << if_not_empty(" Languages", entry.languages); cout << if_not_empty(" Check", entry.check); - cout << if_not_equal(" Min version", entry.minVersion, header.minVersion); - cout << if_not_equal(" Only below version", entry.onlyBelowVersion, header.onlyBelowVersion); + print(cout, entry.winver, header); - cout << if_not_zero(" Options", entry.options); - cout << if_not_equal(" Type", entry.type, SetupTypeEntry::User); + cout << if_not_equal(" Custom setup type", entry.custom_type, false); + cout << if_not_equal(" Type", entry.type, setup::type_entry::User); cout << if_not_zero(" Size", entry.size); } - if(header.numComponentEntries) { + if(header.component_count) { cout << endl << "Component entries:" << endl; } - for(size_t i = 0; i < header.numComponentEntries; i++) { + for(size_t i = 0; i < header.component_count; i++) { - SetupComponentEntry entry; + setup::component_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading component entry #" << i; @@ -482,24 +471,23 @@ int main(int argc, char * argv[]) { cout << if_not_empty(" Languages", entry.languages); cout << if_not_empty(" Check", entry.check); - cout << if_not_zero(" Extra disk space required", entry.extraDiskSpaceRequired); + cout << if_not_zero(" Extra disk space required", entry.extra_disk_pace_required); cout << if_not_zero(" Level", entry.level); cout << if_not_equal(" Used", entry.used, true); - cout << if_not_equal(" Min version", entry.minVersion, header.minVersion); - cout << if_not_equal(" Only below version", entry.onlyBelowVersion, header.onlyBelowVersion); + print(cout, entry.winver, header); cout << if_not_zero(" Options", entry.options); cout << if_not_zero(" Size", entry.size); } - if(header.numTaskEntries) { + if(header.task_count) { cout << endl << "Task entries:" << endl; } - for(size_t i = 0; i < header.numTaskEntries; i++) { + for(size_t i = 0; i < header.task_count; i++) { - SetupTaskEntry entry; + setup::task_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading task entry #" << i; @@ -507,7 +495,7 @@ int main(int argc, char * argv[]) { cout << " - " << quoted(entry.name) << ':' << endl; cout << if_not_empty(" Description", entry.description); - cout << if_not_empty(" Group description", entry.groupDescription); + cout << if_not_empty(" Group description", entry.group_description); cout << if_not_empty(" Components", entry.components); cout << if_not_empty(" Languages", entry.languages); cout << if_not_empty(" Check", entry.check); @@ -515,17 +503,16 @@ int main(int argc, char * argv[]) { cout << if_not_zero(" Level", entry.level); cout << if_not_equal(" Used", entry.used, true); - cout << if_not_equal(" Min version", entry.minVersion, header.minVersion); - cout << if_not_equal(" Only below version", entry.onlyBelowVersion, header.onlyBelowVersion); + print(cout, entry.winver, header); cout << if_not_zero(" Options", entry.options); } - if(header.numDirectoryEntries) { + if(header.directory_count) { cout << endl << "Directory entries:" << endl; } - for(size_t i = 0; i < header.numDirectoryEntries; i++) { + for(size_t i = 0; i < header.directory_count; i++) { setup::directory_entry entry; entry.load(*is, version); @@ -550,12 +537,12 @@ int main(int argc, char * argv[]) { } - if(header.numFileEntries) { + if(header.file_count) { cout << endl << "File entries:" << endl; } std::vector files; - files.resize(header.numFileEntries); - for(size_t i = 0; i < header.numFileEntries; i++) { + files.resize(header.file_count); + for(size_t i = 0; i < header.file_count; i++) { setup::file_entry & entry = files[i]; entry.load(*is, version); @@ -590,12 +577,12 @@ int main(int argc, char * argv[]) { } - if(header.numIconEntries) { + if(header.icon_count) { cout << endl << "Icon entries:" << endl; } - for(size_t i = 0; i < header.numIconEntries; i++) { + for(size_t i = 0; i < header.icon_count; i++) { - IconEntry entry; + setup::icon_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading icon entry #" << i; @@ -603,16 +590,16 @@ int main(int argc, char * argv[]) { cout << " - " << quoted(entry.name) << " -> " << quoted(entry.filename) << endl; cout << if_not_empty(" Parameters", entry.parameters); - cout << if_not_empty(" Working directory", entry.workingDir); - cout << if_not_empty(" Icon file", entry.iconFilename); + cout << if_not_empty(" Working directory", entry.working_dir); + cout << if_not_empty(" Icon file", entry.icon_file); cout << if_not_empty(" Comment", entry.comment); - cout << if_not_empty(" App user model id", entry.appUserModelId); + cout << if_not_empty(" App user model id", entry.app_user_model_id); print(cout, entry, header); - cout << if_not_zero(" Icon index", entry.iconIndex); - cout << if_not_equal(" Show command", entry.showCmd, 1); - cout << if_not_equal(" Close on exit", entry.closeOnExit, IconEntry::NoSetting); + cout << if_not_zero(" Icon index", entry.icon_index); + cout << if_not_equal(" Show command", entry.show_command, 1); + cout << if_not_equal(" Close on exit", entry.close_on_exit, setup::icon_entry::NoSetting); cout << if_not_zero(" Hotkey", entry.hotkey); @@ -620,12 +607,12 @@ int main(int argc, char * argv[]) { } - if(header.numIniEntries) { + if(header.ini_entry_count) { cout << endl << "Ini entries:" << endl; } - for(size_t i = 0; i < header.numIniEntries; i++) { + for(size_t i = 0; i < header.ini_entry_count; i++) { - IniEntry entry; + setup::ini_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading ini entry #" << i; @@ -641,19 +628,19 @@ int main(int argc, char * argv[]) { } - if(header.numRegistryEntries) { + if(header.registry_entry_count) { cout << endl << "Registry entries:" << endl; } - for(size_t i = 0; i < header.numRegistryEntries; i++) { + for(size_t i = 0; i < header.registry_entry_count; i++) { - RegistryEntry entry; + setup::registry_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading registry entry #" << i; } cout << " - "; - if(entry.hive != RegistryEntry::Unset) { + if(entry.hive != setup::registry_entry::Unset) { cout << entry.hive << '\\'; } cout << quoted(entry.key); @@ -666,7 +653,7 @@ int main(int argc, char * argv[]) { if(!entry.value.empty()) { cout << " = " << quoted(entry.value); } - if(entry.type != RegistryEntry::None) { + if(entry.type != setup::registry_entry::None) { cout << " (" << color::cyan << entry.type << color::reset << ')'; } cout << endl; @@ -682,10 +669,10 @@ int main(int argc, char * argv[]) { } - if(header.numDeleteEntries) { + if(header.delete_entry_count) { cout << endl << "Delete entries:" << endl; } - for(size_t i = 0; i < header.numDeleteEntries; i++) { + for(size_t i = 0; i < header.delete_entry_count; i++) { setup::delete_entry entry; entry.load(*is, version); @@ -700,10 +687,10 @@ int main(int argc, char * argv[]) { } - if(header.numUninstallDeleteEntries) { + if(header.uninstall_delete_entry_count) { cout << endl << "Uninstall delete entries:" << endl; } - for(size_t i = 0; i < header.numUninstallDeleteEntries; i++) { + for(size_t i = 0; i < header.uninstall_delete_entry_count; i++) { setup::delete_entry entry; entry.load(*is, version); @@ -718,12 +705,12 @@ int main(int argc, char * argv[]) { } - if(header.numRunEntries) { + if(header.run_entry_count) { cout << endl << "Run entries:" << endl; } - for(size_t i = 0; i < header.numRunEntries; i++) { + for(size_t i = 0; i < header.run_entry_count; i++) { - RunEntry entry; + setup::run_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading install run entry #" << i; @@ -733,12 +720,12 @@ int main(int argc, char * argv[]) { } - if(header.numUninstallRunEntries) { + if(header.uninstall_run_entry_count) { cout << endl << "Uninstall run entries:" << endl; } - for(size_t i = 0; i < header.numUninstallRunEntries; i++) { + for(size_t i = 0; i < header.uninstall_run_entry_count; i++) { - RunEntry entry; + setup::run_entry entry; entry.load(*is, version); if(is->fail()) { log_error << "error reading uninstall run entry #" << i; @@ -770,12 +757,12 @@ int main(int argc, char * argv[]) { is->exceptions(std::ios_base::badbit | std::ios_base::failbit); - if(header.numFileLocationEntries) { + if(header.data_entry_count) { cout << endl << "File location entries:" << endl; } std::vector locations; - locations.resize(header.numFileLocationEntries); - for(size_t i = 0; i < header.numFileLocationEntries; i++) { + locations.resize(header.data_entry_count); + for(size_t i = 0; i < header.data_entry_count; i++) { setup::data_entry & entry = locations[i]; entry.load(*is, version); @@ -785,16 +772,17 @@ int main(int argc, char * argv[]) { cout << " - " << "File location #" << i << ':' << endl; - cout << if_not_zero(" First slice", entry.first_slice); - cout << if_not_equal(" Last slice", entry.last_slice, entry.first_slice); + cout << if_not_zero(" First slice", entry.chunk.first_slice); + cout << if_not_equal(" Last slice", entry.chunk.last_slice, entry.chunk.first_slice); - cout << " Chunk: offset " << color::cyan << print_hex(entry.chunk_offset) << color::reset - << " size " << color::cyan << print_hex(entry.chunk_size) << color::reset << std::endl; + cout << " Chunk: offset " << color::cyan << print_hex(entry.chunk.offset) + << color::reset << " size " << color::cyan << print_hex(entry.chunk.size) + << color::reset << std::endl; - cout << if_not_zero(" File offset", print_hex(entry.file_offset)); - cout << if_not_zero(" File size", print_bytes(entry.file_size)); + cout << if_not_zero(" File offset", print_hex(entry.file.offset)); + cout << if_not_zero(" File size", print_bytes(entry.file.size)); - cout << " Checksum: " << entry.checksum << endl; + cout << " Checksum: " << entry.file.checksum << endl; std::tm t; if(entry.options & setup::data_entry::TimeStampInUTC) { @@ -838,21 +826,15 @@ int main(int argc, char * argv[]) { } } - typedef std::map > Chunks; + typedef std::map Files; + typedef std::map Chunks; Chunks chunks; for(size_t i = 0; i < locations.size(); i++) { - const setup::data_entry & location = locations[i]; - - stream::chunk::compression_method compression = stream::chunk::Stored; - if(location.options & setup::data_entry::ChunkCompressed) { - compression = header.compressMethod; + setup::data_entry & location = locations[i]; + if(location.chunk.compression == stream::UnknownCompression) { + location.chunk.compression = header.compression; } - - chunks[stream::chunk(location.first_slice, location.chunk_offset, location.chunk_size, - compression, location.options & setup::data_entry::ChunkEncrypted) - ].push_back(i); - assert(header.compressMethod == stream::chunk::BZip2 - || !(location.options & setup::data_entry::BZipped)); + chunks[location.chunk][location.file] = i; } boost::shared_ptr slice_reader; @@ -863,41 +845,39 @@ int main(int argc, char * argv[]) { fs::path path(argv[1]); slice_reader = boost::make_shared(path.parent_path().string() + '/', path.stem().string(), - header.slicesPerDisk); + header.slices_per_disk); } try { - BOOST_FOREACH(Chunks::value_type & chunk, chunks) { - - cout << "[starting " << chunk.first.compression - << " chunk @ " << chunk.first.first_slice << " + " << print_hex(offsets.data_offset) - << " + " << print_hex(chunk.first.offset) << ']' << std::endl; + BOOST_FOREACH(const Chunks::value_type & chunk, chunks) { - std::sort(chunk.second.begin(), chunk.second.end(), FileLocationComparer(locations)); + cout << "[starting " << chunk.first.compression << " chunk @ " << chunk.first.first_slice + << " + " << print_hex(offsets.data_offset) << " + " << print_hex(chunk.first.offset) + << ']' << std::endl; stream::chunk_reader::pointer chunk_source; chunk_source = stream::chunk_reader::get(*slice_reader, chunk.first); uint64_t offset = 0; - BOOST_FOREACH(size_t location_i, chunk.second) { - const setup::data_entry & location = locations[location_i]; + BOOST_FOREACH(const Files::value_type & location, chunk.second) { + const stream::file & file = location.first; - if(location.file_offset < offset) { + if(file.offset < offset) { log_error << "bad offset"; return 1; } - if(location.file_offset > offset) { - std::cout << "discarding " << print_bytes(location.file_offset - offset) << std::endl; - discard(*chunk_source, location.file_offset - offset); + if(file.offset > offset) { + std::cout << "discarding " << print_bytes(file.offset - offset) << std::endl; + discard(*chunk_source, file.offset - offset); } - offset = location.file_offset + location.file_size; + offset = file.offset + file.size; std::cout << "-> reading "; bool named = false; - BOOST_FOREACH(size_t file_i, files_for_location[location_i]) { + BOOST_FOREACH(size_t file_i, files_for_location[location.second]) { if(!files[file_i].destination.empty()) { std::cout << '"' << files[file_i].destination << '"'; named = true; @@ -907,15 +887,15 @@ int main(int argc, char * argv[]) { if(!named) { std::cout << "unnamed file"; } - std::cout << " @ " << print_hex(location.file_offset) - << " (" << print_bytes(location.file_size) << ')' << std::endl; + std::cout << " @ " << print_hex(file.offset) + << " (" << print_bytes(file.size) << ')' << std::endl; crypto::checksum checksum; stream::file_reader::pointer file_source; - file_source = stream::file_reader::get(*chunk_source, location, version, &checksum); + file_source = stream::file_reader::get(*chunk_source, file, &checksum); - BOOST_FOREACH(size_t file_i, files_for_location[location_i]) { + BOOST_FOREACH(size_t file_i, files_for_location[location.second]) { if(!files[file_i].destination.empty()) { std::ofstream ofs(files[file_i].destination.c_str()); @@ -940,7 +920,7 @@ int main(int argc, char * argv[]) { ofs.write(buffer, n); total += uint64_t(n); - float new_status = float(size_t(1000.f * float(total) / float(location.file_size))) + float new_status = float(size_t(1000.f * float(total) / float(file.size))) * (1 / 1000.f); if(status != new_status && new_status != 100.f) { @@ -973,10 +953,10 @@ int main(int argc, char * argv[]) { progress::clear(); - if(checksum != location.checksum) { + if(checksum != file.checksum) { log_warning << "checksum mismatch:"; log_warning << "actual: " << checksum; - log_warning << "expected: " << location.checksum; + log_warning << "expected: " << file.checksum; } } } diff --git a/src/crypto/checksum.cpp b/src/crypto/checksum.cpp index b6731ee..20f71a6 100644 --- a/src/crypto/checksum.cpp +++ b/src/crypto/checksum.cpp @@ -23,7 +23,7 @@ bool checksum::operator==(const checksum & o) const { } // namespace crypto -ENUM_NAMES(crypto::checksum_type, "Checksum Type", +NAMES(crypto::checksum_type, "Checksum Type", "Adler32", "CRC32", "MD5", diff --git a/src/loader/offsets.cpp b/src/loader/offsets.cpp index 5dacb66..c946729 100644 --- a/src/loader/offsets.cpp +++ b/src/loader/offsets.cpp @@ -23,7 +23,7 @@ struct setup_loader_version { unsigned char magic[12]; // Earliest known version with that ID. - InnoVersionConstant version; + setup::version_constant version; }; @@ -87,7 +87,7 @@ bool offsets::load_offsets_at(std::istream & is, uint32_t pos) { return false; } - InnoVersionConstant version = 0; + setup::version_constant version = 0; for(size_t i = 0; i < ARRAY_SIZE(known_setup_loader_versions); i++) { BOOST_STATIC_ASSERT(ARRAY_SIZE(known_setup_loader_versions[i].magic) == ARRAY_SIZE(magic)); if(!memcmp(magic, known_setup_loader_versions[i].magic, ARRAY_SIZE(magic))) { diff --git a/src/setup/IconEntry.hpp b/src/setup/IconEntry.hpp deleted file mode 100644 index b86ace5..0000000 --- a/src/setup/IconEntry.hpp +++ /dev/null @@ -1,59 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_ICONENTRY_HPP -#define INNOEXTRACT_SETUP_ICONENTRY_HPP - -#include -#include -#include - -#include "setup/SetupItem.hpp" -#include "setup/version.hpp" -#include "util/enum.hpp" -#include "util/flags.hpp" - -struct IconEntry : public SetupItem { - - FLAGS(Options, - NeverUninstall, - CreateOnlyIfFileExists, - UseAppPaths, - FolderShortcut, - ExcludeFromShowInNewInstall, - // obsolete options: - RunMinimized - ); - - enum CloseOnExit { - NoSetting, - Yes, - No, - }; - - std::string name; - std::string filename; - std::string parameters; - std::string workingDir; - std::string iconFilename; - std::string comment; - std::string appUserModelId; - - int iconIndex; - - int showCmd; - - CloseOnExit closeOnExit; - - uint16_t hotkey; - - Options options; - - void load(std::istream & is, const inno_version & version); - -}; - -FLAGS_OVERLOADS(IconEntry::Options) -NAMED_ENUM(IconEntry::Options) - -NAMED_ENUM(IconEntry::CloseOnExit) - -#endif // INNOEXTRACT_SETUP_ICONENTRY_HPP diff --git a/src/setup/IniEntry.hpp b/src/setup/IniEntry.hpp deleted file mode 100644 index 9dd3f87..0000000 --- a/src/setup/IniEntry.hpp +++ /dev/null @@ -1,37 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_INIENTRY_HPP -#define INNOEXTRACT_SETUP_INIENTRY_HPP - -#include -#include - -#include "setup/SetupItem.hpp" -#include "setup/version.hpp" -#include "util/enum.hpp" -#include "util/flags.hpp" - -struct IniEntry : public SetupItem { - - FLAGS(Options, - CreateKeyIfDoesntExist, - UninsDeleteEntry, - UninsDeleteEntireSection, - UninsDeleteSectionIfEmpty, - HasValue - ); - - std::string inifile; - std::string section; - std::string key; - std::string value; - - Options options; - - void load(std::istream & is, const inno_version & version); - -}; - -FLAGS_OVERLOADS(IniEntry::Options) -NAMED_ENUM(IniEntry::Options) - -#endif // INNOEXTRACT_SETUP_INIENTRY_HPP diff --git a/src/setup/LanguageEntry.cpp b/src/setup/LanguageEntry.cpp deleted file mode 100644 index 1634f5e..0000000 --- a/src/setup/LanguageEntry.cpp +++ /dev/null @@ -1,67 +0,0 @@ - -#include "setup/LanguageEntry.hpp" - -#include -#include - -#include "util/load.hpp" - -void convert(iconv_t converter, const std::string & from, std::string & to); - -void LanguageEntry::load(std::istream & is, const inno_version & version) { - - if(version >= INNO_VERSION(4, 0, 0)) { - is >> encoded_string(name, version.codepage()); - } else { - name = "default"; - } - - is >> encoded_string(languageName, (version >= INNO_VERSION(4, 2, 2)) ? 1200 : 1252); - - is >> encoded_string(dialogFontName, version.codepage()); - is >> encoded_string(titleFontName, version.codepage()); - is >> encoded_string(welcomeFontName, version.codepage()); - is >> encoded_string(copyrightFontName, version.codepage()); - - if(version >= INNO_VERSION(4, 0, 0)) { - is >> binary_string(data); - } - - if(version >= INNO_VERSION(4, 0, 1)) { - is >> ansi_string(licenseText); - is >> ansi_string(infoBeforeText); - is >> ansi_string(infoAfterText); - } else { - licenseText.clear(), infoBeforeText.clear(), infoAfterText.clear(); - } - - languageId = load_number(is); - - if(version >= INNO_VERSION(4, 2, 2) && (version < INNO_VERSION(5, 3, 0) || !version.unicode)) { - codepage = load_number(is); - } else { - codepage = 0; - } - if(!codepage) { - codepage = version.codepage(); - } - - dialogFontSize = load_number(is); - - if(version < INNO_VERSION(4, 1, 0)) { - dialogFontStandardHeight = load_number(is); - } else { - dialogFontStandardHeight = 0; - } - - titleFontSize = load_number(is); - welcomeFontSize = load_number(is); - copyrightFontSize = load_number(is); - - if(version >= INNO_VERSION(5, 2, 3)) { - rightToLeft = ::load(is); - } else { - rightToLeft = false; - } - -} diff --git a/src/setup/LanguageEntry.hpp b/src/setup/LanguageEntry.hpp deleted file mode 100644 index 961f75f..0000000 --- a/src/setup/LanguageEntry.hpp +++ /dev/null @@ -1,40 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_LANGUAGEENTRY_HPP -#define INNOEXTRACT_SETUP_LANGUAGEENTRY_HPP - -#include -#include -#include - -#include "setup/version.hpp" - -struct LanguageEntry { - - // introduced in 2.0.1 - - std::string name; - std::string languageName; - std::string dialogFontName; - std::string titleFontName; - std::string welcomeFontName; - std::string copyrightFontName; - std::string data; - std::string licenseText; - std::string infoBeforeText; - std::string infoAfterText; - - uint32_t languageId; - uint32_t codepage; - size_t dialogFontSize; - size_t dialogFontStandardHeight; - size_t titleFontSize; - size_t welcomeFontSize; - size_t copyrightFontSize; - - bool rightToLeft; - - void load(std::istream & is, const inno_version & version); - -}; - -#endif // INNOEXTRACT_SETUP_LANGUAGEENTRY_HPP diff --git a/src/setup/PermissionEntry.cpp b/src/setup/PermissionEntry.cpp deleted file mode 100644 index 30619db..0000000 --- a/src/setup/PermissionEntry.cpp +++ /dev/null @@ -1,12 +0,0 @@ - -#include "setup/PermissionEntry.hpp" - -#include "util/load.hpp" - -void PermissionEntry::load(std::istream & is, const inno_version & version) { - - (void)version; - - is >> binary_string(permissions); // an array of TGrantPermissionEntry's - -} diff --git a/src/setup/PermissionEntry.hpp b/src/setup/PermissionEntry.hpp deleted file mode 100644 index 528b328..0000000 --- a/src/setup/PermissionEntry.hpp +++ /dev/null @@ -1,20 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_PERMISSIONENTRY_HPP -#define INNOEXTRACT_SETUP_PERMISSIONENTRY_HPP - -#include -#include - -#include "setup/version.hpp" - -struct PermissionEntry { - - // introduced in 4.1.0 - - std::string permissions; - - void load(std::istream & is, const inno_version & version); - -}; - -#endif // INNOEXTRACT_SETUP_PERMISSIONENTRY_HPP diff --git a/src/setup/RunEntry.hpp b/src/setup/RunEntry.hpp deleted file mode 100644 index fa4088b..0000000 --- a/src/setup/RunEntry.hpp +++ /dev/null @@ -1,57 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_RUNENTRY_HPP -#define INNOEXTRACT_SETUP_RUNENTRY_HPP - -#include -#include - -#include "setup/SetupItem.hpp" -#include "setup/version.hpp" -#include "util/enum.hpp" -#include "util/flags.hpp" - -struct RunEntry : public SetupItem { - - FLAGS(Options, - ShellExec, - SkipIfDoesntExist, - PostInstall, - Unchecked, - SkipIfSilent, - Skipif_not_equalSilent, - HideWizard, - Bits32, - Bits64, - RunAsOriginalUser - ); - - enum Wait { - WaitUntilTerminated, - NoWait, - WaitUntilIdle, - }; - - std::string name; - std::string parameters; - std::string workingDir; - std::string runOnceId; - std::string statusMessage; - std::string verb; - std::string description; - - int showCmd; - - Wait wait; - - Options options; - - void load(std::istream & is, const inno_version & version); - -}; - -FLAGS_OVERLOADS(RunEntry::Options) -NAMED_ENUM(RunEntry::Options) - -NAMED_ENUM(RunEntry::Wait) - -#endif // INNOEXTRACT_SETUP_RUNENTRY_HPP diff --git a/src/setup/SetupComponentEntry.cpp b/src/setup/SetupComponentEntry.cpp deleted file mode 100644 index 9ecbf55..0000000 --- a/src/setup/SetupComponentEntry.cpp +++ /dev/null @@ -1,83 +0,0 @@ - -#include "setup/SetupComponentEntry.hpp" - -#include "util/load.hpp" -#include "util/storedenum.hpp" - -namespace { - -STORED_FLAGS_MAP(StoredSetupComponentOptions0, - SetupComponentEntry::Fixed, - SetupComponentEntry::Restart, - SetupComponentEntry::DisableNoUninstallWarning, -); - -// starting with version 3.0.8 -STORED_FLAGS_MAP(StoredSetupComponentOptions1, - SetupComponentEntry::Fixed, - SetupComponentEntry::Restart, - SetupComponentEntry::DisableNoUninstallWarning, - SetupComponentEntry::Exclusive, -); - -// starting with version 4.2.3 -STORED_FLAGS_MAP(StoredSetupComponentOptions2, - SetupComponentEntry::Fixed, - SetupComponentEntry::Restart, - SetupComponentEntry::DisableNoUninstallWarning, - SetupComponentEntry::Exclusive, - SetupComponentEntry::DontInheritCheck, -); - -} // anonymous namespace - -void SetupComponentEntry::load(std::istream & is, const inno_version & version) { - - is >> encoded_string(name, version.codepage()); - is >> encoded_string(description, version.codepage()); - is >> encoded_string(types, version.codepage()); - if(version >= INNO_VERSION(4, 0, 1)) { - is >> encoded_string(languages, version.codepage()); - } else { - languages.clear(); - } - if(version >= INNO_VERSION(3, 0, 8)) { - is >> encoded_string(check, version.codepage()); - } else { - check.clear(); - } - - if(version >= INNO_VERSION(4, 0, 0)) { - extraDiskSpaceRequired = load_number(is); - } else { - extraDiskSpaceRequired = load_number(is); - } - - if(version >= INNO_VERSION(3, 0, 8)) { - level = load_number(is); - used = load_number(is); - } else { - level = 0, used = true; - } - - minVersion.load(is, version); - onlyBelowVersion.load(is, version); - - if(version >= INNO_VERSION(4, 2, 3)) { - options = stored_flags(is).get(); - } else if(version >= INNO_VERSION(3, 0, 8)) { - options = stored_flags(is).get(); - } else { - options = stored_flags(is).get(); - } - - size = (version >= INNO_VERSION(4, 0, 0)) ? load_number(is) : load_number(is); -} - -ENUM_NAMES(SetupComponentEntry::Options, "Setup Component Option", - "fixed", - "restart", - "disable no uninstall warning", - "exclusive", - "don't inherit check", -) diff --git a/src/setup/SetupComponentEntry.hpp b/src/setup/SetupComponentEntry.hpp deleted file mode 100644 index 7e20ffc..0000000 --- a/src/setup/SetupComponentEntry.hpp +++ /dev/null @@ -1,51 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_SETUPCOMPONENTENTRY_HPP -#define INNOEXTRACT_SETUP_SETUPCOMPONENTENTRY_HPP - -#include -#include -#include - -#include "setup/version.hpp" -#include "setup/WindowsVersion.hpp" -#include "util/enum.hpp" -#include "util/flags.hpp" - -struct SetupComponentEntry { - - // introduced in 2.0.0 - - FLAGS(Options, - Fixed, - Restart, - DisableNoUninstallWarning, - Exclusive, - DontInheritCheck - ); - - std::string name; - std::string description; - std::string types; - std::string languages; - std::string check; - - uint64_t extraDiskSpaceRequired; - - int level; - bool used; - - WindowsVersion minVersion; - WindowsVersion onlyBelowVersion; - - Options options; - - uint64_t size; - - void load(std::istream & is, const inno_version & version); - -}; - -FLAGS_OVERLOADS(SetupComponentEntry::Options) -NAMED_ENUM(SetupComponentEntry::Options) - -#endif // INNOEXTRACT_SETUP_SETUPCOMPONENTENTRY_HPP diff --git a/src/setup/SetupHeader.cpp b/src/setup/SetupHeader.cpp deleted file mode 100644 index 50623ce..0000000 --- a/src/setup/SetupHeader.cpp +++ /dev/null @@ -1,664 +0,0 @@ - -#include "SetupHeader.hpp" - -#include -#include - -#include - -#include "util/load.hpp" -#include "util/storedenum.hpp" - -namespace { - -STORED_ENUM_MAP(StoredInstallMode, SetupHeader::NormalInstallMode, - SetupHeader::NormalInstallMode, - SetupHeader::SilentInstallMode, - SetupHeader::VerySilentInstallMode -); - -STORED_ENUM_MAP(StoredUninstallLogMode, SetupHeader::AppendLog, - SetupHeader::AppendLog, - SetupHeader::NewLog, - SetupHeader::OverwriteLog -); - -STORED_ENUM_MAP(StoredUninstallStyle, SetupHeader::ClassicStyle, - SetupHeader::ClassicStyle, - SetupHeader::ModernStyle -); - -STORED_ENUM_MAP(StoredDirExistsWarning, SetupHeader::Auto, - SetupHeader::Auto, - SetupHeader::No, - SetupHeader::Yes -); - -// pre- 5.3.7 -STORED_ENUM_MAP(StoredPrivileges0, SetupHeader::NoPrivileges, - SetupHeader::NoPrivileges, - SetupHeader::PowerUserPrivileges, - SetupHeader::AdminPriviliges, -); - -// post- 5.3.7 -STORED_ENUM_MAP(StoredPrivileges1, SetupHeader::NoPrivileges, - SetupHeader::NoPrivileges, - SetupHeader::PowerUserPrivileges, - SetupHeader::AdminPriviliges, - SetupHeader::LowestPrivileges -); - -STORED_ENUM_MAP(StoredShowLanguageDialog, SetupHeader::Yes, - SetupHeader::Yes, - SetupHeader::No, - SetupHeader::Auto -); - -STORED_ENUM_MAP(StoredLanguageDetectionMethod, SetupHeader::UILanguage, - SetupHeader::UILanguage, - SetupHeader::LocaleLanguage, - SetupHeader::NoLanguageDetection -); - -STORED_FLAGS_MAP(StoredArchitectures, - SetupHeader::ArchitectureUnknown, - SetupHeader::X86, - SetupHeader::Amd64, - SetupHeader::IA64 -); - -STORED_ENUM_MAP(StoredRestartComputer, SetupHeader::Auto, - SetupHeader::Auto, - SetupHeader::No, - SetupHeader::Yes -); - -// pre-4.2.5 -STORED_ENUM_MAP(StoredCompressionMethod0, stream::chunk::Unknown, - stream::chunk::Zlib, - stream::chunk::BZip2, - stream::chunk::LZMA1 -); - -// 4.2.5 -STORED_ENUM_MAP(StoredCompressionMethod1, stream::chunk::Unknown, - stream::chunk::Stored, - stream::chunk::BZip2, - stream::chunk::LZMA1 -); - -// [4.2.6 5.3.9) -STORED_ENUM_MAP(StoredCompressionMethod2, stream::chunk::Unknown, - stream::chunk::Stored, - stream::chunk::Zlib, - stream::chunk::BZip2, - stream::chunk::LZMA1 -); - -// 5.3.9+ -STORED_ENUM_MAP(StoredCompressionMethod3, stream::chunk::Unknown, - stream::chunk::Stored, - stream::chunk::Zlib, - stream::chunk::BZip2, - stream::chunk::LZMA1, - stream::chunk::LZMA2 -); - -STORED_ENUM_MAP(StoredDisablePage, SetupHeader::Auto, - SetupHeader::Auto, - SetupHeader::No, - SetupHeader::Yes -); - -} // anonymous namespace - -void SetupHeader::load(std::istream & is, const inno_version & version) { - - options = 0; - - if(version < INNO_VERSION(1, 3, 21)) { - ::load(is); // uncompressed size of the setup header structure - } - - is >> encoded_string(appName, version.codepage()); - is >> encoded_string(appVerName, version.codepage()); - if(version >= INNO_VERSION(1, 3, 21)) { - is >> encoded_string(appId, version.codepage()); - } - is >> encoded_string(appCopyright, version.codepage()); - if(version >= INNO_VERSION(1, 3, 21)) { - is >> encoded_string(appPublisher, version.codepage()); - is >> encoded_string(appPublisherURL, version.codepage()); - } else { - appPublisher.clear(), appPublisherURL.clear(); - } - if(version >= INNO_VERSION(5, 1, 13)) { - is >> encoded_string(appSupportPhone, version.codepage()); - } else { - appSupportPhone.clear(); - } - if(version >= INNO_VERSION(1, 3, 21)) { - is >> encoded_string(appSupportURL, version.codepage()); - is >> encoded_string(appUpdatesURL, version.codepage()); - is >> encoded_string(appVersion, version.codepage()); - } else { - appSupportURL.clear(), appUpdatesURL.clear(), appVersion.clear(); - } - is >> encoded_string(defaultDirName, version.codepage()); - is >> encoded_string(defaultGroupName, version.codepage()); - if(version < INNO_VERSION(3, 0, 0)) { - is >> ansi_string(uninstallIconName); - } else { - uninstallIconName.clear(); - } - is >> encoded_string(baseFilename, version.codepage()); - if(version >= INNO_VERSION(1, 3, 21)) { - if(version < INNO_VERSION(5, 2, 5)) { - is >> ansi_string(licenseText); - is >> ansi_string(infoBeforeText); - is >> ansi_string(infoAfterText); - } - is >> encoded_string(uninstallFilesDir, version.codepage()); - is >> encoded_string(uninstallDisplayName, version.codepage()); - is >> encoded_string(uninstallDisplayIcon, version.codepage()); - is >> encoded_string(appMutex, version.codepage()); - } else { - licenseText.clear(), infoBeforeText.clear(), infoAfterText.clear(); - uninstallFilesDir.clear(), uninstallDisplayName.clear(); - uninstallDisplayIcon.clear(), appMutex.clear(); - } - if(version >= INNO_VERSION(3, 0, 0)) { - is >> encoded_string(defaultUserInfoName, version.codepage()); - is >> encoded_string(defaultUserInfoOrg, version.codepage()); - } else { - defaultUserInfoName.clear(), defaultUserInfoOrg.clear(); - } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { - is >> encoded_string(defaultUserInfoSerial, version.codepage()); - if(version < INNO_VERSION(5, 2, 5)) { - is >> binary_string(compiledCodeText); - } - } else { - defaultUserInfoSerial.clear(), compiledCodeText.clear(); - } - if(version >= INNO_VERSION(4, 2, 4)) { - is >> encoded_string(appReadmeFile, version.codepage()); - is >> encoded_string(appContact, version.codepage()); - is >> encoded_string(appComments, version.codepage()); - is >> encoded_string(appModifyPath, version.codepage()); - } else { - appReadmeFile.clear(), appContact.clear(); - appComments.clear(), appModifyPath.clear(); - } - if(version >= INNO_VERSION(5, 3, 8)) { - is >> encoded_string(createUninstallRegKey, version.codepage()); - } else { - createUninstallRegKey.clear(); - } - if(version >= INNO_VERSION(5, 3, 10)) { - is >> encoded_string(uninstallable, version.codepage()); - } else { - uninstallable.clear(); - } - if(version >= INNO_VERSION(5, 2, 5)) { - is >> ansi_string(licenseText); - is >> ansi_string(infoBeforeText); - is >> ansi_string(infoAfterText); - } - if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) { - is >> binary_string(signedUninstallerSignature); - } else { - signedUninstallerSignature.clear(); - } - if(version >= INNO_VERSION(5, 2, 5)) { - is >> binary_string(compiledCodeText); - } - - if(version >= INNO_VERSION(2, 0, 6) && !version.unicode) { - leadBytes = stored_char_set(is); - } else { - leadBytes = 0; - } - - if(version >= INNO_VERSION(4, 0, 0)) { - numLanguageEntries = load_number(is); - } else if(version >= INNO_VERSION(2, 0, 1)) { - numLanguageEntries = 1; - } else { - numLanguageEntries = 0; - } - - if(version >= INNO_VERSION(4, 2, 1)) { - numCustomMessageEntries = load_number(is); - } else { - numCustomMessageEntries = 0; - } - - if(version >= INNO_VERSION(4, 1, 0)) { - numPermissionEntries = load_number(is); - } else { - numPermissionEntries = 0; - } - - if(version >= INNO_VERSION(2, 0, 0)) { - numTypeEntries = load_number(is); - numComponentEntries = load_number(is); - numTaskEntries = load_number(is); - } else { - numTypeEntries = 0, numComponentEntries = 0, numTaskEntries = 0; - } - - numDirectoryEntries = load_number(is, version.bits); - numFileEntries = load_number(is, version.bits); - numFileLocationEntries = load_number(is, version.bits); - numIconEntries = load_number(is, version.bits); - numIniEntries = load_number(is, version.bits); - numRegistryEntries = load_number(is, version.bits); - numDeleteEntries = load_number(is, version.bits); - numUninstallDeleteEntries = load_number(is, version.bits); - numRunEntries = load_number(is, version.bits); - numUninstallRunEntries = load_number(is, version.bits); - - int32_t licenseSize; - int32_t infoBeforeSize; - int32_t infoAfterSize; - if(version < INNO_VERSION(1, 3, 21)) { - licenseSize = load_number(is, version.bits); - infoBeforeSize = load_number(is, version.bits); - infoAfterSize = load_number(is, version.bits); - } - - minVersion.load(is, version); - onlyBelowVersion.load(is, version); - - backColor = load_number(is); - if(version >= INNO_VERSION(1, 3, 21)) { - backColor2 = load_number(is); - } else { - backColor2 = 0; - } - wizardImageBackColor = load_number(is); - if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) { - wizardSmallImageBackColor = load_number(is); - } else { - wizardSmallImageBackColor = 0; - } - - if(version < INNO_VERSION(4, 2, 0)) { - password.crc32 = load_number(is), password.type = crypto::CRC32; - } else if(version < INNO_VERSION(5, 3, 9)) { - is.read(password.md5, sizeof(password.md5)), password.type = crypto::MD5; - } else { - is.read(password.sha1, sizeof(password.sha1)), password.type = crypto::SHA1; - } - 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 = load_number(is); - slicesPerDisk = 1; - } else { - extraDiskSpaceRequired = load_number(is); - slicesPerDisk = load_number(is); - } - - if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) { - installMode = stored_enum(is).get(); - } else { - installMode = NormalInstallMode; - } - - if(version >= INNO_VERSION(1, 3, 21)) { - uninstallLogMode = stored_enum(is).get(); - } else { - uninstallLogMode = AppendLog; - } - - if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) { - uninstallStyle = stored_enum(is).get(); - } else { - uninstallStyle = (version < INNO_VERSION(5, 0, 0)) ? ClassicStyle : ModernStyle; - } - - if(version >= INNO_VERSION(1, 3, 21)) { - dirExistsWarning = stored_enum(is).get(); - } else { - dirExistsWarning = Auto; - } - - if(version >= INNO_VERSION(3, 0, 0) && version < INNO_VERSION(3, 0, 3)) { - AutoBoolean val = stored_enum(is).get(); - switch(val) { - case Yes: options |= AlwaysRestart; break; - case Auto: options |= RestartIfNeededByRun; break; - case No: break; - } - } - - if(version >= INNO_VERSION(5, 3, 7)) { - privilegesRequired = stored_enum(is).get(); - } else if(version >= INNO_VERSION(3, 0, 4)) { - privilegesRequired = stored_enum(is).get(); - } - - if(version >= INNO_VERSION(4, 0, 10)) { - showLanguageDialog = stored_enum(is).get(); - languageDetectionMethod = stored_enum(is).get(); - } - - if(version >= INNO_VERSION(5, 3, 9)) { - compressMethod = stored_enum(is).get(); - } else if(version >= INNO_VERSION(4, 2, 6)) { - compressMethod = stored_enum(is).get(); - } else if(version >= INNO_VERSION(4, 2, 5)) { - compressMethod = stored_enum(is).get(); - } else if(version >= INNO_VERSION(4, 1, 5)) { - compressMethod = stored_enum(is).get(); - } - - if(version >= INNO_VERSION(5, 1, 0)) { - architecturesAllowed = stored_flags(is).get(); - architecturesInstallIn64BitMode = stored_flags(is).get(); - } else { - architecturesAllowed = Architectures::all(); - architecturesInstallIn64BitMode = Architectures::all(); - } - - if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) { - signedUninstallerOrigSize = load_number(is); - signedUninstallerHdrChecksum = load_number(is); - } else { - signedUninstallerOrigSize = signedUninstallerHdrChecksum = 0; - } - - if(version >= INNO_VERSION(5, 3, 3)) { - disableDirPage = stored_enum(is).get(); - disableProgramGroupPage = stored_enum(is).get(); - } - - if(version >= INNO_VERSION(5, 3, 6)) { - uninstallDisplaySize = load_number(is); - } else { - uninstallDisplaySize = 0; - } - - - stored_flag_reader flags(is); - - flags.add(DisableStartupPrompt); - if(version < INNO_VERSION(5, 3, 10)) { - flags.add(Uninstallable); - } - flags.add(CreateAppDir); - if(version < INNO_VERSION(5, 3, 3)) { - flags.add(DisableDirPage); - } - if(version < INNO_VERSION(1, 3, 21)) { - flags.add(DisableDirExistsWarning); - } - if(version < INNO_VERSION(5, 3, 3)) { - flags.add(DisableProgramGroupPage); - } - flags.add(AllowNoIcons); - if(version < INNO_VERSION(3, 0, 0) || version >= INNO_VERSION(3, 0, 3)) { - flags.add(AlwaysRestart); - } - if(version < INNO_VERSION(1, 3, 21)) { - flags.add(BackSolid); - } - flags.add(AlwaysUsePersonalGroup); - flags.add(WindowVisible); - flags.add(WindowShowCaption); - flags.add(WindowResizable); - flags.add(WindowStartMaximized); - flags.add(EnableDirDoesntExistWarning); - if(version < INNO_VERSION(4, 1, 2)) { - flags.add(DisableAppendDir); - } - flags.add(Password); - flags.add(AllowRootDirectory); - flags.add(DisableFinishedPage); - if(version.bits != 16) { - if(version < INNO_VERSION(3, 0, 4)) { - flags.add(AdminPrivilegesRequired); - } - if(version < INNO_VERSION(3, 0, 0)) { - flags.add(AlwaysCreateUninstallIcon); - } - if(version < INNO_VERSION(1, 3, 21)) { - flags.add(OverwriteUninstRegEntries); - } - flags.add(ChangesAssociations); - } - if(version >= INNO_VERSION(1, 3, 21)) { - if(version < INNO_VERSION(5, 3, 8)) { - flags.add(CreateUninstallRegKey); - } - flags.add(UsePreviousAppDir); - flags.add(BackColorHorizontal); - flags.add(UsePreviousGroup); - flags.add(UpdateUninstallLogAppName); - } - if(version >= INNO_VERSION(2, 0, 0)) { - flags.add(UsePreviousSetupType); - flags.add(DisableReadyMemo); - flags.add(AlwaysShowComponentsList); - flags.add(FlatComponentsList); - flags.add(ShowComponentSizes); - flags.add(UsePreviousTasks); - flags.add(DisableReadyPage); - } - if(version >= INNO_VERSION(2, 0, 7)) { - flags.add(AlwaysShowDirOnReadyPage); - flags.add(AlwaysShowGroupOnReadyPage); - } - if(version >= INNO_VERSION(2, 0, 17) && version < INNO_VERSION(4, 1, 5)) { - flags.add(BzipUsed); - } - if(version >= INNO_VERSION(2, 0, 18)) { - flags.add(AllowUNCPath); - } - if(version >= INNO_VERSION(3, 0, 0)) { - flags.add(UserInfoPage); - flags.add(UsePreviousUserInfo); - } - if(version >= INNO_VERSION(3, 0, 1)) { - flags.add(UninstallRestartComputer); - } - if(version >= INNO_VERSION(3, 0, 3)) { - flags.add(RestartIfNeededByRun); - } - if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { - flags.add(ShowTasksTreeLines); - } - if(version >= INNO_VERSION(4, 0, 0) && version < INNO_VERSION(4, 0, 10)) { - flags.add(ShowLanguageDialog); - } - - if(version >= INNO_VERSION(4, 0, 1) && version < INNO_VERSION(4, 0, 10)) { - flags.add(DetectLanguageUsingLocale); - } - if(version >= INNO_VERSION(4, 0, 9)) { - flags.add(AllowCancelDuringInstall); - } else { - options |= AllowCancelDuringInstall; - } - if(version >= INNO_VERSION(4, 1, 3)) { - flags.add(WizardImageStretch); - } - if(version >= INNO_VERSION(4, 1, 8)) { - flags.add(AppendDefaultDirName); - flags.add(AppendDefaultGroupName); - } - if(version >= INNO_VERSION(4, 2, 2)) { - flags.add(EncryptionUsed); - } - if(version >= INNO_VERSION(5, 0, 4)) { - flags.add(ChangesEnvironment); - } - if(version >= INNO_VERSION(5, 1, 7) && !version.unicode) { - flags.add(ShowUndisplayableLanguages); - } - if(version >= INNO_VERSION(5, 1, 13)) { - flags.add(SetupLogging); - } - if(version >= INNO_VERSION(5, 2, 1)) { - flags.add(SignedUninstaller); - } - if(version >= INNO_VERSION(5, 3, 8)) { - flags.add(UsePreviousLanguage); - } - if(version >= INNO_VERSION(5, 3, 9)) { - flags.add(DisableWelcomePage); - } - - options |= flags; - - if(version < INNO_VERSION(3, 0, 4)) { - privilegesRequired = (options & AdminPrivilegesRequired) ? AdminPriviliges : NoPrivileges; - } - - if(version < INNO_VERSION(4, 0, 10)) { - showLanguageDialog = (options & ShowLanguageDialog) ? Yes : No; - languageDetectionMethod = (options & DetectLanguageUsingLocale) ? LocaleLanguage : UILanguage; - } - - if(version < INNO_VERSION(4, 1, 5)) { - compressMethod = (options & BzipUsed) ? stream::chunk::BZip2 : stream::chunk::Zlib; - } - - if(version < INNO_VERSION(5, 3, 3)) { - disableDirPage = (options & DisableDirPage) ? Yes : No; - disableProgramGroupPage = (options & DisableProgramGroupPage) ? Yes : No; - } - - if(version < INNO_VERSION(1, 3, 21)) { - if(licenseSize > 0) { - std::string temp; - temp.resize(size_t(licenseSize)); - is.read(&temp[0], licenseSize); - to_utf8(temp, licenseText); - } - if(infoBeforeSize > 0) { - std::string temp; - temp.resize(size_t(infoBeforeSize)); - is.read(&temp[0], infoBeforeSize); - to_utf8(temp, infoBeforeText); - } - if(infoAfterSize > 0) { - std::string temp; - temp.resize(size_t(infoAfterSize)); - is.read(&temp[0], infoAfterSize); - to_utf8(temp, infoAfterText); - } - } - -} - -ENUM_NAMES(SetupHeader::Options, "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(SetupHeader::Options::bits == enum_names::count); - -ENUM_NAMES(SetupHeader::Architectures, "Architecture", - "unknown", - "x86", - "amd64", - "IA64", -) - -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", -) diff --git a/src/setup/SetupHeader.hpp b/src/setup/SetupHeader.hpp deleted file mode 100644 index eb884f3..0000000 --- a/src/setup/SetupHeader.hpp +++ /dev/null @@ -1,243 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_SETUPHEADER_HPP -#define INNOEXTRACT_SETUP_SETUPHEADER_HPP - -#include -#include -#include -#include -#include - -#include "crypto/checksum.hpp" -#include "setup/version.hpp" -#include "setup/WindowsVersion.hpp" -#include "stream/chunk.hpp" -#include "util/enum.hpp" -#include "util/flags.hpp" - -typedef char SetupSalt[8]; - -struct SetupHeader { - - // Setup data header. - - FLAGS(Options, - - DisableStartupPrompt, - CreateAppDir, - AllowNoIcons, - AlwaysRestart, - AlwaysUsePersonalGroup, - WindowVisible, - WindowShowCaption, - WindowResizable, - WindowStartMaximized, - EnableDirDoesntExistWarning, - Password, - AllowRootDirectory, - DisableFinishedPage, - ChangesAssociations, - UsePreviousAppDir, - BackColorHorizontal, - UsePreviousGroup, - UpdateUninstallLogAppName, - UsePreviousSetupType, - DisableReadyMemo, - AlwaysShowComponentsList, - FlatComponentsList, - ShowComponentSizes, - UsePreviousTasks, - DisableReadyPage, - AlwaysShowDirOnReadyPage, - AlwaysShowGroupOnReadyPage, - AllowUNCPath, - UserInfoPage, - UsePreviousUserInfo, - UninstallRestartComputer, - RestartIfNeededByRun, - ShowTasksTreeLines, - AllowCancelDuringInstall, - WizardImageStretch, - AppendDefaultDirName, - AppendDefaultGroupName, - EncryptionUsed, - ChangesEnvironment, - ShowUndisplayableLanguages, - SetupLogging, - SignedUninstaller, - UsePreviousLanguage, - DisableWelcomePage, - - // Obsolete flags - Uninstallable, - DisableDirPage, - DisableProgramGroupPage, - DisableAppendDir, - AdminPrivilegesRequired, - AlwaysCreateUninstallIcon, - CreateUninstallRegKey, - BzipUsed, - ShowLanguageDialog, - DetectLanguageUsingLocale, - DisableDirExistsWarning, - BackSolid, - OverwriteUninstRegEntries - ); - - FLAGS(Architectures, - ArchitectureUnknown, - X86, - Amd64, - IA64 - ); - - 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 numDirectoryEntries; - size_t numFileEntries; - size_t numFileLocationEntries; - size_t numIconEntries; - size_t numIniEntries; - size_t numRegistryEntries; - size_t numDeleteEntries; - size_t numUninstallDeleteEntries; - size_t numRunEntries; - size_t numUninstallRunEntries; - - WindowsVersion minVersion; - WindowsVersion onlyBelowVersion; - - typedef uint32_t Color; - Color backColor; - Color backColor2; - Color wizardImageBackColor; - Color wizardSmallImageBackColor; - - crypto::checksum password; - SetupSalt passwordSalt; - - int64_t 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; - - stream::chunk::compression_method compressMethod; - - Architectures architecturesAllowed; - Architectures architecturesInstallIn64BitMode; - - uint32_t signedUninstallerOrigSize; - uint32_t signedUninstallerHdrChecksum; - - AutoBoolean disableDirPage; - AutoBoolean disableProgramGroupPage; - - size_t uninstallDisplaySize; - - Options options; - - void load(std::istream & is, const inno_version & version); - -}; - -FLAGS_OVERLOADS(SetupHeader::Options) -NAMED_ENUM(SetupHeader::Options) - -FLAGS_OVERLOADS(SetupHeader::Architectures) -NAMED_ENUM(SetupHeader::Architectures) - -NAMED_ENUM(SetupHeader::InstallMode) - -NAMED_ENUM(SetupHeader::UninstallLogMode) - -NAMED_ENUM(SetupHeader::UninstallStyle) - -NAMED_ENUM(SetupHeader::AutoBoolean) - -NAMED_ENUM(SetupHeader::Privileges) - -NAMED_ENUM(SetupHeader::LanguageDetection) - -#endif // INNOEXTRACT_SETUP_SETUPHEADER_HPP diff --git a/src/setup/SetupItem.hpp b/src/setup/SetupItem.hpp deleted file mode 100644 index 8348424..0000000 --- a/src/setup/SetupItem.hpp +++ /dev/null @@ -1,32 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_SETUPCONDITION_HPP -#define INNOEXTRACT_SETUP_SETUPCONDITION_HPP - -#include -#include - -#include "setup/version.hpp" -#include "setup/WindowsVersion.hpp" - -struct SetupItem { - - std::string components; - std::string tasks; - std::string languages; - std::string check; - - std::string afterInstall; - std::string beforeInstall; - - WindowsVersion minVersion; - WindowsVersion onlyBelowVersion; - -protected: - - void load_condition_data(std::istream & is, const inno_version & version); - - void load_version_data(std::istream & is, const inno_version & version); - -}; - -#endif // INNOEXTRACT_SETUP_SETUPCONDITION_HPP diff --git a/src/setup/SetupTaskEntry.hpp b/src/setup/SetupTaskEntry.hpp deleted file mode 100644 index 3a679fd..0000000 --- a/src/setup/SetupTaskEntry.hpp +++ /dev/null @@ -1,47 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_SETUPTASKENTRY_HPP -#define INNOEXTRACT_SETUP_SETUPTASKENTRY_HPP - -#include -#include - -#include "setup/version.hpp" -#include "setup/WindowsVersion.hpp" -#include "util/enum.hpp" -#include "util/flags.hpp" - -struct SetupTaskEntry { - - // introduced in 2.0.0 - - FLAGS(Options, - Exclusive, - Unchecked, - Restart, - CheckedOnce, - DontInheritCheck - ); - - std::string name; - std::string description; - std::string groupDescription; - std::string components; - std::string languages; - std::string check; - - int level; - bool used; - - WindowsVersion minVersion; - WindowsVersion onlyBelowVersion; - - Options options; - - void load(std::istream & is, const inno_version & version); - -}; - -FLAGS_OVERLOADS(SetupTaskEntry::Options) -NAMED_ENUM(SetupTaskEntry::Options) - -#endif // INNOEXTRACT_SETUP_SETUPTASKENTRY_HPP diff --git a/src/setup/SetupTypeEntry.cpp b/src/setup/SetupTypeEntry.cpp deleted file mode 100644 index 7ad35d0..0000000 --- a/src/setup/SetupTypeEntry.cpp +++ /dev/null @@ -1,60 +0,0 @@ - -#include "setup/SetupTypeEntry.hpp" - -#include "util/load.hpp" -#include "util/storedenum.hpp" - -namespace { - -STORED_FLAGS_MAP(StoredSetupTypeOptions, - SetupTypeEntry::CustomSetupType, -); - -STORED_ENUM_MAP(StoredSetupType, SetupTypeEntry::User, - SetupTypeEntry::User, - SetupTypeEntry::DefaultFull, - SetupTypeEntry::DefaultCompact, - SetupTypeEntry::DefaultCustom, -); - -} // anonymous namespace - -void SetupTypeEntry::load(std::istream & is, const inno_version & version) { - - is >> encoded_string(name, version.codepage()); - is >> encoded_string(description, version.codepage()); - if(version >= INNO_VERSION(4, 0, 1)) { - is >> encoded_string(languages, version.codepage()); - } else { - languages.clear(); - } - if(version >= INNO_VERSION(3, 0, 8)) { - is >> encoded_string(check, version.codepage()); - } else { - check.clear(); - } - - minVersion.load(is, version); - onlyBelowVersion.load(is, version); - - options = stored_flags(is).get(); - - if(version >= INNO_VERSION(4, 0, 3)) { - type = stored_enum(is).get(); - } else { - type = User; - } - - size = (version >= INNO_VERSION(4, 0, 0)) ? load_number(is) : load_number(is); -} - -ENUM_NAMES(SetupTypeEntry::Options, "Setyp Type Option", - "is custom", -) - -ENUM_NAMES(SetupTypeEntry::Type, "Setyp Type", - "user", - "default full", - "default compact", - "default custom", -) diff --git a/src/setup/SetupTypeEntry.hpp b/src/setup/SetupTypeEntry.hpp deleted file mode 100644 index 1ba8156..0000000 --- a/src/setup/SetupTypeEntry.hpp +++ /dev/null @@ -1,52 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_SETUPTYPEENTRY_HPP -#define INNOEXTRACT_SETUP_SETUPTYPEENTRY_HPP - -#include -#include -#include - -#include "setup/version.hpp" -#include "setup/WindowsVersion.hpp" -#include "util/enum.hpp" -#include "util/flags.hpp" - -struct SetupTypeEntry { - - // introduced in 2.0.0 - - FLAGS(Options, - CustomSetupType - ); - - enum Type { - User, - DefaultFull, - DefaultCompact, - DefaultCustom - }; - - std::string name; - std::string description; - std::string languages; - std::string check; - - WindowsVersion minVersion; - WindowsVersion onlyBelowVersion; - - Options options; - - Type type; - - uint64_t size; - - void load(std::istream & is, const inno_version & version); - -}; - -FLAGS_OVERLOADS(SetupTypeEntry::Options) -NAMED_ENUM(SetupTypeEntry::Options) - -NAMED_ENUM(SetupTypeEntry::Type) - -#endif // INNOEXTRACT_SETUP_SETUPTYPEENTRY_HPP diff --git a/src/setup/WindowsVersion.cpp b/src/setup/WindowsVersion.cpp deleted file mode 100644 index 9b5e8d9..0000000 --- a/src/setup/WindowsVersion.cpp +++ /dev/null @@ -1,128 +0,0 @@ - -#include "setup/WindowsVersion.hpp" - -#include - -#include "util/load.hpp" -#include "util/util.hpp" - -const WindowsVersion WindowsVersion::none = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0 } }; - -void WindowsVersion::Version::load(std::istream& is, const inno_version& version) { - - if(version >= INNO_VERSION(1, 3, 21)) { - build = load_number(is); - } else { - build = 0; - } - - minor = load_number(is); - major = load_number(is); - -} - -void WindowsVersion::load(std::istream & is, const inno_version & version) { - - winVersion.load(is, version); - ntVersion.load(is, version); - - if(version >= INNO_VERSION(1, 3, 21)) { - ntServicePack.minor = load_number(is); - ntServicePack.major = load_number(is); - } else { - ntServicePack.major = 0, ntServicePack.minor = 0; - } - -} - -namespace { - -struct WindowsVersionName { - - const char * name; - - WindowsVersion::Version version; - -}; - -WindowsVersionName windowsVersionNames[] = { - { "Windows 1.0", { 1, 4, 0 } }, - { "Windows 2.0", { 2, 11, 0 } }, - { "Windows 3.0", { 3, 0, 0 } }, - { "Windows for Workgroups 3.11", { 3, 11, 0 } }, - { "Windows 95", { 4, 0, 950 } }, - { "Windows 98", { 4, 1, 1998 } }, - { "Windows 98 Second Edition", { 4, 1, 2222 } }, - { "Windows ME", { 4, 90, 3000 } }, -}; - -WindowsVersionName windowsNtVersionNames[] = { - { "Windows NT Workstation 3.5", { 3, 5, 807 } }, - { "Windows NT 3.1", { 3, 10, 528 } }, - { "Windows NT Workstation 3.51", { 3, 51, 1057 } }, - { "Windows NT Workstation 4.0", { 4, 0, 1381 } }, - { "Windows 2000", { 5, 0, 2195 } }, - { "Windows XP", { 5, 1, 2600 } }, - { "Windows XP x64", { 5, 2, 3790 } }, - { "Windows Vista", { 6, 0, 6000 } }, - { "Windows 7", { 6, 1, 7600 } } -}; - -const char * getVersionName(const WindowsVersion::Version & version, bool nt = false) { - - WindowsVersionName * names; - size_t count; - if(nt) { - names = windowsNtVersionNames, count = ARRAY_SIZE(windowsNtVersionNames); - } else { - names = windowsVersionNames, count = ARRAY_SIZE(windowsVersionNames); - } - - for(size_t i = 0; i < count; i++) { - const WindowsVersionName & v = names[i]; - if(v.version.major != version.major || v.version.minor < version.minor) { - continue; - } - return v.name; - }; - return NULL; -} - -} - -std::ostream & operator<<(std::ostream & os, const WindowsVersion::Version & v) { - os << v.major << '.' << v.minor; - if(v.build) { - os << v.build; - } - return os; -} - -std::ostream & operator<<(std::ostream & os, const WindowsVersion & v) { - os << v.winVersion; - if(v.ntVersion != v.winVersion) { - os << " nt " << v.ntVersion; - } - const char * winName = getVersionName(v.winVersion); - const char * ntName = getVersionName(v.ntVersion, true); - if(winName || ntName) { - os << " ("; - if(winName) { - os << winName; - } - if(ntName && ntName != winName) { - if(winName) { - os << " / "; - } - os << ntName; - } - os << ')'; - } - if(v.ntServicePack.major || v.ntServicePack.minor) { - os << " service pack " << v.ntServicePack.major; - if(v.ntServicePack.minor) { - os << '.' << v.ntServicePack.minor; - } - } - return os; -} diff --git a/src/setup/WindowsVersion.hpp b/src/setup/WindowsVersion.hpp deleted file mode 100644 index af8e1ad..0000000 --- a/src/setup/WindowsVersion.hpp +++ /dev/null @@ -1,67 +0,0 @@ - -#ifndef INNOEXTRACT_SETUP_WINDOWSVERSION_HPP -#define INNOEXTRACT_SETUP_WINDOWSVERSION_HPP - -#include -#include "setup/version.hpp" - -struct WindowsVersion { - - struct Version { - - unsigned major; - unsigned minor; - unsigned build; - - inline bool operator==(const Version & o) const { - return (build == o.build && major == o.major && minor == o.minor); - } - - inline bool operator!=(const Version & o) const { - return !(*this == o); - } - - void load(std::istream & is, const inno_version & version); - - }; - - Version winVersion; - Version ntVersion; - - struct ServicePack { - - unsigned major; - unsigned minor; - - inline bool operator==(const ServicePack & o) const { - return (major == o.major && minor == o.minor); - } - - inline bool operator!=(const ServicePack & o) const { - return !(*this == o); - } - - }; - - ServicePack ntServicePack; - - void load(std::istream & is, const inno_version & version); - - inline bool operator==(const WindowsVersion & o) const { - return (winVersion == o.winVersion - && ntServicePack == o.ntServicePack - && ntServicePack == o.ntServicePack); - } - - inline bool operator!=(const WindowsVersion & o) const { - return !(*this == o); - } - - static const WindowsVersion none; - -}; - -std::ostream & operator<<(std::ostream & os, const WindowsVersion::Version & svd); -std::ostream & operator<<(std::ostream & os, const WindowsVersion & svd); - -#endif // INNOEXTRACT_SETUP_WINDOWSVERSION_HPP diff --git a/src/setup/component.cpp b/src/setup/component.cpp new file mode 100644 index 0000000..d4ad255 --- /dev/null +++ b/src/setup/component.cpp @@ -0,0 +1,87 @@ + +#include "setup/component.hpp" + +#include "setup/version.hpp" +#include "util/load.hpp" +#include "util/storedenum.hpp" + +namespace setup { + +namespace { + +STORED_FLAGS_MAP(stored_component_flags_0, + component_entry::Fixed, + component_entry::Restart, + component_entry::DisableNoUninstallWarning, +); + +// starting with version 3.0.8 +STORED_FLAGS_MAP(stored_component_flags_1, + component_entry::Fixed, + component_entry::Restart, + component_entry::DisableNoUninstallWarning, + component_entry::Exclusive, +); + +// starting with version 4.2.3 +STORED_FLAGS_MAP(stored_component_flags_2, + component_entry::Fixed, + component_entry::Restart, + component_entry::DisableNoUninstallWarning, + component_entry::Exclusive, + component_entry::DontInheritCheck, +); + +} // anonymous namespace + +void component_entry::load(std::istream & is, const version & version) { + + is >> encoded_string(name, version.codepage()); + is >> encoded_string(description, version.codepage()); + is >> encoded_string(types, version.codepage()); + if(version >= INNO_VERSION(4, 0, 1)) { + is >> encoded_string(languages, version.codepage()); + } else { + languages.clear(); + } + if(version >= INNO_VERSION(3, 0, 8)) { + is >> encoded_string(check, version.codepage()); + } else { + check.clear(); + } + + if(version >= INNO_VERSION(4, 0, 0)) { + extra_disk_pace_required = load_number(is); + } else { + extra_disk_pace_required = load_number(is); + } + + if(version >= INNO_VERSION(3, 0, 8)) { + level = load_number(is); + used = load_number(is); + } else { + level = 0, used = true; + } + + winver.load(is, version); + + if(version >= INNO_VERSION(4, 2, 3)) { + options = stored_flags(is).get(); + } else if(version >= INNO_VERSION(3, 0, 8)) { + options = stored_flags(is).get(); + } else { + options = stored_flags(is).get(); + } + + size = (version >= INNO_VERSION(4, 0, 0)) ? load_number(is) : load_number(is); +} + +} // namespace setup + +NAMES(setup::component_entry::flags, "Setup Component Option", + "fixed", + "restart", + "disable no uninstall warning", + "exclusive", + "don't inherit check", +) diff --git a/src/setup/component.hpp b/src/setup/component.hpp new file mode 100644 index 0000000..2240a9e --- /dev/null +++ b/src/setup/component.hpp @@ -0,0 +1,54 @@ + +#ifndef INNOEXTRACT_SETUP_COMPONENT_HPP +#define INNOEXTRACT_SETUP_COMPONENT_HPP + +#include +#include +#include + +#include "setup/windows.hpp" +#include "util/enum.hpp" +#include "util/flags.hpp" + +namespace setup { + +struct version; + +struct component_entry { + + // introduced in 2.0.0 + + FLAGS(flags, + Fixed, + Restart, + DisableNoUninstallWarning, + Exclusive, + DontInheritCheck + ); + + std::string name; + std::string description; + std::string types; + std::string languages; + std::string check; + + uint64_t extra_disk_pace_required; + + int level; + bool used; + + windows_version_range winver; + + flags options; + + uint64_t size; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +NAMED_FLAGS(setup::component_entry::flags) + +#endif // INNOEXTRACT_SETUP_COMPONENT_HPP diff --git a/src/setup/data.cpp b/src/setup/data.cpp index e2aaccf..a8388bd 100644 --- a/src/setup/data.cpp +++ b/src/setup/data.cpp @@ -1,49 +1,50 @@ #include "setup/data.hpp" +#include "setup/version.hpp" #include "util/load.hpp" #include "util/log.hpp" #include "util/storedenum.hpp" namespace setup { -void data_entry::load(std::istream & is, const inno_version & version) { +void data_entry::load(std::istream & is, const version & version) { - first_slice = load_number(is, version.bits); - last_slice = load_number(is, version.bits); + chunk.first_slice = load_number(is, version.bits); + chunk.last_slice = load_number(is, version.bits); if(version < INNO_VERSION(4, 0, 0)) { - if(first_slice < 1 || last_slice < 1) { - log_warning << "[file location] unexpected disk number: " << first_slice << " / " - << last_slice; + if(chunk.first_slice < 1 || chunk.last_slice < 1) { + log_warning << "[file location] unexpected disk number: " << chunk.first_slice << " / " + << chunk.last_slice; } else { - first_slice--, last_slice--; + chunk.first_slice--, chunk.last_slice--; } } - chunk_offset = load_number(is); + chunk.offset = load_number(is); if(version >= INNO_VERSION(4, 0, 1)) { - file_offset = load_number(is); + file.offset = load_number(is); } else { - file_offset = 0; + file.offset = 0; } if(version >= INNO_VERSION(4, 0, 0)) { - file_size = load_number(is); - chunk_size = load_number(is); + file.size = load_number(is); + chunk.size = load_number(is); } else { - file_size = load_number(is); - chunk_size = load_number(is); + file.size = load_number(is); + chunk.size = load_number(is); } if(version >= INNO_VERSION(5, 3, 9)) { - is.read(checksum.sha1, sizeof(checksum.sha1)), checksum.type = crypto::SHA1; + is.read(file.checksum.sha1, sizeof(file.checksum.sha1)), file.checksum.type = crypto::SHA1; } else if(version >= INNO_VERSION(4, 2, 0)) { - is.read(checksum.md5, sizeof(checksum.md5)), checksum.type = crypto::MD5; + is.read(file.checksum.md5, sizeof(file.checksum.md5)), file.checksum.type = crypto::MD5; } else if(version >= INNO_VERSION(4, 0, 1)) { - checksum.crc32 = load_number(is), checksum.type = crypto::CRC32; + file.checksum.crc32 = load_number(is), file.checksum.type = crypto::CRC32; } else { - checksum.adler32 = load_number(is), checksum.type = crypto::Adler32; + file.checksum.adler32 = load_number(is), file.checksum.type = crypto::Adler32; } if(version.bits == 16) { @@ -108,14 +109,30 @@ void data_entry::load(std::istream & is, const inno_version & version) { options |= flags; + chunk.compression = (options & ChunkCompressed) ? stream::UnknownCompression : stream::Stored; if(options & BZipped) { options |= ChunkCompressed; + chunk.compression = stream::BZip2; + } + + chunk.encrypted = (options & ChunkEncrypted); + + if(options & CallInstructionOptimized) { + if(version < INNO_VERSION(5, 2, 0)) { + file.filter = stream::InstructionFilter4108; + } else if(version < INNO_VERSION(5, 3, 9)) { + file.filter = stream::InstructionFilter5200; + } else { + file.filter = stream::InstructionFilter5309; + } + } else { + file.filter = stream::NoFilter; } } -} // namespace setup +} // namespace setup; -ENUM_NAMES(setup::data_entry::flags, "File Location Option", +NAMES(setup::data_entry::flags, "File Location Option", "version info valid", "version info not valid", "timestamp in UTC", diff --git a/src/setup/data.hpp b/src/setup/data.hpp index b1e3b52..c62c937 100644 --- a/src/setup/data.hpp +++ b/src/setup/data.hpp @@ -8,14 +8,16 @@ #include #include "crypto/checksum.hpp" -#include "setup/SetupItem.hpp" -#include "setup/version.hpp" +#include "stream/chunk.hpp" +#include "stream/file.hpp" #include "util/enum.hpp" #include "util/flags.hpp" namespace setup { -struct data_entry : public SetupItem { +struct version; + +struct data_entry { FLAGS(flags, @@ -33,16 +35,9 @@ struct data_entry : public SetupItem { BZipped ); - size_t first_slice; - size_t last_slice; - - uint32_t chunk_offset; //!< offset of the compressed chunk in firstSlice - uint64_t chunk_size; //! total compressed size of the chunk - - uint64_t file_offset; //!< offset of this file within the decompressed chunk - uint64_t file_size; //!< decompressed size of this file + stream::chunk chunk; - crypto::checksum checksum; + stream::file file; timespec timestamp; @@ -51,13 +46,12 @@ struct data_entry : public SetupItem { flags options; - void load(std::istream & is, const inno_version & version); + void load(std::istream & is, const version & version); }; } // namespace setup -FLAGS_OVERLOADS(setup::data_entry::flags) -NAMED_ENUM(setup::data_entry::flags) +NAMED_FLAGS(setup::data_entry::flags) #endif // INNOEXTRACT_SETUP_DATA_HPP diff --git a/src/setup/delete.cpp b/src/setup/delete.cpp index adc6f42..96cf778 100644 --- a/src/setup/delete.cpp +++ b/src/setup/delete.cpp @@ -1,6 +1,7 @@ #include "setup/delete.hpp" +#include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -16,7 +17,7 @@ STORED_ENUM_MAP(delete_target_type_map, delete_entry::Files, } // anonymous namespace -void delete_entry::load(std::istream & is, const inno_version & version) { +void delete_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { ::load(is); // uncompressed size of the directory entry structure @@ -33,7 +34,7 @@ void delete_entry::load(std::istream & is, const inno_version & version) { } // namespace setup -ENUM_NAMES(setup::delete_entry::target_type, "Delete Type", +NAMES(setup::delete_entry::target_type, "Delete Type", "files", "files and subdirs", "dir if empty", diff --git a/src/setup/delete.hpp b/src/setup/delete.hpp index 94e11ea..362f25c 100644 --- a/src/setup/delete.hpp +++ b/src/setup/delete.hpp @@ -5,13 +5,14 @@ #include #include -#include "setup/SetupItem.hpp" -#include "setup/version.hpp" +#include "setup/item.hpp" #include "util/enum.hpp" namespace setup { -struct delete_entry : public SetupItem { +struct version; + +struct delete_entry : public item { enum target_type { Files, @@ -23,7 +24,7 @@ struct delete_entry : public SetupItem { target_type type; - void load(std::istream & is, const inno_version & version); + void load(std::istream & is, const version & version); }; diff --git a/src/setup/directory.cpp b/src/setup/directory.cpp index 435e5f5..9e06dd3 100644 --- a/src/setup/directory.cpp +++ b/src/setup/directory.cpp @@ -1,6 +1,7 @@ #include "setup/directory.hpp" +#include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" @@ -25,7 +26,7 @@ STORED_FLAGS_MAP(stored_inno_directory_options_1, } // anonymous namespace -void directory_entry::load(std::istream & is, const inno_version & version) { +void directory_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { ::load(is); // uncompressed size of the directory entry structure @@ -65,7 +66,7 @@ void directory_entry::load(std::istream & is, const inno_version & version) { } // namespace setup -ENUM_NAMES(setup::directory_entry::flags, "Directory Option", +NAMES(setup::directory_entry::flags, "Directory Option", "never uninstall", "delete after install", "always uninstall", diff --git a/src/setup/directory.hpp b/src/setup/directory.hpp index 1adf80c..ab52a10 100644 --- a/src/setup/directory.hpp +++ b/src/setup/directory.hpp @@ -6,14 +6,15 @@ #include #include -#include "setup/SetupItem.hpp" -#include "setup/version.hpp" +#include "setup/item.hpp" #include "util/enum.hpp" #include "util/flags.hpp" namespace setup { -struct directory_entry : public SetupItem { +struct version; + +struct directory_entry : public item { FLAGS(flags, NeverUninstall, @@ -32,13 +33,12 @@ struct directory_entry : public SetupItem { flags options; - void load(std::istream & is, const inno_version & version); + void load(std::istream & is, const version & version); }; } // namespace setup -FLAGS_OVERLOADS(setup::directory_entry::flags) -NAMED_ENUM(setup::directory_entry::flags) +NAMED_FLAGS(setup::directory_entry::flags) #endif // INNOEXTRACT_SETUP_DIRECTORY_HPP diff --git a/src/setup/file.cpp b/src/setup/file.cpp index 5911b24..280b475 100644 --- a/src/setup/file.cpp +++ b/src/setup/file.cpp @@ -1,6 +1,7 @@ #include "setup/file.hpp" +#include "setup/version.hpp" #include "util/load.hpp" #include "util/log.hpp" #include "util/storedenum.hpp" @@ -41,7 +42,7 @@ STORED_ENUM_MAP(stored_file_type_1, file_entry::UserFile, NAMED_ENUM(setup::file_copy_mode) -ENUM_NAMES(setup::file_copy_mode, "File Copy Mode", +NAMES(setup::file_copy_mode, "File Copy Mode", "normal", "if doesn't exist", "always overwrite", @@ -50,7 +51,7 @@ ENUM_NAMES(setup::file_copy_mode, "File Copy Mode", namespace setup { -void file_entry::load(std::istream & is, const inno_version & version) { +void file_entry::load(std::istream & is, const version & version) { (void)enum_names::names; @@ -183,7 +184,7 @@ void file_entry::load(std::istream & is, const inno_version & version) { } // namespace setup -ENUM_NAMES(setup::file_entry::flags, "File Option", +NAMES(setup::file_entry::flags, "File Option", "confirm overwrite", "never uninstall", "restart replace", @@ -219,7 +220,7 @@ ENUM_NAMES(setup::file_entry::flags, "File Option", "readme", ) -ENUM_NAMES(setup::file_entry::file_type, "File Entry Type", +NAMES(setup::file_entry::file_type, "File Entry Type", "user file", "uninstaller exe", "reg server exe", diff --git a/src/setup/file.hpp b/src/setup/file.hpp index e254427..0f710a4 100644 --- a/src/setup/file.hpp +++ b/src/setup/file.hpp @@ -6,14 +6,15 @@ #include #include -#include "setup/SetupItem.hpp" -#include "setup/version.hpp" +#include "setup/item.hpp" #include "util/enum.hpp" #include "util/flags.hpp" namespace setup { -struct file_entry : public SetupItem { +struct version; + +struct file_entry : public item { FLAGS(flags, @@ -75,15 +76,13 @@ struct file_entry : public SetupItem { file_type type; - void load(std::istream & is, const inno_version & version); + void load(std::istream & is, const version & version); }; } // namespace setup -FLAGS_OVERLOADS(setup::file_entry::flags) -NAMED_ENUM(setup::file_entry::flags) - +NAMED_FLAGS(setup::file_entry::flags) NAMED_ENUM(setup::file_entry::file_type) #endif // INNOEXTRACT_SETUP_FILE_HPP diff --git a/src/setup/header.cpp b/src/setup/header.cpp new file mode 100644 index 0000000..3aa4dab --- /dev/null +++ b/src/setup/header.cpp @@ -0,0 +1,655 @@ + +#include "setup/header.hpp" + +#include +#include + +#include + +#include "setup/version.hpp" +#include "util/load.hpp" +#include "util/storedenum.hpp" + +namespace setup { + +namespace { + +STORED_ENUM_MAP(stored_install_verbosity, header::NormalInstallMode, + header::NormalInstallMode, + header::SilentInstallMode, + header::VerySilentInstallMode +); + +STORED_ENUM_MAP(stored_log_mode, header::AppendLog, + header::AppendLog, + header::NewLog, + header::OverwriteLog +); + +STORED_ENUM_MAP(stored_setup_style, header::ClassicStyle, + header::ClassicStyle, + header::ModernStyle +); + +STORED_ENUM_MAP(stored_bool_auto_no_yes, header::Auto, + header::Auto, + header::No, + header::Yes +); + +// pre- 5.3.7 +STORED_ENUM_MAP(stored_privileges_0, header::NoPrivileges, + header::NoPrivileges, + header::PowerUserPrivileges, + header::AdminPriviliges, +); + +// post- 5.3.7 +STORED_ENUM_MAP(stored_privileges_1, header::NoPrivileges, + header::NoPrivileges, + header::PowerUserPrivileges, + header::AdminPriviliges, + header::LowestPrivileges +); + +STORED_ENUM_MAP(stored_bool_yes_no_auto, header::Yes, + header::Yes, + header::No, + header::Auto +); + +STORED_ENUM_MAP(stored_language_detection_method, header::UILanguage, + header::UILanguage, + header::LocaleLanguage, + header::NoLanguageDetection +); + +STORED_FLAGS_MAP(stored_architectures, + header::ArchitectureUnknown, + header::X86, + header::Amd64, + header::IA64 +); + +// pre-4.2.5 +STORED_ENUM_MAP(stored_compression_method_0, stream::UnknownCompression, + stream::Zlib, + stream::BZip2, + stream::LZMA1 +); + +// 4.2.5 +STORED_ENUM_MAP(stored_compression_method_1, stream::UnknownCompression, + stream::Stored, + stream::BZip2, + stream::LZMA1 +); + +// [4.2.6 5.3.9) +STORED_ENUM_MAP(stored_compression_method_2, stream::UnknownCompression, + stream::Stored, + stream::Zlib, + stream::BZip2, + stream::LZMA1 +); + +// 5.3.9+ +STORED_ENUM_MAP(stored_compression_method_3, stream::UnknownCompression, + stream::Stored, + stream::Zlib, + stream::BZip2, + stream::LZMA1, + stream::LZMA2 +); + +} // anonymous namespace + +void header::load(std::istream & is, const version & version) { + + options = 0; + + if(version < INNO_VERSION(1, 3, 21)) { + ::load(is); // uncompressed size of the setup header structure + } + + is >> encoded_string(app_name, version.codepage()); + is >> encoded_string(app_versioned_name, version.codepage()); + if(version >= INNO_VERSION(1, 3, 21)) { + is >> encoded_string(app_id, version.codepage()); + } + is >> encoded_string(app_copyright, version.codepage()); + if(version >= INNO_VERSION(1, 3, 21)) { + is >> encoded_string(app_publisher, version.codepage()); + is >> encoded_string(app_publisher_url, version.codepage()); + } else { + app_publisher.clear(), app_publisher_url.clear(); + } + if(version >= INNO_VERSION(5, 1, 13)) { + is >> encoded_string(app_support_phone, version.codepage()); + } else { + app_support_phone.clear(); + } + if(version >= INNO_VERSION(1, 3, 21)) { + is >> encoded_string(app_support_url, version.codepage()); + is >> encoded_string(app_updates_url, version.codepage()); + is >> encoded_string(app_version, version.codepage()); + } else { + app_support_url.clear(), app_updates_url.clear(), app_version.clear(); + } + is >> encoded_string(default_dir_name, version.codepage()); + is >> encoded_string(default_group_name, version.codepage()); + if(version < INNO_VERSION(3, 0, 0)) { + is >> ansi_string(uninstall_icon_name); + } else { + uninstall_icon_name.clear(); + } + is >> encoded_string(base_filename, version.codepage()); + if(version >= INNO_VERSION(1, 3, 21)) { + if(version < INNO_VERSION(5, 2, 5)) { + is >> ansi_string(license_text); + is >> ansi_string(info_before); + is >> ansi_string(info_after); + } + is >> encoded_string(uninstall_files_dir, version.codepage()); + is >> encoded_string(uninstall_name, version.codepage()); + is >> encoded_string(uninstall_icon, version.codepage()); + is >> encoded_string(app_mutex, version.codepage()); + } else { + license_text.clear(), info_before.clear(), info_after.clear(); + uninstall_files_dir.clear(), uninstall_name.clear(); + uninstall_icon.clear(), app_mutex.clear(); + } + if(version >= INNO_VERSION(3, 0, 0)) { + is >> encoded_string(default_user_name, version.codepage()); + is >> encoded_string(default_user_organisation, version.codepage()); + } else { + default_user_name.clear(), default_user_organisation.clear(); + } + if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + is >> encoded_string(default_serial, version.codepage()); + if(version < INNO_VERSION(5, 2, 5)) { + is >> binary_string(compiled_code); + } + } else { + default_serial.clear(), compiled_code.clear(); + } + if(version >= INNO_VERSION(4, 2, 4)) { + is >> encoded_string(app_readme_file, version.codepage()); + is >> encoded_string(app_contact, version.codepage()); + is >> encoded_string(app_comments, version.codepage()); + is >> encoded_string(app_modify_path, version.codepage()); + } else { + app_readme_file.clear(), app_contact.clear(); + app_comments.clear(), app_modify_path.clear(); + } + if(version >= INNO_VERSION(5, 3, 8)) { + is >> encoded_string(create_uninstall_registry_key, version.codepage()); + } else { + create_uninstall_registry_key.clear(); + } + if(version >= INNO_VERSION(5, 3, 10)) { + is >> encoded_string(uninstallable, version.codepage()); + } else { + uninstallable.clear(); + } + if(version >= INNO_VERSION(5, 2, 5)) { + is >> ansi_string(license_text); + is >> ansi_string(info_before); + is >> ansi_string(info_after); + } + if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) { + is >> binary_string(uninstaller_signature); + } else { + uninstaller_signature.clear(); + } + if(version >= INNO_VERSION(5, 2, 5)) { + is >> binary_string(compiled_code); + } + + if(version >= INNO_VERSION(2, 0, 6) && !version.unicode) { + lead_bytes = stored_char_set(is); + } else { + lead_bytes = 0; + } + + if(version >= INNO_VERSION(4, 0, 0)) { + language_count = load_number(is); + } else if(version >= INNO_VERSION(2, 0, 1)) { + language_count = 1; + } else { + language_count = 0; + } + + if(version >= INNO_VERSION(4, 2, 1)) { + message_count = load_number(is); + } else { + message_count = 0; + } + + if(version >= INNO_VERSION(4, 1, 0)) { + permission_count = load_number(is); + } else { + permission_count = 0; + } + + if(version >= INNO_VERSION(2, 0, 0)) { + type_count = load_number(is); + component_count = load_number(is); + task_count = load_number(is); + } else { + type_count = 0, component_count = 0, task_count = 0; + } + + directory_count = load_number(is, version.bits); + file_count = load_number(is, version.bits); + data_entry_count = load_number(is, version.bits); + icon_count = load_number(is, version.bits); + ini_entry_count = load_number(is, version.bits); + registry_entry_count = load_number(is, version.bits); + delete_entry_count = load_number(is, version.bits); + uninstall_delete_entry_count = load_number(is, version.bits); + run_entry_count = load_number(is, version.bits); + uninstall_run_entry_count = load_number(is, version.bits); + + int32_t license_size; + int32_t info_before_size; + int32_t info_after_size; + if(version < INNO_VERSION(1, 3, 21)) { + license_size = load_number(is, version.bits); + info_before_size = load_number(is, version.bits); + info_after_size = load_number(is, version.bits); + } + + winver.load(is, version); + + back_color = load_number(is); + if(version >= INNO_VERSION(1, 3, 21)) { + back_color2 = load_number(is); + } else { + back_color2 = 0; + } + image_back_color = load_number(is); + if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) { + small_image_back_color = load_number(is); + } else { + small_image_back_color = 0; + } + + if(version < INNO_VERSION(4, 2, 0)) { + password.crc32 = load_number(is), password.type = crypto::CRC32; + } else if(version < INNO_VERSION(5, 3, 9)) { + is.read(password.md5, sizeof(password.md5)), password.type = crypto::MD5; + } else { + is.read(password.sha1, sizeof(password.sha1)), password.type = crypto::SHA1; + } + if(version >= INNO_VERSION(4, 2, 2)) { + is.read(password_salt, sizeof(password_salt)); + } else { + memset(password_salt, 0, sizeof(password_salt)); + } + + if(version < INNO_VERSION(4, 0, 0)) { + extra_disk_space_required = load_number(is); + slices_per_disk = 1; + } else { + extra_disk_space_required = load_number(is); + slices_per_disk = load_number(is); + } + + if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) { + install_mode = stored_enum(is).get(); + } else { + install_mode = NormalInstallMode; + } + + if(version >= INNO_VERSION(1, 3, 21)) { + uninstall_log_mode = stored_enum(is).get(); + } else { + uninstall_log_mode = AppendLog; + } + + if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) { + uninstall_style = stored_enum(is).get(); + } else { + uninstall_style = (version < INNO_VERSION(5, 0, 0)) ? ClassicStyle : ModernStyle; + } + + if(version >= INNO_VERSION(1, 3, 21)) { + dir_exists_warning = stored_enum(is).get(); + } else { + dir_exists_warning = Auto; + } + + if(version >= INNO_VERSION(3, 0, 0) && version < INNO_VERSION(3, 0, 3)) { + auto_bool val = stored_enum(is).get(); + switch(val) { + case Yes: options |= AlwaysRestart; break; + case Auto: options |= RestartIfNeededByRun; break; + case No: break; + } + } + + if(version >= INNO_VERSION(5, 3, 7)) { + privileges_required = stored_enum(is).get(); + } else if(version >= INNO_VERSION(3, 0, 4)) { + privileges_required = stored_enum(is).get(); + } + + if(version >= INNO_VERSION(4, 0, 10)) { + show_language_dialog = stored_enum(is).get(); + language_detection = stored_enum(is).get(); + } + + if(version >= INNO_VERSION(5, 3, 9)) { + compression = stored_enum(is).get(); + } else if(version >= INNO_VERSION(4, 2, 6)) { + compression = stored_enum(is).get(); + } else if(version >= INNO_VERSION(4, 2, 5)) { + compression = stored_enum(is).get(); + } else if(version >= INNO_VERSION(4, 1, 5)) { + compression = stored_enum(is).get(); + } + + if(version >= INNO_VERSION(5, 1, 0)) { + architectures_allowed = stored_flags(is).get(); + architectures_installed_in_64bit_mode = stored_flags(is).get(); + } else { + architectures_allowed = architecture_types::all(); + architectures_installed_in_64bit_mode = architecture_types::all(); + } + + if(version >= INNO_VERSION(5, 2, 1) && version < INNO_VERSION(5, 3, 10)) { + signed_uninstaller_original_size = load_number(is); + signed_uninstaller_header_checksum = load_number(is); + } else { + signed_uninstaller_original_size = signed_uninstaller_header_checksum = 0; + } + + if(version >= INNO_VERSION(5, 3, 3)) { + disable_dir_page = stored_enum(is).get(); + disable_program_group_page = stored_enum(is).get(); + } + + if(version >= INNO_VERSION(5, 3, 6)) { + uninstall_display_size = load_number(is); + } else { + uninstall_display_size = 0; + } + + + stored_flag_reader flags(is); + + flags.add(DisableStartupPrompt); + if(version < INNO_VERSION(5, 3, 10)) { + flags.add(Uninstallable); + } + flags.add(CreateAppDir); + if(version < INNO_VERSION(5, 3, 3)) { + flags.add(DisableDirPage); + } + if(version < INNO_VERSION(1, 3, 21)) { + flags.add(DisableDirExistsWarning); + } + if(version < INNO_VERSION(5, 3, 3)) { + flags.add(DisableProgramGroupPage); + } + flags.add(AllowNoIcons); + if(version < INNO_VERSION(3, 0, 0) || version >= INNO_VERSION(3, 0, 3)) { + flags.add(AlwaysRestart); + } + if(version < INNO_VERSION(1, 3, 21)) { + flags.add(BackSolid); + } + flags.add(AlwaysUsePersonalGroup); + flags.add(WindowVisible); + flags.add(WindowShowCaption); + flags.add(WindowResizable); + flags.add(WindowStartMaximized); + flags.add(EnableDirDoesntExistWarning); + if(version < INNO_VERSION(4, 1, 2)) { + flags.add(DisableAppendDir); + } + flags.add(Password); + flags.add(AllowRootDirectory); + flags.add(DisableFinishedPage); + if(version.bits != 16) { + if(version < INNO_VERSION(3, 0, 4)) { + flags.add(AdminPrivilegesRequired); + } + if(version < INNO_VERSION(3, 0, 0)) { + flags.add(AlwaysCreateUninstallIcon); + } + if(version < INNO_VERSION(1, 3, 21)) { + flags.add(OverwriteUninstRegEntries); + } + flags.add(ChangesAssociations); + } + if(version >= INNO_VERSION(1, 3, 21)) { + if(version < INNO_VERSION(5, 3, 8)) { + flags.add(CreateUninstallRegKey); + } + flags.add(UsePreviousAppDir); + flags.add(BackColorHorizontal); + flags.add(UsePreviousGroup); + flags.add(UpdateUninstallLogAppName); + } + if(version >= INNO_VERSION(2, 0, 0)) { + flags.add(UsePreviousSetupType); + flags.add(DisableReadyMemo); + flags.add(AlwaysShowComponentsList); + flags.add(FlatComponentsList); + flags.add(ShowComponentSizes); + flags.add(UsePreviousTasks); + flags.add(DisableReadyPage); + } + if(version >= INNO_VERSION(2, 0, 7)) { + flags.add(AlwaysShowDirOnReadyPage); + flags.add(AlwaysShowGroupOnReadyPage); + } + if(version >= INNO_VERSION(2, 0, 17) && version < INNO_VERSION(4, 1, 5)) { + flags.add(BzipUsed); + } + if(version >= INNO_VERSION(2, 0, 18)) { + flags.add(AllowUNCPath); + } + if(version >= INNO_VERSION(3, 0, 0)) { + flags.add(UserInfoPage); + flags.add(UsePreviousUserInfo); + } + if(version >= INNO_VERSION(3, 0, 1)) { + flags.add(UninstallRestartComputer); + } + if(version >= INNO_VERSION(3, 0, 3)) { + flags.add(RestartIfNeededByRun); + } + if(version >= INNO_VERSION_EXT(3, 0, 6, 1)) { + flags.add(ShowTasksTreeLines); + } + if(version >= INNO_VERSION(4, 0, 0) && version < INNO_VERSION(4, 0, 10)) { + flags.add(ShowLanguageDialog); + } + + if(version >= INNO_VERSION(4, 0, 1) && version < INNO_VERSION(4, 0, 10)) { + flags.add(DetectLanguageUsingLocale); + } + if(version >= INNO_VERSION(4, 0, 9)) { + flags.add(AllowCancelDuringInstall); + } else { + options |= AllowCancelDuringInstall; + } + if(version >= INNO_VERSION(4, 1, 3)) { + flags.add(WizardImageStretch); + } + if(version >= INNO_VERSION(4, 1, 8)) { + flags.add(AppendDefaultDirName); + flags.add(AppendDefaultGroupName); + } + if(version >= INNO_VERSION(4, 2, 2)) { + flags.add(EncryptionUsed); + } + if(version >= INNO_VERSION(5, 0, 4)) { + flags.add(ChangesEnvironment); + } + if(version >= INNO_VERSION(5, 1, 7) && !version.unicode) { + flags.add(ShowUndisplayableLanguages); + } + if(version >= INNO_VERSION(5, 1, 13)) { + flags.add(SetupLogging); + } + if(version >= INNO_VERSION(5, 2, 1)) { + flags.add(SignedUninstaller); + } + if(version >= INNO_VERSION(5, 3, 8)) { + flags.add(UsePreviousLanguage); + } + if(version >= INNO_VERSION(5, 3, 9)) { + flags.add(DisableWelcomePage); + } + + options |= flags; + + if(version < INNO_VERSION(3, 0, 4)) { + privileges_required = (options & AdminPrivilegesRequired) ? AdminPriviliges : NoPrivileges; + } + + if(version < INNO_VERSION(4, 0, 10)) { + show_language_dialog = (options & ShowLanguageDialog) ? Yes : No; + language_detection = (options & DetectLanguageUsingLocale) ? LocaleLanguage : UILanguage; + } + + if(version < INNO_VERSION(4, 1, 5)) { + compression = (options & BzipUsed) ? stream::BZip2 : stream::Zlib; + } + + if(version < INNO_VERSION(5, 3, 3)) { + disable_dir_page = (options & DisableDirPage) ? Yes : No; + disable_program_group_page = (options & DisableProgramGroupPage) ? Yes : No; + } + + if(version < INNO_VERSION(1, 3, 21)) { + if(license_size > 0) { + std::string temp; + temp.resize(size_t(license_size)); + is.read(&temp[0], license_size); + to_utf8(temp, license_text); + } + if(info_before_size > 0) { + std::string temp; + temp.resize(size_t(info_before_size)); + is.read(&temp[0], info_before_size); + to_utf8(temp, info_before); + } + if(info_after_size > 0) { + std::string temp; + temp.resize(size_t(info_after_size)); + is.read(&temp[0], info_after_size); + to_utf8(temp, info_after); + } + } + +} + +} // namespace setup + +NAMES(setup::header::flags, "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", +) + +NAMES(setup::header::architecture_types, "Architecture", + "unknown", + "x86", + "amd64", + "IA64", +) + +NAMES(setup::header::install_verbosity, "Install Mode", + "normal", + "silent", + "very silent", +) + +NAMES(setup::header::log_mode, "Uninstall Log Mode", + "append", + "new log", + "overwrite", +) + +NAMES(setup::header::style, "Uninstall Style", + "classic", + "modern", +) + +NAMES(setup::header::auto_bool, "Auto Boolean", + "auto", + "no", + "yes", +) + +NAMES(setup::header::privilege_level, "Privileges", + "none", + "power user", + "admin", + "lowest", +) + +NAMES(setup::header::language_detection_method, "Language Detection", + "ui language", + "locale", + "none", +) diff --git a/src/setup/header.hpp b/src/setup/header.hpp new file mode 100644 index 0000000..7c4b2da --- /dev/null +++ b/src/setup/header.hpp @@ -0,0 +1,238 @@ + +#ifndef INNOEXTRACT_SETUP_HEADER_HPP +#define INNOEXTRACT_SETUP_HEADER_HPP + +#include +#include +#include +#include +#include + +#include "crypto/checksum.hpp" +#include "setup/windows.hpp" +#include "stream/chunk.hpp" +#include "util/enum.hpp" +#include "util/flags.hpp" + +namespace setup { + +struct version; + +typedef char salt[8]; + +struct header { + + // Setup data header. + + FLAGS(flags, + + DisableStartupPrompt, + CreateAppDir, + AllowNoIcons, + AlwaysRestart, + AlwaysUsePersonalGroup, + WindowVisible, + WindowShowCaption, + WindowResizable, + WindowStartMaximized, + EnableDirDoesntExistWarning, + Password, + AllowRootDirectory, + DisableFinishedPage, + ChangesAssociations, + UsePreviousAppDir, + BackColorHorizontal, + UsePreviousGroup, + UpdateUninstallLogAppName, + UsePreviousSetupType, + DisableReadyMemo, + AlwaysShowComponentsList, + FlatComponentsList, + ShowComponentSizes, + UsePreviousTasks, + DisableReadyPage, + AlwaysShowDirOnReadyPage, + AlwaysShowGroupOnReadyPage, + AllowUNCPath, + UserInfoPage, + UsePreviousUserInfo, + UninstallRestartComputer, + RestartIfNeededByRun, + ShowTasksTreeLines, + AllowCancelDuringInstall, + WizardImageStretch, + AppendDefaultDirName, + AppendDefaultGroupName, + EncryptionUsed, + ChangesEnvironment, + ShowUndisplayableLanguages, + SetupLogging, + SignedUninstaller, + UsePreviousLanguage, + DisableWelcomePage, + + // Obsolete flags + Uninstallable, + DisableDirPage, + DisableProgramGroupPage, + DisableAppendDir, + AdminPrivilegesRequired, + AlwaysCreateUninstallIcon, + CreateUninstallRegKey, + BzipUsed, + ShowLanguageDialog, + DetectLanguageUsingLocale, + DisableDirExistsWarning, + BackSolid, + OverwriteUninstRegEntries + ); + + FLAGS(architecture_types, + ArchitectureUnknown, + X86, + Amd64, + IA64 + ); + + std::string app_name; + std::string app_versioned_name; + std::string app_id; + std::string app_copyright; + std::string app_publisher; + std::string app_publisher_url; + std::string app_support_phone; + std::string app_support_url; + std::string app_updates_url; + std::string app_version; + std::string default_dir_name; + std::string default_group_name; + std::string uninstall_icon_name; + std::string base_filename; + std::string uninstall_files_dir; + std::string uninstall_name; + std::string uninstall_icon; + std::string app_mutex; + std::string default_user_name; + std::string default_user_organisation; + std::string default_serial; + std::string app_readme_file; + std::string app_contact; + std::string app_comments; + std::string app_modify_path; + std::string create_uninstall_registry_key; + std::string uninstallable; + std::string license_text; + std::string info_before; + std::string info_after; + std::string uninstaller_signature; + std::string compiled_code; + + std::bitset<256> lead_bytes; + + size_t language_count; + size_t message_count; + size_t permission_count; + size_t type_count; + size_t component_count; + size_t task_count; + size_t directory_count; + size_t file_count; + size_t data_entry_count; + size_t icon_count; + size_t ini_entry_count; + size_t registry_entry_count; + size_t delete_entry_count; + size_t uninstall_delete_entry_count; + size_t run_entry_count; + size_t uninstall_run_entry_count; + + windows_version_range winver; + + typedef uint32_t Color; + Color back_color; + Color back_color2; + Color image_back_color; + Color small_image_back_color; + + crypto::checksum password; + salt password_salt; + + int64_t extra_disk_space_required; + size_t slices_per_disk; + + enum install_verbosity { + NormalInstallMode, + SilentInstallMode, + VerySilentInstallMode, + }; + install_verbosity install_mode; + + enum log_mode { + AppendLog, + NewLog, + OverwriteLog + }; + log_mode uninstall_log_mode; + + enum style { + ClassicStyle, + ModernStyle + }; + style uninstall_style; + + enum auto_bool { + Auto, + No, + Yes + }; + + auto_bool dir_exists_warning; + + enum privilege_level { + NoPrivileges, + PowerUserPrivileges, + AdminPriviliges, + LowestPrivileges + }; + privilege_level privileges_required; + + auto_bool show_language_dialog; + + enum language_detection_method { + UILanguage, + LocaleLanguage, + NoLanguageDetection + }; + language_detection_method language_detection; + + stream::compression_method compression; + + architecture_types architectures_allowed; + architecture_types architectures_installed_in_64bit_mode; + + uint32_t signed_uninstaller_original_size; + uint32_t signed_uninstaller_header_checksum; + + auto_bool disable_dir_page; + auto_bool disable_program_group_page; + + size_t uninstall_display_size; + + flags options; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +NAMED_FLAGS(setup::header::flags) +NAMED_FLAGS(setup::header::architecture_types) +NAMED_ENUM(setup::header::install_verbosity) +NAMED_ENUM(setup::header::log_mode) +NAMED_ENUM(setup::header::style) +NAMED_ENUM(setup::header::auto_bool) +NAMED_ENUM(setup::header::privilege_level) +NAMED_ENUM(setup::header::language_detection_method) + +#endif // INNOEXTRACT_SETUP_HEADER_HPP diff --git a/src/setup/IconEntry.cpp b/src/setup/icon.cpp similarity index 58% rename from src/setup/IconEntry.cpp rename to src/setup/icon.cpp index 66fb401..ab15c00 100644 --- a/src/setup/IconEntry.cpp +++ b/src/setup/icon.cpp @@ -1,20 +1,23 @@ -#include "setup/IconEntry.hpp" +#include "setup/icon.hpp" +#include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" +namespace setup { + namespace { -STORED_ENUM_MAP(StoredCloseOnExit, IconEntry::NoSetting, - IconEntry::NoSetting, - IconEntry::Yes, - IconEntry::No, +STORED_ENUM_MAP(stored_close_setting, icon_entry::NoSetting, + icon_entry::NoSetting, + icon_entry::CloseOnExit, + icon_entry::DontCloseOnExit, ); } // anonymous namespace -void IconEntry::load(std::istream & is, const inno_version & version) { +void icon_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { ::load(is); // uncompressed size of the icon entry structure @@ -23,27 +26,27 @@ void IconEntry::load(std::istream & is, const inno_version & version) { is >> encoded_string(name, version.codepage()); is >> encoded_string(filename, version.codepage()); is >> encoded_string(parameters, version.codepage()); - is >> encoded_string(workingDir, version.codepage()); - is >> encoded_string(iconFilename, version.codepage()); + is >> encoded_string(working_dir, version.codepage()); + is >> encoded_string(icon_file, version.codepage()); is >> encoded_string(comment, version.codepage()); load_condition_data(is, version); if(version >= INNO_VERSION(5, 3, 5)) { - is >> encoded_string(appUserModelId, version.codepage()); + is >> encoded_string(app_user_model_id, version.codepage()); } else { - appUserModelId.clear(); + app_user_model_id.clear(); } load_version_data(is, version); - iconIndex = load_number(is, version.bits); + icon_index = load_number(is, version.bits); if(version >= INNO_VERSION(1, 3, 21)) { - showCmd = load_number(is); - closeOnExit = stored_enum(is).get(); + show_command = load_number(is); + close_on_exit = stored_enum(is).get(); } else { - showCmd = 1, closeOnExit = NoSetting; + show_command = 1, close_on_exit = NoSetting; } if(version >= INNO_VERSION(2, 0, 7)) { @@ -52,7 +55,7 @@ void IconEntry::load(std::istream & is, const inno_version & version) { hotkey = 0; } - stored_flag_reader flags(is); + stored_flag_reader flags(is); flags.add(NeverUninstall); if(version >= INNO_VERSION(1, 3, 21)) { @@ -72,7 +75,9 @@ void IconEntry::load(std::istream & is, const inno_version & version) { options = flags; } -ENUM_NAMES(IconEntry::Options, "Icon Option", +} // namespace setup + +NAMES(setup::icon_entry::flags, "Icon Option", "never uninstall", "create only if file exists", "use app paths", @@ -81,8 +86,8 @@ ENUM_NAMES(IconEntry::Options, "Icon Option", "run minimized", ) -ENUM_NAMES(IconEntry::CloseOnExit, "Close on Exit", +NAMES(setup::icon_entry::close_setting, "Close on Exit", "no setting", - "yes", - "no", + "close on exit", + "don't close on exit", ) diff --git a/src/setup/icon.hpp b/src/setup/icon.hpp new file mode 100644 index 0000000..e7fdfdd --- /dev/null +++ b/src/setup/icon.hpp @@ -0,0 +1,62 @@ + +#ifndef INNOEXTRACT_SETUP_ICON_HPP +#define INNOEXTRACT_SETUP_ICON_HPP + +#include +#include +#include + +#include "setup/item.hpp" +#include "util/enum.hpp" +#include "util/flags.hpp" + +namespace setup { + +struct version; + +struct icon_entry : public item { + + FLAGS(flags, + NeverUninstall, + CreateOnlyIfFileExists, + UseAppPaths, + FolderShortcut, + ExcludeFromShowInNewInstall, + // obsolete options: + RunMinimized + ); + + enum close_setting { + NoSetting, + CloseOnExit, + DontCloseOnExit, + }; + + std::string name; + std::string filename; + std::string parameters; + std::string working_dir; + std::string icon_file; + std::string comment; + std::string app_user_model_id; + + int icon_index; + + int show_command; + + close_setting close_on_exit; + + uint16_t hotkey; + + flags options; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +NAMED_FLAGS(setup::icon_entry::flags) +NAMED_ENUM(setup::icon_entry::close_setting) + +#endif // INNOEXTRACT_SETUP_ICON_HPP diff --git a/src/setup/IniEntry.cpp b/src/setup/ini.cpp similarity index 61% rename from src/setup/IniEntry.cpp rename to src/setup/ini.cpp index effac15..6cc86af 100644 --- a/src/setup/IniEntry.cpp +++ b/src/setup/ini.cpp @@ -1,24 +1,27 @@ -#include "setup/IniEntry.hpp" +#include "setup/ini.hpp" #include +#include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" +namespace setup { + namespace { -STORED_FLAGS_MAP(StoredIniOptions, - IniEntry::CreateKeyIfDoesntExist, - IniEntry::UninsDeleteEntry, - IniEntry::UninsDeleteEntireSection, - IniEntry::UninsDeleteSectionIfEmpty, - IniEntry::HasValue, +STORED_FLAGS_MAP(stored_ini_flags, + ini_entry::CreateKeyIfDoesntExist, + ini_entry::UninsDeleteEntry, + ini_entry::UninsDeleteEntireSection, + ini_entry::UninsDeleteSectionIfEmpty, + ini_entry::HasValue, ); } // anonymous namespace -void IniEntry::load(std::istream & is, const inno_version & version) { +void ini_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { ::load(is); // uncompressed size of the ini entry structure @@ -36,10 +39,12 @@ void IniEntry::load(std::istream & is, const inno_version & version) { load_version_data(is, version); - options = stored_flags(is).get(); + options = stored_flags(is).get(); } -ENUM_NAMES(IniEntry::Options, "Ini Option", +} // namespace setup + +NAMES(setup::ini_entry::flags, "Ini Option", "create key if doesn't exist", "uninstall delete entry", "uninstall delete section", diff --git a/src/setup/ini.hpp b/src/setup/ini.hpp new file mode 100644 index 0000000..9901416 --- /dev/null +++ b/src/setup/ini.hpp @@ -0,0 +1,41 @@ + +#ifndef INNOEXTRACT_SETUP_INI_HPP +#define INNOEXTRACT_SETUP_INI_HPP + +#include +#include + +#include "setup/item.hpp" +#include "util/enum.hpp" +#include "util/flags.hpp" + +namespace setup { + +struct version; + +struct ini_entry : public item { + + FLAGS(flags, + CreateKeyIfDoesntExist, + UninsDeleteEntry, + UninsDeleteEntireSection, + UninsDeleteSectionIfEmpty, + HasValue + ); + + std::string inifile; + std::string section; + std::string key; + std::string value; + + flags options; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +NAMED_FLAGS(setup::ini_entry::flags) + +#endif // INNOEXTRACT_SETUP_INI_HPP diff --git a/src/setup/SetupItem.cpp b/src/setup/item.cpp similarity index 54% rename from src/setup/SetupItem.cpp rename to src/setup/item.cpp index e5f9eae..518b388 100644 --- a/src/setup/SetupItem.cpp +++ b/src/setup/item.cpp @@ -1,9 +1,12 @@ -#include "setup/SetupItem.hpp" +#include "setup/item.hpp" +#include "setup/version.hpp" #include "util/load.hpp" -void SetupItem::load_condition_data(std::istream & is, const inno_version & version) { +namespace setup { + +void item::load_condition_data(std::istream & is, const version & version) { if(version >= INNO_VERSION(2, 0, 0)) { is >> encoded_string(components, version.codepage()); @@ -23,17 +26,12 @@ void SetupItem::load_condition_data(std::istream & is, const inno_version & vers } if(version >= INNO_VERSION(4, 1, 0)) { - is >> encoded_string(afterInstall, version.codepage()); - is >> encoded_string(beforeInstall, version.codepage()); + is >> encoded_string(after_install, version.codepage()); + is >> encoded_string(before_install, version.codepage()); } else { - afterInstall.clear(), beforeInstall.clear(); + after_install.clear(), before_install.clear(); } } -void SetupItem::load_version_data(std::istream & is, const inno_version & version) { - - minVersion.load(is, version); - onlyBelowVersion.load(is, version); - -} +} // namespace setup diff --git a/src/setup/item.hpp b/src/setup/item.hpp new file mode 100644 index 0000000..bbebb24 --- /dev/null +++ b/src/setup/item.hpp @@ -0,0 +1,38 @@ + +#ifndef INNOEXTRACT_SETUP_ITEM_HPP +#define INNOEXTRACT_SETUP_ITEM_HPP + +#include +#include + +#include "setup/windows.hpp" + +namespace setup { + +struct version; + +struct item { + + std::string components; + std::string tasks; + std::string languages; + std::string check; + + std::string after_install; + std::string before_install; + + windows_version_range winver; + +protected: + + void load_condition_data(std::istream & is, const version & version); + + inline void load_version_data(std::istream & is, const version & version) { + winver.load(is, version); + } + +}; + +} // namespace setup + +#endif // INNOEXTRACT_SETUP_ITEM_HPP diff --git a/src/setup/language.cpp b/src/setup/language.cpp new file mode 100644 index 0000000..3f687da --- /dev/null +++ b/src/setup/language.cpp @@ -0,0 +1,67 @@ + +#include "setup/language.hpp" + +#include "setup/version.hpp" +#include "util/load.hpp" + +namespace setup { + +void language_entry::load(std::istream & is, const version & version) { + + if(version >= INNO_VERSION(4, 0, 0)) { + is >> encoded_string(name, version.codepage()); + } else { + name = "default"; + } + + is >> encoded_string(language_name, (version >= INNO_VERSION(4, 2, 2)) ? 1200 : 1252); + + is >> encoded_string(dialog_font, version.codepage()); + is >> encoded_string(title_font, version.codepage()); + is >> encoded_string(welcome_font, version.codepage()); + is >> encoded_string(copyright_font, version.codepage()); + + if(version >= INNO_VERSION(4, 0, 0)) { + is >> binary_string(data); + } + + if(version >= INNO_VERSION(4, 0, 1)) { + is >> ansi_string(license_text); + is >> ansi_string(info_before); + is >> ansi_string(info_after); + } else { + license_text.clear(), info_before.clear(), info_after.clear(); + } + + language_id = load_number(is); + + if(version >= INNO_VERSION(4, 2, 2) && (version < INNO_VERSION(5, 3, 0) || !version.unicode)) { + codepage = load_number(is); + } else { + codepage = 0; + } + if(!codepage) { + codepage = version.codepage(); + } + + dialog_font_size = load_number(is); + + if(version < INNO_VERSION(4, 1, 0)) { + dialog_font_standard_height = load_number(is); + } else { + dialog_font_standard_height = 0; + } + + title_font_size = load_number(is); + welcome_font_size = load_number(is); + copyright_font_size = load_number(is); + + if(version >= INNO_VERSION(5, 2, 3)) { + right_to_left = ::load(is); + } else { + right_to_left = false; + } + +} + +} // namespace setup diff --git a/src/setup/language.hpp b/src/setup/language.hpp new file mode 100644 index 0000000..72d0832 --- /dev/null +++ b/src/setup/language.hpp @@ -0,0 +1,44 @@ + +#ifndef INNOEXTRACT_SETUP_LANGUAGE_HPP +#define INNOEXTRACT_SETUP_LANGUAGE_HPP + +#include +#include +#include + +namespace setup { + +struct version; + +struct language_entry { + + // introduced in 2.0.1 + + std::string name; + std::string language_name; + std::string dialog_font; + std::string title_font; + std::string welcome_font; + std::string copyright_font; + std::string data; + std::string license_text; + std::string info_before; + std::string info_after; + + uint32_t language_id; + uint32_t codepage; + size_t dialog_font_size; + size_t dialog_font_standard_height; + size_t title_font_size; + size_t welcome_font_size; + size_t copyright_font_size; + + bool right_to_left; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +#endif // INNOEXTRACT_SETUP_LANGUAGE_HPP diff --git a/src/setup/MessageEntry.cpp b/src/setup/message.cpp similarity index 57% rename from src/setup/MessageEntry.cpp rename to src/setup/message.cpp index 52b01c5..bf7a62a 100644 --- a/src/setup/MessageEntry.cpp +++ b/src/setup/message.cpp @@ -1,11 +1,14 @@ -#include "setup/MessageEntry.hpp" +#include "setup/message.hpp" #include +#include "setup/version.hpp" #include "util/load.hpp" -void MessageEntry::load(std::istream & is, const inno_version & version) { +namespace setup { + +void message_entry::load(std::istream & is, const version & version) { is >> encoded_string(name, version.codepage()); is >> binary_string(value); // encoding depends on the codepage in the LanguageEntry @@ -13,3 +16,5 @@ void MessageEntry::load(std::istream & is, const inno_version & version) { language = load_number(is); } + +} // namespace setup diff --git a/src/setup/MessageEntry.hpp b/src/setup/message.hpp similarity index 51% rename from src/setup/MessageEntry.hpp rename to src/setup/message.hpp index e687816..76f60f6 100644 --- a/src/setup/MessageEntry.hpp +++ b/src/setup/message.hpp @@ -1,13 +1,15 @@ -#ifndef INNOEXTRACT_SETUP_CUSTOMMESSAGEENTRY_HPP -#define INNOEXTRACT_SETUP_CUSTOMMESSAGEENTRY_HPP +#ifndef INNOEXTRACT_SETUP_MESSAGE_HPP +#define INNOEXTRACT_SETUP_MESSAGE_HPP #include #include -#include "setup/version.hpp" +namespace setup { -struct MessageEntry { +struct version; + +struct message_entry { // introduced in 4.2.1 @@ -20,8 +22,10 @@ struct MessageEntry { // Index into the default language entry list or -1. int language; - void load(std::istream & is, const inno_version & version); + void load(std::istream & is, const version & version); }; -#endif // INNOEXTRACT_SETUP_CUSTOMMESSAGEENTRY_HPP +} // namespace setup + +#endif // INNOEXTRACT_SETUP_MESSAGE_HPP diff --git a/src/setup/permission.cpp b/src/setup/permission.cpp new file mode 100644 index 0000000..47af92b --- /dev/null +++ b/src/setup/permission.cpp @@ -0,0 +1,16 @@ + +#include "setup/permission.hpp" + +#include "util/load.hpp" + +namespace setup { + +void permission_entry::load(std::istream & is, const version & version) { + + (void)version; + + is >> binary_string(permissions); // an array of TGrantPermissionEntry's + +} + +} // namespace setup diff --git a/src/setup/permission.hpp b/src/setup/permission.hpp new file mode 100644 index 0000000..e94b918 --- /dev/null +++ b/src/setup/permission.hpp @@ -0,0 +1,24 @@ + +#ifndef INNOEXTRACT_SETUP_PERMISSION_HPP +#define INNOEXTRACT_SETUP_PERMISSION_HPP + +#include +#include + +namespace setup { + +struct version; + +struct permission_entry { + + // introduced in 4.1.0 + + std::string permissions; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +#endif // INNOEXTRACT_SETUP_PERMISSION_HPP diff --git a/src/setup/RegistryEntry.cpp b/src/setup/registry.cpp similarity index 61% rename from src/setup/RegistryEntry.cpp rename to src/setup/registry.cpp index 0b109bf..e4afbf2 100644 --- a/src/setup/RegistryEntry.cpp +++ b/src/setup/registry.cpp @@ -1,42 +1,45 @@ -#include "setup/RegistryEntry.hpp" +#include "setup/registry.hpp" #include +#include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" +namespace setup { + namespace { // 16-bit -STORED_ENUM_MAP(StoredRegistryEntryType0, RegistryEntry::None, - RegistryEntry::None, - RegistryEntry::String, +STORED_ENUM_MAP(stored_registry_entry_type_0, registry_entry::None, + registry_entry::None, + registry_entry::String, ); -STORED_ENUM_MAP(StoredRegistryEntryType1, RegistryEntry::None, - RegistryEntry::None, - RegistryEntry::String, - RegistryEntry::ExpandString, - RegistryEntry::DWord, - RegistryEntry::Binary, - RegistryEntry::MultiString, +STORED_ENUM_MAP(stored_registry_entry_type_1, registry_entry::None, + registry_entry::None, + registry_entry::String, + registry_entry::ExpandString, + registry_entry::DWord, + registry_entry::Binary, + registry_entry::MultiString, ); // starting with version 5.2.5 -STORED_ENUM_MAP(StoredRegistryEntryType2, RegistryEntry::None, - RegistryEntry::None, - RegistryEntry::String, - RegistryEntry::ExpandString, - RegistryEntry::DWord, - RegistryEntry::Binary, - RegistryEntry::MultiString, - RegistryEntry::QWord, +STORED_ENUM_MAP(stored_registry_entry_type_2, registry_entry::None, + registry_entry::None, + registry_entry::String, + registry_entry::ExpandString, + registry_entry::DWord, + registry_entry::Binary, + registry_entry::MultiString, + registry_entry::QWord, ); } // anonymous namespace -void RegistryEntry::load(std::istream & is, const inno_version & version) { +void registry_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { ::load(is); // uncompressed size of the directory entry structure @@ -61,7 +64,7 @@ void RegistryEntry::load(std::istream & is, const inno_version & version) { load_version_data(is, version); if(version.bits != 16) { - hive = Hive(load_number(is) & ~0x80000000); + hive = hive_name(load_number(is) & ~0x80000000); } else { hive = Unset; } @@ -73,14 +76,14 @@ void RegistryEntry::load(std::istream & is, const inno_version & version) { } if(version >= INNO_VERSION(5, 2, 5)) { - type = stored_enum(is).get(); + type = stored_enum(is).get(); } else if(version.bits != 16) { - type = stored_enum(is).get(); + type = stored_enum(is).get(); } else { - type = stored_enum(is).get(); + type = stored_enum(is).get(); } - stored_flag_reader flags(is); + stored_flag_reader flags(is); if(version.bits != 16) { flags.add(CreateValueIfDoesntExist); @@ -104,7 +107,9 @@ void RegistryEntry::load(std::istream & is, const inno_version & version) { options = flags; } -ENUM_NAMES(RegistryEntry::Options, "Registry Option", +} // namespace setup + +NAMES(setup::registry_entry::flags, "Registry Option", "create value if doesn't exist", "uninstall delete value", "uninstall clear value", @@ -119,7 +124,7 @@ ENUM_NAMES(RegistryEntry::Options, "Registry Option", "64 bit", ) -ENUM_NAMES(RegistryEntry::Hive, "Registry Hive", +NAMES(setup::registry_entry::hive_name, "Registry Hive", "HKCR", "HKCU", "HKLM", @@ -130,7 +135,7 @@ ENUM_NAMES(RegistryEntry::Hive, "Registry Hive", "Unset", ) -ENUM_NAMES(RegistryEntry::Type, "Registry Entry Type", +NAMES(setup::registry_entry::value_type, "Registry Entry Type", "none", "string", "expand string", diff --git a/src/setup/RegistryEntry.hpp b/src/setup/registry.hpp similarity index 54% rename from src/setup/RegistryEntry.hpp rename to src/setup/registry.hpp index c3485f4..3b8c5bd 100644 --- a/src/setup/RegistryEntry.hpp +++ b/src/setup/registry.hpp @@ -1,19 +1,22 @@ -#ifndef INNOEXTRACT_SETUP_REGISTRYENTRY_HPP -#define INNOEXTRACT_SETUP_REGISTRYENTRY_HPP +#ifndef INNOEXTRACT_SETUP_REGISTRY_HPP +#define INNOEXTRACT_SETUP_REGISTRY_HPP #include #include -#include "setup/SetupItem.hpp" -#include "setup/version.hpp" -#include "setup/WindowsVersion.hpp" +#include "setup/item.hpp" +#include "setup/windows.hpp" #include "util/enum.hpp" #include "util/flags.hpp" -struct RegistryEntry : public SetupItem { +namespace setup { + +struct version; + +struct registry_entry : public item { - FLAGS(Options, + FLAGS(flags, CreateValueIfDoesntExist, UninsDeleteValue, UninsClearValue, @@ -28,7 +31,7 @@ struct RegistryEntry : public SetupItem { Bits64 ); - enum Hive { + enum hive_name { HKCR, HKCU, HKLM, @@ -39,7 +42,7 @@ struct RegistryEntry : public SetupItem { Unset, }; - enum Type { + enum value_type { None, String, ExpandString, @@ -55,23 +58,22 @@ struct RegistryEntry : public SetupItem { std::string permissions; - Hive hive; + hive_name hive; int permission; //!< index into the permission entry list - Type type; + value_type type; - Options options; + flags options; - void load(std::istream & is, const inno_version & version); + void load(std::istream & is, const version & version); }; -FLAGS_OVERLOADS(RegistryEntry::Options) -NAMED_ENUM(RegistryEntry::Options) - -NAMED_ENUM(RegistryEntry::Hive) +} // namespace setup -NAMED_ENUM(RegistryEntry::Type) +NAMED_FLAGS(setup::registry_entry::flags) +NAMED_ENUM(setup::registry_entry::hive_name) +NAMED_ENUM(setup::registry_entry::value_type) -#endif // INNOEXTRACT_SETUP_REGISTRYENTRY_HPP +#endif // INNOEXTRACT_SETUP_REGISTRY_HPP diff --git a/src/setup/RunEntry.cpp b/src/setup/run.cpp similarity index 66% rename from src/setup/RunEntry.cpp rename to src/setup/run.cpp index 75cc9e7..8ffad35 100644 --- a/src/setup/RunEntry.cpp +++ b/src/setup/run.cpp @@ -1,22 +1,25 @@ -#include "setup/RunEntry.hpp" +#include "setup/run.hpp" #include +#include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" +namespace setup { + namespace { -STORED_ENUM_MAP(StoredRunWait, RunEntry::WaitUntilTerminated, - RunEntry::WaitUntilTerminated, - RunEntry::NoWait, - RunEntry::WaitUntilIdle, +STORED_ENUM_MAP(stored_run_wait_condition, run_entry::WaitUntilTerminated, + run_entry::WaitUntilTerminated, + run_entry::NoWait, + run_entry::WaitUntilIdle, ); } // anonymous namespace -void RunEntry::load(std::istream & is, const inno_version & version) { +void run_entry::load(std::istream & is, const version & version) { if(version < INNO_VERSION(1, 3, 21)) { ::load(is); // uncompressed size of the directory entry structure @@ -24,16 +27,16 @@ void RunEntry::load(std::istream & is, const inno_version & version) { is >> encoded_string(name, version.codepage()); is >> encoded_string(parameters, version.codepage()); - is >> encoded_string(workingDir, version.codepage()); + is >> encoded_string(working_dir, version.codepage()); if(version >= INNO_VERSION(1, 3, 21)) { - is >> encoded_string(runOnceId, version.codepage()); + is >> encoded_string(run_once_id, version.codepage()); } else { - runOnceId.clear(); + run_once_id.clear(); } if(version >= INNO_VERSION(2, 0, 2)) { - is >> encoded_string(statusMessage, version.codepage()); + is >> encoded_string(status_message, version.codepage()); } else { - statusMessage.clear(); + status_message.clear(); } if(version >= INNO_VERSION(5, 1, 13)) { is >> encoded_string(verb, version.codepage()); @@ -49,14 +52,14 @@ void RunEntry::load(std::istream & is, const inno_version & version) { load_version_data(is, version); if(version >= INNO_VERSION(1, 3, 21)) { - showCmd = load_number(is); + show_command = load_number(is); } else { - showCmd = 0; + show_command = 0; } - wait = stored_enum(is).get(); + wait = stored_enum(is).get(); - stored_flag_reader flags(is); + stored_flag_reader flags(is); flags.add(ShellExec); if(version >= INNO_VERSION(1, 3, 21)) { @@ -82,7 +85,9 @@ void RunEntry::load(std::istream & is, const inno_version & version) { options = flags; } -ENUM_NAMES(RunEntry::Options, "Run Option", +} // namespace setup + +NAMES(setup::run_entry::flags, "Run Option", "shell exec", "skip if doesn't exist", "post install", @@ -95,7 +100,7 @@ ENUM_NAMES(RunEntry::Options, "Run Option", "run as original user", ) -ENUM_NAMES(RunEntry::Wait, "Run Wait Type", +NAMES(setup::run_entry::wait_condition, "Run Wait Type", "wait until terminated", "no wait", "wait until idle", diff --git a/src/setup/run.hpp b/src/setup/run.hpp new file mode 100644 index 0000000..7428fba --- /dev/null +++ b/src/setup/run.hpp @@ -0,0 +1,60 @@ + +#ifndef INNOEXTRACT_SETUP_RUN_HPP +#define INNOEXTRACT_SETUP_RUN_HPP + +#include +#include + +#include "setup/item.hpp" +#include "util/enum.hpp" +#include "util/flags.hpp" + +namespace setup { + +struct version; + +struct run_entry : public item { + + FLAGS(flags, + ShellExec, + SkipIfDoesntExist, + PostInstall, + Unchecked, + SkipIfSilent, + Skipif_not_equalSilent, + HideWizard, + Bits32, + Bits64, + RunAsOriginalUser + ); + + enum wait_condition { + WaitUntilTerminated, + NoWait, + WaitUntilIdle, + }; + + std::string name; + std::string parameters; + std::string working_dir; + std::string run_once_id; + std::string status_message; + std::string verb; + std::string description; + + int show_command; + + wait_condition wait; + + flags options; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +NAMED_FLAGS(setup::run_entry::flags) +NAMED_ENUM(setup::run_entry::wait_condition) + +#endif // INNOEXTRACT_SETUP_RUN_HPP diff --git a/src/setup/SetupTaskEntry.cpp b/src/setup/task.cpp similarity index 73% rename from src/setup/SetupTaskEntry.cpp rename to src/setup/task.cpp index 7c4d7ec..8c3079c 100644 --- a/src/setup/SetupTaskEntry.cpp +++ b/src/setup/task.cpp @@ -1,16 +1,19 @@ -#include "setup/SetupTaskEntry.hpp" +#include "setup/task.hpp" #include +#include "setup/version.hpp" #include "util/load.hpp" #include "util/storedenum.hpp" -void SetupTaskEntry::load(std::istream & is, const inno_version & version) { +namespace setup { + +void task_entry::load(std::istream & is, const version & version) { is >> encoded_string(name, version.codepage()); is >> encoded_string(description, version.codepage()); - is >> encoded_string(groupDescription, version.codepage()); + is >> encoded_string(group_description, version.codepage()); is >> encoded_string(components, version.codepage()); if(version >= INNO_VERSION(4, 0, 1)) { is >> encoded_string(languages, version.codepage()); @@ -25,10 +28,9 @@ void SetupTaskEntry::load(std::istream & is, const inno_version & version) { check.clear(), level = 0, used = true; } - minVersion.load(is, version); - onlyBelowVersion.load(is, version); + winver.load(is, version); - stored_flag_reader flags(is); + stored_flag_reader flags(is); flags.add(Exclusive); flags.add(Unchecked); @@ -45,7 +47,9 @@ void SetupTaskEntry::load(std::istream & is, const inno_version & version) { options = flags; } -ENUM_NAMES(SetupTaskEntry::Options, "Setup Task Option", +} // namespace setup + +NAMES(setup::task_entry::flags, "Setup Task Option", "exclusive", "unchecked", "restart", diff --git a/src/setup/task.hpp b/src/setup/task.hpp new file mode 100644 index 0000000..2fff2ad --- /dev/null +++ b/src/setup/task.hpp @@ -0,0 +1,50 @@ + +#ifndef INNOEXTRACT_SETUP_TASK_HPP +#define INNOEXTRACT_SETUP_TASK_HPP + +#include +#include + +#include "setup/windows.hpp" +#include "util/enum.hpp" +#include "util/flags.hpp" + +namespace setup { + +struct version; + +struct task_entry { + + // introduced in 2.0.0 + + FLAGS(flags, + Exclusive, + Unchecked, + Restart, + CheckedOnce, + DontInheritCheck + ); + + std::string name; + std::string description; + std::string group_description; + std::string components; + std::string languages; + std::string check; + + int level; + bool used; + + windows_version_range winver; + + flags options; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +NAMED_FLAGS(setup::task_entry::flags) + +#endif // INNOEXTRACT_SETUP_TASK_HPP diff --git a/src/setup/type.cpp b/src/setup/type.cpp new file mode 100644 index 0000000..e6e7c3e --- /dev/null +++ b/src/setup/type.cpp @@ -0,0 +1,75 @@ + +#include "setup/type.hpp" + +#include "setup/version.hpp" +#include "util/load.hpp" +#include "util/storedenum.hpp" + +namespace setup { + +namespace { + +FLAGS(type_flags, + CustomSetupType +); + +STORED_FLAGS_MAP(stored_type_flags, + CustomSetupType, +); + +STORED_ENUM_MAP(stored_setup_type, type_entry::User, + type_entry::User, + type_entry::DefaultFull, + type_entry::DefaultCompact, + type_entry::DefaultCustom, +); + +} // anonymous namespace + +} // namespace setup + +NAMED_FLAGS(setup::type_flags) + +namespace setup { + +void type_entry::load(std::istream & is, const version & version) { + + is >> encoded_string(name, version.codepage()); + is >> encoded_string(description, version.codepage()); + if(version >= INNO_VERSION(4, 0, 1)) { + is >> encoded_string(languages, version.codepage()); + } else { + languages.clear(); + } + if(version >= INNO_VERSION(3, 0, 8)) { + is >> encoded_string(check, version.codepage()); + } else { + check.clear(); + } + + winver.load(is, version); + + type_flags options = stored_flags(is).get(); + custom_type = (options & CustomSetupType); + + if(version >= INNO_VERSION(4, 0, 3)) { + type = stored_enum(is).get(); + } else { + type = User; + } + + size = (version >= INNO_VERSION(4, 0, 0)) ? load_number(is) : load_number(is); +} + +} // namespace setup + +NAMES(setup::type_flags, "Setyp Type Option", + "is custom", +) + +NAMES(setup::type_entry::setup_type, "Setyp Type", + "user", + "default full", + "default compact", + "default custom", +) diff --git a/src/setup/type.hpp b/src/setup/type.hpp new file mode 100644 index 0000000..e1600e7 --- /dev/null +++ b/src/setup/type.hpp @@ -0,0 +1,49 @@ + +#ifndef INNOEXTRACT_SETUP_TYPE_HPP +#define INNOEXTRACT_SETUP_TYPE_HPP + +#include +#include +#include + +#include "setup/windows.hpp" +#include "util/enum.hpp" +#include "util/flags.hpp" + +namespace setup { + +struct version; + +struct type_entry { + + // introduced in 2.0.0 + + enum setup_type { + User, + DefaultFull, + DefaultCompact, + DefaultCustom + }; + + std::string name; + std::string description; + std::string languages; + std::string check; + + windows_version_range winver; + + bool custom_type; + + setup_type type; + + uint64_t size; + + void load(std::istream & is, const version & version); + +}; + +} // namespace setup + +NAMED_ENUM(setup::type_entry::setup_type) + +#endif // INNOEXTRACT_SETUP_TYPE_HPP diff --git a/src/setup/version.cpp b/src/setup/version.cpp index ad3c379..e295870 100644 --- a/src/setup/version.cpp +++ b/src/setup/version.cpp @@ -3,45 +3,53 @@ #include #include -#include +#include +#include #include +#include -#include +#include "util/util.hpp" -using std::cout; using std::string; -using std::endl; -typedef char StoredLegacySetupDataVersion[12]; +namespace setup { -struct KnownLegacySetupDataVersion { +namespace { + +typedef char stored_legacy_version[12]; + +struct known_legacy_version { char name[13]; // terminating 0 byte is ignored - InnoVersionConstant version; + version_constant version; unsigned char bits; + operator version_constant() const { return version; } + }; -const KnownLegacySetupDataVersion knownLegacySetupDataVersions[] = { +const known_legacy_version legacy_versions[] = { { "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]; +typedef char stored_version[64]; -struct KnownSetupDataVersion { +struct known_version { - StoredSetupDataVersion name; + stored_version name; - InnoVersionConstant version; + version_constant version; bool unicode; + operator version_constant() const { return version; } + }; -const KnownSetupDataVersion knownSetupDataVersions[] = { +const known_version versions[] = { { "Inno Setup Setup Data (1.3.21)", INNO_VERSION_EXT(1, 3, 21, 0), false }, { "Inno Setup Setup Data (1.3.25)", INNO_VERSION_EXT(1, 3, 25, 0), false }, { "Inno Setup Setup Data (2.0.0)", INNO_VERSION_EXT(2, 0, 0, 0), false }, @@ -112,7 +120,9 @@ const KnownSetupDataVersion knownSetupDataVersions[] = { { "Inno Setup Setup Data (5.4.2) (u)", INNO_VERSION_EXT(5, 4, 2, 0), true }, }; -std::ostream & operator<<(std::ostream & os, const inno_version & v) { +} // anonymous namespace + +std::ostream & operator<<(std::ostream & os, const version & v) { os << v.a() << '.' << v.b() << '.' << v.c(); if(v.d()) { @@ -134,80 +144,177 @@ std::ostream & operator<<(std::ostream & os, const inno_version & v) { return os; } -void inno_version::load(std::istream & is) { +void version::load(std::istream & is) { - BOOST_STATIC_ASSERT(sizeof(StoredLegacySetupDataVersion) <= sizeof(StoredSetupDataVersion)); + static const char digits[] = "0123456789"; - StoredLegacySetupDataVersion legacyVersion; - is.read(legacyVersion, sizeof(legacyVersion)); + BOOST_STATIC_ASSERT(sizeof(stored_legacy_version) <= sizeof(stored_version)); - if(legacyVersion[0] == 'i' && legacyVersion[sizeof(legacyVersion) - 1] == '\x1a') { - - cout << "found legacy version: \"" - << std::string(legacyVersion, sizeof(legacyVersion) - 1) << '"' << endl; + stored_legacy_version legacy_version; + is.read(legacy_version, sizeof(legacy_version)); + + if(legacy_version[0] == 'i' && legacy_version[sizeof(legacy_version) - 1] == '\x1a') { - 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; + for(size_t i = 0; i < ARRAY_SIZE(legacy_versions); i++) { + if(!memcmp(legacy_version, legacy_versions[i].name, sizeof(legacy_version))) { + value = legacy_versions[i].version; + bits = legacy_versions[i].bits; unicode = false; known = true; - cout << "-> version is known" << endl; return; } } - // TODO autodetect version + if(legacy_version[0] != 'i' || legacy_version[2] != '.' || legacy_version[4] != '.' + || legacy_version[7] != '-' || legacy_version[8] != '-') { + throw version_error(); + } + + if(legacy_version[9] == '1' && legacy_version[10] == '6') { + bits = 16; + } else if(legacy_version[9] == '3' && legacy_version[10] == '2') { + bits = 32; + } else { + throw version_error(); + } + + std::string version_str(legacy_version, legacy_version + ARRAY_SIZE(legacy_version) + 1); + + try { + unsigned a = boost::lexical_cast(version_str.substr(1, 1)); + unsigned b = boost::lexical_cast(version_str.substr(3, 1)); + unsigned c = boost::lexical_cast(version_str.substr(5, 2)); + value = INNO_VERSION(a, b, c); + } catch(boost::bad_lexical_cast) { + throw version_error(); + } + unicode = false; known = false; - cout << "-> unknown version" << endl; - throw new string("bad version"); + return; } - StoredSetupDataVersion storedVersion; - memcpy(storedVersion, legacyVersion, sizeof(legacyVersion)); - is.read(storedVersion + sizeof(legacyVersion), sizeof(storedVersion) - sizeof(legacyVersion)); + stored_version version; + memcpy(version, legacy_version, sizeof(legacy_version)); + is.read(version + sizeof(legacy_version), sizeof(version) - sizeof(legacy_version)); - char * end = std::find(storedVersion, storedVersion + ARRAY_SIZE(storedVersion) - 1, '\0'); - std::string versionstr(storedVersion, end); - cout << "found version: \"" << versionstr << '"' << endl; - for(size_t i = 0; i < ARRAY_SIZE(knownSetupDataVersions); i++) { - if(!memcmp(storedVersion, knownSetupDataVersions[i].name, sizeof(storedVersion))) { - version = knownSetupDataVersions[i].version; + for(size_t i = 0; i < ARRAY_SIZE(versions); i++) { + if(!memcmp(version, versions[i].name, sizeof(version))) { + value = versions[i].version; bits = 32; - unicode = knownSetupDataVersions[i].unicode; + unicode = versions[i].unicode; known = true; - cout << "-> version is known" << endl; return; } } - // TODO autodetect version + char * end = std::find(version, version + ARRAY_SIZE(version), '\0'); + string version_str(version, end); + if(version_str.find("Inno Setup") == string::npos) { + throw version_error(); + } - known = false; + size_t bracket = version_str.find('('); + for(; bracket != string::npos; bracket = version_str.find('(', bracket + 1)) { + + if(version_str.length() - bracket < 6) { + continue; + } + + try { + + size_t a_start = bracket + 1; + size_t a_end = version_str.find_first_not_of(digits, a_start); + if(a_end == string::npos || version_str[a_end] != '.') { + continue; + } + unsigned a = boost::lexical_cast(version_str.substr(a_start, a_end - a_start)); + + size_t b_start = a_end + 1; + size_t b_end = version_str.find_first_not_of(digits, b_start); + if(b_end == string::npos || version_str[b_end] != '.') { + continue; + } + unsigned b = boost::lexical_cast(version_str.substr(b_start, b_end - b_start)); + + size_t c_start = b_end + 1; + size_t c_end = version_str.find_first_not_of(digits, c_start); + if(c_end == string::npos) { + continue; + } + unsigned c = boost::lexical_cast(version_str.substr(c_start, c_end - c_start)); + + size_t d_start = c_end; + if(version_str[d_start] == 'a') { + if(d_start + 1 >= version_str.length()) { + continue; + } + d_start++; + } + + unsigned d = 0; + if(version_str[d_start] == '.') { + d_start++; + size_t d_end = version_str.find_first_not_of(digits, d_start); + if(d_end != string::npos && d_end != d_start) { + d = boost::lexical_cast(version_str.substr(d_start, d_end - d_start)); + } + } + + value = INNO_VERSION_EXT(a, b, c, d); + break; + + } catch(boost::bad_lexical_cast) { + continue; + } + } + if(bracket == string::npos) { + throw version_error(); + } - cout << "-> unknown version" << endl; - throw new string("bad version"); + bits = 32; + unicode = (version_str.find("(u)") != string::npos); + known = false; } -bool inno_version::isSuspicious() const { +bool version::is_ambiguous() const { - if(version == INNO_VERSION(2, 0, 1)) { + if(value == INNO_VERSION(2, 0, 1)) { // might be either 2.0.1 or 2.0.2 return true; } - if(version == INNO_VERSION(3, 0, 3)) { + if(value == INNO_VERSION(3, 0, 3)) { // might be either 3.0.3 or 3.0.4 return true; } - if(version == INNO_VERSION(4, 2, 3)) { + if(value == INNO_VERSION(4, 2, 3)) { // might be either 4.2.3 or 4.2.4 return true; } return false; } + +version_constant version::next() { + + const known_legacy_version * legacy_end = legacy_versions + ARRAY_SIZE(legacy_versions); + const known_legacy_version * legacy_version; + legacy_version = std::upper_bound(legacy_versions, legacy_end, value); + if(legacy_version != legacy_end) { + return value = legacy_version->version; + } + + const known_version * end = versions + ARRAY_SIZE(versions); + const known_version * version = std::upper_bound(versions, end, value); + if(version != end) { + return version->version; + } + + return 0; +} + +} // namespace setup diff --git a/src/setup/version.hpp b/src/setup/version.hpp index a89950a..00fd070 100644 --- a/src/setup/version.hpp +++ b/src/setup/version.hpp @@ -4,16 +4,24 @@ #include #include +#include -typedef uint32_t InnoVersionConstant; -#define INNO_VERSION_EXT(a, b, c, d) \ - ((InnoVersionConstant(a) << 24) | (InnoVersionConstant(b) << 16) \ - | (InnoVersionConstant(c) << 8) | InnoVersionConstant(d)) +namespace setup { + +struct version_error : public std::exception { }; + +typedef uint32_t version_constant; +#define INNO_VERSION_EXT(a, b, c, d) ( \ + (::setup::version_constant(a) << 24) \ + | (::setup::version_constant(b) << 16) \ + | (::setup::version_constant(c) << 8) \ + | (::setup::version_constant(d) ) \ +) #define INNO_VERSION(a, b, c) INNO_VERSION_EXT(a, b, c, 0) -struct inno_version { +struct version { - InnoVersionConstant version; + version_constant value; uint8_t bits; // 16 or 32 @@ -21,66 +29,40 @@ struct inno_version { bool known; + inline version() : known(false) { } - inline inno_version() : known(false) { } + inline version(version_constant value, bool unicode = false, + bool known = false, uint8_t bits = 32) + : value(value), bits(bits), unicode(unicode), known(known) { } - inline inno_version(InnoVersionConstant _version, bool _unicode = false, - bool _known = false, uint8_t _bits = 32) - : version(_version), bits(_bits), unicode(_unicode), known(_known) { } + inline version(uint8_t a, uint8_t b, uint8_t c, uint8_t d = 0, bool unicode = false, + bool known = false, uint8_t bits = 32) + : value(INNO_VERSION_EXT(a, b, c, d)), bits(bits), unicode(unicode), known(known) { } - inline inno_version(uint8_t a, uint8_t b, uint8_t c, uint8_t d = 0, bool _unicode = false, - bool _known = false, uint8_t _bits = 32) - : version(INNO_VERSION_EXT(a, b, c, d)), bits(_bits), unicode(_unicode), known(_known) { } - - inline unsigned int a() const { return version >> 24; } - inline unsigned int b() const { return (version >> 16) & 0xff; } - inline unsigned int c() const { return (version >> 8) & 0xff; } - inline unsigned int d() const { return version & 0xff; } + inline unsigned int a() const { return value >> 24; } + inline unsigned int b() const { return (value >> 16) & 0xff; } + inline unsigned int c() const { return (value >> 8) & 0xff; } + inline unsigned int d() const { return value & 0xff; } void load(std::istream & is); - //! @return the Windows codepage used for encode strings + //! @return the Windows codepage used to encode strings inline uint32_t codepage() const { return uint32_t(unicode ? 1200 : 1252); } //! @return true if the version stored might not be correct - inline bool isSuspicious() const; + inline bool is_ambiguous() const; + + operator version_constant() const { + return value; + } + + version_constant next(); }; -inline bool operator==(const inno_version & a, const inno_version & b) { - return a.version == b.version; -} -inline bool operator!=(const inno_version & a, const inno_version & b) { - return !operator==(a, b); -} -inline bool operator< (const inno_version & a, const inno_version & b) { - return a.version < b.version; -} -inline bool operator> (const inno_version & a, const inno_version & b) { - return operator< (b, a); -} -inline bool operator<=(const inno_version & a, const inno_version & b) { - return !operator> (a, b); -} -inline bool operator>=(const inno_version & a, const inno_version & b) { - return !operator< (a, b); -} - -inline bool operator==(const inno_version & a, InnoVersionConstant b) { return a.version == b; } -inline bool operator!=(const inno_version & a, InnoVersionConstant b) { return !operator==(a, b); } -inline bool operator< (const inno_version & a, InnoVersionConstant b) { return a.version < b; } -inline bool operator> (const inno_version & a, InnoVersionConstant b) { return operator< (b, a); } -inline bool operator<=(const inno_version & a, InnoVersionConstant b) { return !operator> (a, b); } -inline bool operator>=(const inno_version & a, InnoVersionConstant b) { return !operator< (a, b); } - -inline bool operator==(InnoVersionConstant a, const inno_version & b) { return a == b.version; } -inline bool operator!=(InnoVersionConstant a, const inno_version & b) { return !operator==(a, b); } -inline bool operator< (InnoVersionConstant a, const inno_version & b) { return a < b.version; } -inline bool operator> (InnoVersionConstant a, const inno_version & b) { return operator< (b, a); } -inline bool operator<=(InnoVersionConstant a, const inno_version & b) { return !operator> (a, b); } -inline bool operator>=(InnoVersionConstant a, const inno_version & b) { return !operator< (a, b); } +std::ostream & operator<<(std::ostream & os, const version & version); -std::ostream & operator<<(std::ostream & os, const inno_version & version); +} // namespace setup #endif // INNOEXTRACT_SETUP_VERSION_HPP diff --git a/src/setup/windows.cpp b/src/setup/windows.cpp new file mode 100644 index 0000000..e908394 --- /dev/null +++ b/src/setup/windows.cpp @@ -0,0 +1,145 @@ + +#include "setup/windows.hpp" + +#include +#include + +#include "setup/version.hpp" +#include "util/load.hpp" +#include "util/util.hpp" + +namespace setup { + +const windows_version windows_version::none = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0 } }; + +void windows_version::data::load(std::istream & is, const version & version) { + + if(version >= INNO_VERSION(1, 3, 21)) { + build = load_number(is); + } else { + build = 0; + } + + minor = load_number(is); + major = load_number(is); + +} + +void windows_version::load(std::istream & is, const version & version) { + + win_version.load(is, version); + nt_version.load(is, version); + + if(version >= INNO_VERSION(1, 3, 21)) { + nt_service_pack.minor = load_number(is); + nt_service_pack.major = load_number(is); + } else { + nt_service_pack.major = 0, nt_service_pack.minor = 0; + } + +} + +void windows_version_range::load(std::istream & is, const version & version) { + begin.load(is, version); + end.load(is, version); +} + + +namespace { + +struct windows_version_name { + + const char * name; + + windows_version::data version; + +}; + +windows_version_name windows_version_names[] = { + { "Windows 1.0", { 1, 4, 0 } }, + { "Windows 2.0", { 2, 11, 0 } }, + { "Windows 3.0", { 3, 0, 0 } }, + { "Windows for Workgroups 3.11", { 3, 11, 0 } }, + { "Windows 95", { 4, 0, 950 } }, + { "Windows 98", { 4, 1, 1998 } }, + { "Windows 98 Second Edition", { 4, 1, 2222 } }, + { "Windows ME", { 4, 90, 3000 } }, +}; + +windows_version_name windows_nt_version_names[] = { + { "Windows NT Workstation 3.5", { 3, 5, 807 } }, + { "Windows NT 3.1", { 3, 10, 528 } }, + { "Windows NT Workstation 3.51", { 3, 51, 1057 } }, + { "Windows NT Workstation 4.0", { 4, 0, 1381 } }, + { "Windows 2000", { 5, 0, 2195 } }, + { "Windows XP", { 5, 1, 2600 } }, + { "Windows XP x64", { 5, 2, 3790 } }, + { "Windows Vista", { 6, 0, 6000 } }, + { "Windows 7", { 6, 1, 7600 } } +}; + +const char * get_version_name(const windows_version::data & version, bool nt = false) { + + windows_version_name * names; + size_t count; + if(nt) { + names = windows_nt_version_names, count = ARRAY_SIZE(windows_nt_version_names); + } else { + names = windows_version_names, count = ARRAY_SIZE(windows_version_names); + } + + for(size_t i = 0; i < count; i++) { + const windows_version_name & v = names[i]; + if(v.version.major != version.major || v.version.minor < version.minor) { + continue; + } + return v.name; + }; + return NULL; +} + +} // nanonymous namespace + +std::ostream & operator<<(std::ostream & os, const windows_version::data & v) { + os << v.major << '.' << v.minor; + if(v.build) { + os << v.build; + } + return os; +} + +std::ostream & operator<<(std::ostream & os, const windows_version & v) { + + os << v.win_version; + if(v.nt_version != v.win_version) { + os << " nt " << v.nt_version; + } + + const char * win_name = get_version_name(v.win_version); + const char * nt_name = get_version_name(v.nt_version, true); + + if(win_name || nt_name) { + os << " ("; + if(win_name) { + os << win_name; + } + if(nt_name && nt_name != win_name) { + if(win_name) { + os << " / "; + } + os << nt_name; + } + os << ')'; + } + + if(v.nt_service_pack.major || v.nt_service_pack.minor) { + os << " service pack " << v.nt_service_pack.major; + if(v.nt_service_pack.minor) { + os << '.' << v.nt_service_pack.minor; + } + } + + return os; +} + +} // namespace setup diff --git a/src/setup/windows.hpp b/src/setup/windows.hpp new file mode 100644 index 0000000..919cf8a --- /dev/null +++ b/src/setup/windows.hpp @@ -0,0 +1,81 @@ + +#ifndef INNOEXTRACT_SETUP_WINDOWS_HPP +#define INNOEXTRACT_SETUP_WINDOWS_HPP + +#include + +namespace setup { + +struct version; + +struct windows_version { + + struct data { + + unsigned major; + unsigned minor; + unsigned build; + + inline bool operator==(const data & o) const { + return (build == o.build && major == o.major && minor == o.minor); + } + + inline bool operator!=(const data & o) const { + return !(*this == o); + } + + void load(std::istream & is, const version & version); + + }; + + data win_version; + data nt_version; + + struct service_pack { + + unsigned major; + unsigned minor; + + inline bool operator==(const service_pack & o) const { + return (major == o.major && minor == o.minor); + } + + inline bool operator!=(const service_pack & o) const { + return !(*this == o); + } + + }; + + service_pack nt_service_pack; + + void load(std::istream & is, const version & version); + + inline bool operator==(const windows_version & o) const { + return (win_version == o.win_version + && nt_version == o.nt_version + && nt_service_pack == o.nt_service_pack); + } + + inline bool operator!=(const windows_version & o) const { + return !(*this == o); + } + + static const windows_version none; + +}; + +struct windows_version_range { + + windows_version begin; + windows_version end; + + void load(std::istream & is, const version & version); + +}; + +std::ostream & operator<<(std::ostream & os, const windows_version::data & svd); +std::ostream & operator<<(std::ostream & os, const windows_version & svd); + +} // namespace setup + +#endif // INNOEXTRACT_SETUP_WINDOWS_HPP diff --git a/src/stream/block.cpp b/src/stream/block.cpp index 8cfb155..0673c7b 100644 --- a/src/stream/block.cpp +++ b/src/stream/block.cpp @@ -124,11 +124,15 @@ private: NAMED_ENUM(stream::block_compression) -ENUM_NAMES(stream::block_compression, "Compression", "stored", "zlib", "lzma1") +NAMES(stream::block_compression, "Compression", + "stored", + "zlib", + "lzma1", +) namespace stream { -block_reader::pointer block_reader::get(std::istream & base, const inno_version & version) { +block_reader::pointer block_reader::get(std::istream & base, const setup::version & version) { (void)enum_names::name; diff --git a/src/stream/block.hpp b/src/stream/block.hpp index d671b66..4fa55e5 100644 --- a/src/stream/block.hpp +++ b/src/stream/block.hpp @@ -6,7 +6,7 @@ #include -struct inno_version; +namespace setup { struct version; } namespace stream { @@ -26,7 +26,7 @@ public: typedef std::istream type; typedef boost::shared_ptr pointer; - static pointer get(std::istream & base, const inno_version & version); + static pointer get(std::istream & base, const setup::version & version); }; diff --git a/src/stream/chunk.cpp b/src/stream/chunk.cpp index 367b396..c661469 100644 --- a/src/stream/chunk.cpp +++ b/src/stream/chunk.cpp @@ -18,11 +18,6 @@ namespace stream { static const char chunk_id[4] = { 'z', 'l', 'b', 0x1a }; -chunk::chunk(size_t first_slice, uint32_t offset, uint64_t size, - compression_method compression, bool encrypted) - : first_slice(first_slice), offset(offset), size(size), - compression(compression), encrypted(encrypted) { } - bool chunk::operator<(const chunk & o) const { if(first_slice != o.first_slice) { @@ -62,11 +57,11 @@ chunk_reader::pointer chunk_reader::get(slice_reader & base, const chunk & chunk pointer result = boost::make_shared(); switch(chunk.compression) { - case chunk::Stored: break; - case chunk::Zlib: result->push(io::zlib_decompressor(), 8192); break; - case chunk::BZip2: result->push(io::bzip2_decompressor(), 8192); break; - case chunk::LZMA1: result->push(inno_lzma1_decompressor(), 8192); break; - case chunk::LZMA2: result->push(inno_lzma2_decompressor(), 8192); break; + case Stored: break; + case Zlib: result->push(io::zlib_decompressor(), 8192); break; + case BZip2: result->push(io::bzip2_decompressor(), 8192); break; + case LZMA1: result->push(inno_lzma1_decompressor(), 8192); break; + case LZMA2: result->push(inno_lzma2_decompressor(), 8192); break; default: throw chunk_error("unknown compression"); } @@ -77,7 +72,7 @@ chunk_reader::pointer chunk_reader::get(slice_reader & base, const chunk & chunk } // namespace stream -ENUM_NAMES(stream::chunk::compression_method, "Compression Method", +NAMES(stream::compression_method, "Compression Method", "stored", "zlib", "bzip2", diff --git a/src/stream/chunk.hpp b/src/stream/chunk.hpp index bb2f9ec..816c0fe 100644 --- a/src/stream/chunk.hpp +++ b/src/stream/chunk.hpp @@ -21,18 +21,19 @@ struct chunk_error : public std::ios_base::failure { }; +enum compression_method { + Stored, + Zlib, + BZip2, + LZMA1, + LZMA2, + UnknownCompression +}; + struct chunk { - enum compression_method { - Stored, - Zlib, - BZip2, - LZMA1, - LZMA2, - Unknown - }; - size_t first_slice; //!< Slice where the chunk starts. + size_t last_slice; uint32_t offset; //!< Offset of the compressed chunk in firstSlice. uint64_t size; //! Total compressed size of the chunk. @@ -40,9 +41,6 @@ struct chunk { compression_method compression; bool encrypted; - chunk(size_t first_slice, uint32_t offset, uint64_t size, - compression_method compression, bool encrypted); - bool operator<(const chunk & o) const; bool operator==(const chunk & o) const; }; @@ -62,6 +60,6 @@ public: } // namespace stream -NAMED_ENUM(stream::chunk::compression_method) +NAMED_ENUM(stream::compression_method) #endif // INNOEXTRACT_STREAM_CHUNK_HPP diff --git a/src/stream/file.cpp b/src/stream/file.cpp index d77be46..fecb74e 100644 --- a/src/stream/file.cpp +++ b/src/stream/file.cpp @@ -5,8 +5,6 @@ #include #include -#include "setup/data.hpp" -#include "setup/version.hpp" #include "stream/checksum.hpp" #include "stream/exefilter.hpp" @@ -14,22 +12,43 @@ namespace io = boost::iostreams; namespace stream { -file_reader::pointer file_reader::get(base_type & base, const setup::data_entry & location, - const inno_version & version, crypto::checksum * checksum) { +bool file::operator<(const stream::file& o) const { + + if(offset != o.offset) { + return (offset < o.offset); + } else if(size != o.size) { + return (size < o.size); + } else if(filter != o.filter) { + return (filter < o.filter); + } + + return false; +} + +bool file::operator==(const file & o) const { + return (offset == o.offset + && size == o.size + && filter == o.filter); +} + + +file_reader::pointer file_reader::get(base_type & base, const file & file, + crypto::checksum * checksum) { boost::shared_ptr result = boost::make_shared(); - result->push(stream::checksum_filter(checksum, location.checksum.type), 8192); + if(checksum) { + result->push(stream::checksum_filter(checksum, file.checksum.type), 8192); + } - if(location.options & setup::data_entry::CallInstructionOptimized) { - if(version < INNO_VERSION(5, 2, 0)) { - result->push(inno_exe_decoder_4108(), 8192); - } else { - result->push(inno_exe_decoder_5200(version >= INNO_VERSION(5, 3, 9)), 8192); - } + switch(file.filter) { + case NoFilter: break; + case InstructionFilter4108: result->push(inno_exe_decoder_4108(), 8192); break; + case InstructionFilter5200: result->push(inno_exe_decoder_5200(false), 8192); break; + case InstructionFilter5309: result->push(inno_exe_decoder_5200(true), 8192); break; } - result->push(io::restrict(base, 0, int64_t(location.file_size))); + result->push(io::restrict(base, 0, int64_t(file.size))); return result; } diff --git a/src/stream/file.hpp b/src/stream/file.hpp index 3d0e87c..ce6c37a 100644 --- a/src/stream/file.hpp +++ b/src/stream/file.hpp @@ -7,12 +7,31 @@ #include #include -namespace crypto { struct checksum; } -namespace setup { struct data_entry; } -struct inno_version; +#include "crypto/checksum.hpp" namespace stream { +enum compression_filter { + NoFilter, + InstructionFilter4108, + InstructionFilter5200, + InstructionFilter5309, +}; + +struct file { + + uint64_t offset; //!< Offset of this file within the decompressed chunk. + uint64_t size; //!< Decompressed size of this file. + + crypto::checksum checksum; + + compression_filter filter; //!< Additional filter used before compression. + + bool operator<(const file & o) const; + bool operator==(const file & o) const; + +}; + class file_reader { typedef boost::iostreams::chain base_type; @@ -22,8 +41,7 @@ public: typedef std::istream type; typedef boost::shared_ptr pointer; - static pointer get(base_type & base, const setup::data_entry & location, - const inno_version & version, crypto::checksum * checksum_output); + static pointer get(base_type & base, const file & file, crypto::checksum * checksum_output); }; diff --git a/src/util/enum.hpp b/src/util/enum.hpp index 1dc7c27..55772d4 100644 --- a/src/util/enum.hpp +++ b/src/util/enum.hpp @@ -37,8 +37,12 @@ struct enum_names { static const char * names[]; \ static const size_t count; \ }; + +#define NAMED_FLAGS(Flags) \ + FLAGS_OVERLOADS(Flags) \ + NAMED_ENUM(Flags) -#define ENUM_NAMES(Enum, Name, ...) \ +#define NAMES(Enum, Name, ...) \ const char * enum_names::type>::name = (Name); \ const char * enum_names::type>::names[] = { __VA_ARGS__ }; \ const size_t enum_names::type>::count \