Browse Source

Cleanup setup header loading, implement version number parsing.

pull/1/head
Daniel Scharrer 15 years ago
parent
commit
eba41e0f51
  1. 26
      CMakeLists.txt
  2. 468
      src/InnoExtract.cpp
  3. 2
      src/crypto/checksum.cpp
  4. 4
      src/loader/offsets.cpp
  5. 59
      src/setup/IconEntry.hpp
  6. 37
      src/setup/IniEntry.hpp
  7. 67
      src/setup/LanguageEntry.cpp
  8. 40
      src/setup/LanguageEntry.hpp
  9. 12
      src/setup/PermissionEntry.cpp
  10. 20
      src/setup/PermissionEntry.hpp
  11. 57
      src/setup/RunEntry.hpp
  12. 83
      src/setup/SetupComponentEntry.cpp
  13. 51
      src/setup/SetupComponentEntry.hpp
  14. 664
      src/setup/SetupHeader.cpp
  15. 243
      src/setup/SetupHeader.hpp
  16. 32
      src/setup/SetupItem.hpp
  17. 47
      src/setup/SetupTaskEntry.hpp
  18. 60
      src/setup/SetupTypeEntry.cpp
  19. 52
      src/setup/SetupTypeEntry.hpp
  20. 128
      src/setup/WindowsVersion.cpp
  21. 67
      src/setup/WindowsVersion.hpp
  22. 87
      src/setup/component.cpp
  23. 54
      src/setup/component.hpp
  24. 57
      src/setup/data.cpp
  25. 24
      src/setup/data.hpp
  26. 5
      src/setup/delete.cpp
  27. 9
      src/setup/delete.hpp
  28. 5
      src/setup/directory.cpp
  29. 12
      src/setup/directory.hpp
  30. 9
      src/setup/file.cpp
  31. 13
      src/setup/file.hpp
  32. 655
      src/setup/header.cpp
  33. 238
      src/setup/header.hpp
  34. 43
      src/setup/icon.cpp
  35. 62
      src/setup/icon.hpp
  36. 25
      src/setup/ini.cpp
  37. 41
      src/setup/ini.hpp
  38. 20
      src/setup/item.cpp
  39. 38
      src/setup/item.hpp
  40. 67
      src/setup/language.cpp
  41. 44
      src/setup/language.hpp
  42. 9
      src/setup/message.cpp
  43. 16
      src/setup/message.hpp
  44. 16
      src/setup/permission.cpp
  45. 24
      src/setup/permission.hpp
  46. 61
      src/setup/registry.cpp
  47. 40
      src/setup/registry.hpp
  48. 39
      src/setup/run.cpp
  49. 60
      src/setup/run.hpp
  50. 18
      src/setup/task.cpp
  51. 50
      src/setup/task.hpp
  52. 75
      src/setup/type.cpp
  53. 49
      src/setup/type.hpp
  54. 205
      src/setup/version.cpp
  55. 88
      src/setup/version.hpp
  56. 145
      src/setup/windows.cpp
  57. 81
      src/setup/windows.hpp
  58. 8
      src/stream/block.cpp
  59. 4
      src/stream/block.hpp
  60. 17
      src/stream/chunk.cpp
  61. 24
      src/stream/chunk.hpp
  62. 43
      src/stream/file.cpp
  63. 28
      src/stream/file.hpp
  64. 6
      src/util/enum.hpp

26
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

468
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<setup::data_entry> & locations;
const setup::windows_version_range & def = header.winver;
explicit FileLocationComparer(const std::vector<setup::data_entry> & 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<const SetupItem &>(entry), header);
print(cout, static_cast<const setup::item &>(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<LanguageEntry> languages;
languages.resize(header.numLanguageEntries);
for(size_t i = 0; i < header.numLanguageEntries; i++) {
std::vector<setup::language_entry> 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<setup::file_entry> 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<setup::data_entry> 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<stream::chunk, std::vector<size_t> > Chunks;
typedef std::map<stream::file, size_t> Files;
typedef std::map<stream::chunk, Files> 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<stream::slice_reader> slice_reader;
@ -863,41 +845,39 @@ int main(int argc, char * argv[]) {
fs::path path(argv[1]);
slice_reader = boost::make_shared<stream::slice_reader>(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;
}
}
}

2
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",

4
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))) {

59
src/setup/IconEntry.hpp

@ -1,59 +0,0 @@
#ifndef INNOEXTRACT_SETUP_ICONENTRY_HPP
#define INNOEXTRACT_SETUP_ICONENTRY_HPP
#include <stdint.h>
#include <string>
#include <iosfwd>
#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

37
src/setup/IniEntry.hpp

@ -1,37 +0,0 @@
#ifndef INNOEXTRACT_SETUP_INIENTRY_HPP
#define INNOEXTRACT_SETUP_INIENTRY_HPP
#include <string>
#include <iosfwd>
#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

67
src/setup/LanguageEntry.cpp

@ -1,67 +0,0 @@
#include "setup/LanguageEntry.hpp"
#include <sstream>
#include <iconv.h>
#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<uint32_t>(is);
if(version >= INNO_VERSION(4, 2, 2) && (version < INNO_VERSION(5, 3, 0) || !version.unicode)) {
codepage = load_number<uint32_t>(is);
} else {
codepage = 0;
}
if(!codepage) {
codepage = version.codepage();
}
dialogFontSize = load_number<uint32_t>(is);
if(version < INNO_VERSION(4, 1, 0)) {
dialogFontStandardHeight = load_number<uint32_t>(is);
} else {
dialogFontStandardHeight = 0;
}
titleFontSize = load_number<uint32_t>(is);
welcomeFontSize = load_number<uint32_t>(is);
copyrightFontSize = load_number<uint32_t>(is);
if(version >= INNO_VERSION(5, 2, 3)) {
rightToLeft = ::load<uint8_t>(is);
} else {
rightToLeft = false;
}
}

40
src/setup/LanguageEntry.hpp

@ -1,40 +0,0 @@
#ifndef INNOEXTRACT_SETUP_LANGUAGEENTRY_HPP
#define INNOEXTRACT_SETUP_LANGUAGEENTRY_HPP
#include <stdint.h>
#include <string>
#include <iosfwd>
#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

12
src/setup/PermissionEntry.cpp

@ -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
}

20
src/setup/PermissionEntry.hpp

@ -1,20 +0,0 @@
#ifndef INNOEXTRACT_SETUP_PERMISSIONENTRY_HPP
#define INNOEXTRACT_SETUP_PERMISSIONENTRY_HPP
#include <string>
#include <iosfwd>
#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

57
src/setup/RunEntry.hpp

@ -1,57 +0,0 @@
#ifndef INNOEXTRACT_SETUP_RUNENTRY_HPP
#define INNOEXTRACT_SETUP_RUNENTRY_HPP
#include <string>
#include <iosfwd>
#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

83
src/setup/SetupComponentEntry.cpp

@ -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<uint64_t>(is);
} else {
extraDiskSpaceRequired = load_number<uint32_t>(is);
}
if(version >= INNO_VERSION(3, 0, 8)) {
level = load_number<int32_t>(is);
used = load_number<uint8_t>(is);
} else {
level = 0, used = true;
}
minVersion.load(is, version);
onlyBelowVersion.load(is, version);
if(version >= INNO_VERSION(4, 2, 3)) {
options = stored_flags<StoredSetupComponentOptions2>(is).get();
} else if(version >= INNO_VERSION(3, 0, 8)) {
options = stored_flags<StoredSetupComponentOptions1>(is).get();
} else {
options = stored_flags<StoredSetupComponentOptions0>(is).get();
}
size = (version >= INNO_VERSION(4, 0, 0)) ? load_number<uint64_t>(is) : load_number<uint32_t>(is);
}
ENUM_NAMES(SetupComponentEntry::Options, "Setup Component Option",
"fixed",
"restart",
"disable no uninstall warning",
"exclusive",
"don't inherit check",
)

51
src/setup/SetupComponentEntry.hpp

@ -1,51 +0,0 @@
#ifndef INNOEXTRACT_SETUP_SETUPCOMPONENTENTRY_HPP
#define INNOEXTRACT_SETUP_SETUPCOMPONENTENTRY_HPP
#include <stdint.h>
#include <string>
#include <iosfwd>
#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

664
src/setup/SetupHeader.cpp

@ -1,664 +0,0 @@
#include "SetupHeader.hpp"
#include <cstdio>
#include <cstring>
#include <boost/static_assert.hpp>
#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<uint32_t>(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<uint32_t>(is);
} else if(version >= INNO_VERSION(2, 0, 1)) {
numLanguageEntries = 1;
} else {
numLanguageEntries = 0;
}
if(version >= INNO_VERSION(4, 2, 1)) {
numCustomMessageEntries = load_number<uint32_t>(is);
} else {
numCustomMessageEntries = 0;
}
if(version >= INNO_VERSION(4, 1, 0)) {
numPermissionEntries = load_number<uint32_t>(is);
} else {
numPermissionEntries = 0;
}
if(version >= INNO_VERSION(2, 0, 0)) {
numTypeEntries = load_number<uint32_t>(is);
numComponentEntries = load_number<uint32_t>(is);
numTaskEntries = load_number<uint32_t>(is);
} else {
numTypeEntries = 0, numComponentEntries = 0, numTaskEntries = 0;
}
numDirectoryEntries = load_number<uint32_t>(is, version.bits);
numFileEntries = load_number<uint32_t>(is, version.bits);
numFileLocationEntries = load_number<uint32_t>(is, version.bits);
numIconEntries = load_number<uint32_t>(is, version.bits);
numIniEntries = load_number<uint32_t>(is, version.bits);
numRegistryEntries = load_number<uint32_t>(is, version.bits);
numDeleteEntries = load_number<uint32_t>(is, version.bits);
numUninstallDeleteEntries = load_number<uint32_t>(is, version.bits);
numRunEntries = load_number<uint32_t>(is, version.bits);
numUninstallRunEntries = load_number<uint32_t>(is, version.bits);
int32_t licenseSize;
int32_t infoBeforeSize;
int32_t infoAfterSize;
if(version < INNO_VERSION(1, 3, 21)) {
licenseSize = load_number<int32_t>(is, version.bits);
infoBeforeSize = load_number<int32_t>(is, version.bits);
infoAfterSize = load_number<int32_t>(is, version.bits);
}
minVersion.load(is, version);
onlyBelowVersion.load(is, version);
backColor = load_number<uint32_t>(is);
if(version >= INNO_VERSION(1, 3, 21)) {
backColor2 = load_number<uint32_t>(is);
} else {
backColor2 = 0;
}
wizardImageBackColor = load_number<uint32_t>(is);
if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) {
wizardSmallImageBackColor = load_number<uint32_t>(is);
} else {
wizardSmallImageBackColor = 0;
}
if(version < INNO_VERSION(4, 2, 0)) {
password.crc32 = load_number<uint32_t>(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<int32_t>(is);
slicesPerDisk = 1;
} else {
extraDiskSpaceRequired = load_number<int64_t>(is);
slicesPerDisk = load_number<uint32_t>(is);
}
if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) {
installMode = stored_enum<StoredInstallMode>(is).get();
} else {
installMode = NormalInstallMode;
}
if(version >= INNO_VERSION(1, 3, 21)) {
uninstallLogMode = stored_enum<StoredUninstallLogMode>(is).get();
} else {
uninstallLogMode = AppendLog;
}
if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) {
uninstallStyle = stored_enum<StoredUninstallStyle>(is).get();
} else {
uninstallStyle = (version < INNO_VERSION(5, 0, 0)) ? ClassicStyle : ModernStyle;
}
if(version >= INNO_VERSION(1, 3, 21)) {
dirExistsWarning = stored_enum<StoredDirExistsWarning>(is).get();
} else {
dirExistsWarning = Auto;
}
if(version >= INNO_VERSION(3, 0, 0) && version < INNO_VERSION(3, 0, 3)) {
AutoBoolean val = stored_enum<StoredRestartComputer>(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<StoredPrivileges1>(is).get();
} else if(version >= INNO_VERSION(3, 0, 4)) {
privilegesRequired = stored_enum<StoredPrivileges0>(is).get();
}
if(version >= INNO_VERSION(4, 0, 10)) {
showLanguageDialog = stored_enum<StoredShowLanguageDialog>(is).get();
languageDetectionMethod = stored_enum<StoredLanguageDetectionMethod>(is).get();
}
if(version >= INNO_VERSION(5, 3, 9)) {
compressMethod = stored_enum<StoredCompressionMethod3>(is).get();
} else if(version >= INNO_VERSION(4, 2, 6)) {
compressMethod = stored_enum<StoredCompressionMethod2>(is).get();
} else if(version >= INNO_VERSION(4, 2, 5)) {
compressMethod = stored_enum<StoredCompressionMethod1>(is).get();
} else if(version >= INNO_VERSION(4, 1, 5)) {
compressMethod = stored_enum<StoredCompressionMethod0>(is).get();
}
if(version >= INNO_VERSION(5, 1, 0)) {
architecturesAllowed = stored_flags<StoredArchitectures>(is).get();
architecturesInstallIn64BitMode = stored_flags<StoredArchitectures>(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<uint32_t>(is);
signedUninstallerHdrChecksum = load_number<uint32_t>(is);
} else {
signedUninstallerOrigSize = signedUninstallerHdrChecksum = 0;
}
if(version >= INNO_VERSION(5, 3, 3)) {
disableDirPage = stored_enum<StoredDisablePage>(is).get();
disableProgramGroupPage = stored_enum<StoredDisablePage>(is).get();
}
if(version >= INNO_VERSION(5, 3, 6)) {
uninstallDisplaySize = load_number<uint32_t>(is);
} else {
uninstallDisplaySize = 0;
}
stored_flag_reader<Options> 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<SetupHeader::Options::Enum>::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",
)

243
src/setup/SetupHeader.hpp

@ -1,243 +0,0 @@
#ifndef INNOEXTRACT_SETUP_SETUPHEADER_HPP
#define INNOEXTRACT_SETUP_SETUPHEADER_HPP
#include <stdint.h>
#include <stddef.h>
#include <bitset>
#include <string>
#include <iosfwd>
#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

32
src/setup/SetupItem.hpp

@ -1,32 +0,0 @@
#ifndef INNOEXTRACT_SETUP_SETUPCONDITION_HPP
#define INNOEXTRACT_SETUP_SETUPCONDITION_HPP
#include <string>
#include <iosfwd>
#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

47
src/setup/SetupTaskEntry.hpp

@ -1,47 +0,0 @@
#ifndef INNOEXTRACT_SETUP_SETUPTASKENTRY_HPP
#define INNOEXTRACT_SETUP_SETUPTASKENTRY_HPP
#include <string>
#include <iosfwd>
#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

60
src/setup/SetupTypeEntry.cpp

@ -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<StoredSetupTypeOptions>(is).get();
if(version >= INNO_VERSION(4, 0, 3)) {
type = stored_enum<StoredSetupType>(is).get();
} else {
type = User;
}
size = (version >= INNO_VERSION(4, 0, 0)) ? load_number<uint64_t>(is) : load_number<uint32_t>(is);
}
ENUM_NAMES(SetupTypeEntry::Options, "Setyp Type Option",
"is custom",
)
ENUM_NAMES(SetupTypeEntry::Type, "Setyp Type",
"user",
"default full",
"default compact",
"default custom",
)

52
src/setup/SetupTypeEntry.hpp

@ -1,52 +0,0 @@
#ifndef INNOEXTRACT_SETUP_SETUPTYPEENTRY_HPP
#define INNOEXTRACT_SETUP_SETUPTYPEENTRY_HPP
#include <stdint.h>
#include <string>
#include <iosfwd>
#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

128
src/setup/WindowsVersion.cpp

@ -1,128 +0,0 @@
#include "setup/WindowsVersion.hpp"
#include <stdint.h>
#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<uint16_t>(is);
} else {
build = 0;
}
minor = load_number<uint8_t>(is);
major = load_number<uint8_t>(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<uint8_t>(is);
ntServicePack.major = load_number<uint8_t>(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;
}

67
src/setup/WindowsVersion.hpp

@ -1,67 +0,0 @@
#ifndef INNOEXTRACT_SETUP_WINDOWSVERSION_HPP
#define INNOEXTRACT_SETUP_WINDOWSVERSION_HPP
#include <ostream>
#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

87
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<uint64_t>(is);
} else {
extra_disk_pace_required = load_number<uint32_t>(is);
}
if(version >= INNO_VERSION(3, 0, 8)) {
level = load_number<int32_t>(is);
used = load_number<uint8_t>(is);
} else {
level = 0, used = true;
}
winver.load(is, version);
if(version >= INNO_VERSION(4, 2, 3)) {
options = stored_flags<stored_component_flags_2>(is).get();
} else if(version >= INNO_VERSION(3, 0, 8)) {
options = stored_flags<stored_component_flags_1>(is).get();
} else {
options = stored_flags<stored_component_flags_0>(is).get();
}
size = (version >= INNO_VERSION(4, 0, 0)) ? load_number<uint64_t>(is) : load_number<uint32_t>(is);
}
} // namespace setup
NAMES(setup::component_entry::flags, "Setup Component Option",
"fixed",
"restart",
"disable no uninstall warning",
"exclusive",
"don't inherit check",
)

54
src/setup/component.hpp

@ -0,0 +1,54 @@
#ifndef INNOEXTRACT_SETUP_COMPONENT_HPP
#define INNOEXTRACT_SETUP_COMPONENT_HPP
#include <stdint.h>
#include <string>
#include <iosfwd>
#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

57
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<uint32_t>(is, version.bits);
last_slice = load_number<uint32_t>(is, version.bits);
chunk.first_slice = load_number<uint32_t>(is, version.bits);
chunk.last_slice = load_number<uint32_t>(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<uint32_t>(is);
chunk.offset = load_number<uint32_t>(is);
if(version >= INNO_VERSION(4, 0, 1)) {
file_offset = load_number<uint64_t>(is);
file.offset = load_number<uint64_t>(is);
} else {
file_offset = 0;
file.offset = 0;
}
if(version >= INNO_VERSION(4, 0, 0)) {
file_size = load_number<uint64_t>(is);
chunk_size = load_number<uint64_t>(is);
file.size = load_number<uint64_t>(is);
chunk.size = load_number<uint64_t>(is);
} else {
file_size = load_number<uint32_t>(is);
chunk_size = load_number<uint32_t>(is);
file.size = load_number<uint32_t>(is);
chunk.size = load_number<uint32_t>(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<uint32_t>(is), checksum.type = crypto::CRC32;
file.checksum.crc32 = load_number<uint32_t>(is), file.checksum.type = crypto::CRC32;
} else {
checksum.adler32 = load_number<uint32_t>(is), checksum.type = crypto::Adler32;
file.checksum.adler32 = load_number<uint32_t>(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",

24
src/setup/data.hpp

@ -8,14 +8,16 @@
#include <iosfwd>
#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

5
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<uint32_t>(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",

9
src/setup/delete.hpp

@ -5,13 +5,14 @@
#include <string>
#include <iosfwd>
#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);
};

5
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<uint32_t>(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",

12
src/setup/directory.hpp

@ -6,14 +6,15 @@
#include <string>
#include <iosfwd>
#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

9
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<file_copy_mode>::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",

13
src/setup/file.hpp

@ -6,14 +6,15 @@
#include <string>
#include <iosfwd>
#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

655
src/setup/header.cpp

@ -0,0 +1,655 @@
#include "setup/header.hpp"
#include <cstdio>
#include <cstring>
#include <boost/static_assert.hpp>
#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<uint32_t>(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<uint32_t>(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<uint32_t>(is);
} else {
message_count = 0;
}
if(version >= INNO_VERSION(4, 1, 0)) {
permission_count = load_number<uint32_t>(is);
} else {
permission_count = 0;
}
if(version >= INNO_VERSION(2, 0, 0)) {
type_count = load_number<uint32_t>(is);
component_count = load_number<uint32_t>(is);
task_count = load_number<uint32_t>(is);
} else {
type_count = 0, component_count = 0, task_count = 0;
}
directory_count = load_number<uint32_t>(is, version.bits);
file_count = load_number<uint32_t>(is, version.bits);
data_entry_count = load_number<uint32_t>(is, version.bits);
icon_count = load_number<uint32_t>(is, version.bits);
ini_entry_count = load_number<uint32_t>(is, version.bits);
registry_entry_count = load_number<uint32_t>(is, version.bits);
delete_entry_count = load_number<uint32_t>(is, version.bits);
uninstall_delete_entry_count = load_number<uint32_t>(is, version.bits);
run_entry_count = load_number<uint32_t>(is, version.bits);
uninstall_run_entry_count = load_number<uint32_t>(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<int32_t>(is, version.bits);
info_before_size = load_number<int32_t>(is, version.bits);
info_after_size = load_number<int32_t>(is, version.bits);
}
winver.load(is, version);
back_color = load_number<uint32_t>(is);
if(version >= INNO_VERSION(1, 3, 21)) {
back_color2 = load_number<uint32_t>(is);
} else {
back_color2 = 0;
}
image_back_color = load_number<uint32_t>(is);
if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 4)) {
small_image_back_color = load_number<uint32_t>(is);
} else {
small_image_back_color = 0;
}
if(version < INNO_VERSION(4, 2, 0)) {
password.crc32 = load_number<uint32_t>(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<int32_t>(is);
slices_per_disk = 1;
} else {
extra_disk_space_required = load_number<int64_t>(is);
slices_per_disk = load_number<uint32_t>(is);
}
if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) {
install_mode = stored_enum<stored_install_verbosity>(is).get();
} else {
install_mode = NormalInstallMode;
}
if(version >= INNO_VERSION(1, 3, 21)) {
uninstall_log_mode = stored_enum<stored_log_mode>(is).get();
} else {
uninstall_log_mode = AppendLog;
}
if(version >= INNO_VERSION(2, 0, 0) && version < INNO_VERSION(5, 0, 0)) {
uninstall_style = stored_enum<stored_setup_style>(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<stored_bool_auto_no_yes>(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<stored_bool_auto_no_yes>(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<stored_privileges_1>(is).get();
} else if(version >= INNO_VERSION(3, 0, 4)) {
privileges_required = stored_enum<stored_privileges_0>(is).get();
}
if(version >= INNO_VERSION(4, 0, 10)) {
show_language_dialog = stored_enum<stored_bool_yes_no_auto>(is).get();
language_detection = stored_enum<stored_language_detection_method>(is).get();
}
if(version >= INNO_VERSION(5, 3, 9)) {
compression = stored_enum<stored_compression_method_3>(is).get();
} else if(version >= INNO_VERSION(4, 2, 6)) {
compression = stored_enum<stored_compression_method_2>(is).get();
} else if(version >= INNO_VERSION(4, 2, 5)) {
compression = stored_enum<stored_compression_method_1>(is).get();
} else if(version >= INNO_VERSION(4, 1, 5)) {
compression = stored_enum<stored_compression_method_0>(is).get();
}
if(version >= INNO_VERSION(5, 1, 0)) {
architectures_allowed = stored_flags<stored_architectures>(is).get();
architectures_installed_in_64bit_mode = stored_flags<stored_architectures>(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<uint32_t>(is);
signed_uninstaller_header_checksum = load_number<uint32_t>(is);
} else {
signed_uninstaller_original_size = signed_uninstaller_header_checksum = 0;
}
if(version >= INNO_VERSION(5, 3, 3)) {
disable_dir_page = stored_enum<stored_bool_auto_no_yes>(is).get();
disable_program_group_page = stored_enum<stored_bool_auto_no_yes>(is).get();
}
if(version >= INNO_VERSION(5, 3, 6)) {
uninstall_display_size = load_number<uint32_t>(is);
} else {
uninstall_display_size = 0;
}
stored_flag_reader<flags> 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",
)

238
src/setup/header.hpp

@ -0,0 +1,238 @@
#ifndef INNOEXTRACT_SETUP_HEADER_HPP
#define INNOEXTRACT_SETUP_HEADER_HPP
#include <stdint.h>
#include <stddef.h>
#include <bitset>
#include <string>
#include <iosfwd>
#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

43
src/setup/IconEntry.cpp → 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<uint32_t>(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<int32_t>(is, version.bits);
icon_index = load_number<int32_t>(is, version.bits);
if(version >= INNO_VERSION(1, 3, 21)) {
showCmd = load_number<int32_t>(is);
closeOnExit = stored_enum<StoredCloseOnExit>(is).get();
show_command = load_number<int32_t>(is);
close_on_exit = stored_enum<stored_close_setting>(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<Options> flags(is);
stored_flag_reader<flags> 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",
)

62
src/setup/icon.hpp

@ -0,0 +1,62 @@
#ifndef INNOEXTRACT_SETUP_ICON_HPP
#define INNOEXTRACT_SETUP_ICON_HPP
#include <stdint.h>
#include <string>
#include <iosfwd>
#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

25
src/setup/IniEntry.cpp → src/setup/ini.cpp

@ -1,24 +1,27 @@
#include "setup/IniEntry.hpp"
#include "setup/ini.hpp"
#include <stdint.h>
#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<uint32_t>(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<StoredIniOptions>(is).get();
options = stored_flags<stored_ini_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",

41
src/setup/ini.hpp

@ -0,0 +1,41 @@
#ifndef INNOEXTRACT_SETUP_INI_HPP
#define INNOEXTRACT_SETUP_INI_HPP
#include <string>
#include <iosfwd>
#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

20
src/setup/SetupItem.cpp → 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

38
src/setup/item.hpp

@ -0,0 +1,38 @@
#ifndef INNOEXTRACT_SETUP_ITEM_HPP
#define INNOEXTRACT_SETUP_ITEM_HPP
#include <string>
#include <iosfwd>
#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

67
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<uint32_t>(is);
if(version >= INNO_VERSION(4, 2, 2) && (version < INNO_VERSION(5, 3, 0) || !version.unicode)) {
codepage = load_number<uint32_t>(is);
} else {
codepage = 0;
}
if(!codepage) {
codepage = version.codepage();
}
dialog_font_size = load_number<uint32_t>(is);
if(version < INNO_VERSION(4, 1, 0)) {
dialog_font_standard_height = load_number<uint32_t>(is);
} else {
dialog_font_standard_height = 0;
}
title_font_size = load_number<uint32_t>(is);
welcome_font_size = load_number<uint32_t>(is);
copyright_font_size = load_number<uint32_t>(is);
if(version >= INNO_VERSION(5, 2, 3)) {
right_to_left = ::load<uint8_t>(is);
} else {
right_to_left = false;
}
}
} // namespace setup

44
src/setup/language.hpp

@ -0,0 +1,44 @@
#ifndef INNOEXTRACT_SETUP_LANGUAGE_HPP
#define INNOEXTRACT_SETUP_LANGUAGE_HPP
#include <stdint.h>
#include <string>
#include <iosfwd>
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

9
src/setup/MessageEntry.cpp → src/setup/message.cpp

@ -1,11 +1,14 @@
#include "setup/MessageEntry.hpp"
#include "setup/message.hpp"
#include <stdint.h>
#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<int32_t>(is);
}
} // namespace setup

16
src/setup/MessageEntry.hpp → 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 <string>
#include <iosfwd>
#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

16
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

24
src/setup/permission.hpp

@ -0,0 +1,24 @@
#ifndef INNOEXTRACT_SETUP_PERMISSION_HPP
#define INNOEXTRACT_SETUP_PERMISSION_HPP
#include <string>
#include <iosfwd>
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

61
src/setup/RegistryEntry.cpp → src/setup/registry.cpp

@ -1,42 +1,45 @@
#include "setup/RegistryEntry.hpp"
#include "setup/registry.hpp"
#include <stdint.h>
#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<uint32_t>(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<uint32_t>(is) & ~0x80000000);
hive = hive_name(load_number<uint32_t>(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<StoredRegistryEntryType2>(is).get();
type = stored_enum<stored_registry_entry_type_2>(is).get();
} else if(version.bits != 16) {
type = stored_enum<StoredRegistryEntryType1>(is).get();
type = stored_enum<stored_registry_entry_type_1>(is).get();
} else {
type = stored_enum<StoredRegistryEntryType0>(is).get();
type = stored_enum<stored_registry_entry_type_0>(is).get();
}
stored_flag_reader<Options> flags(is);
stored_flag_reader<flags> 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",

40
src/setup/RegistryEntry.hpp → 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 <string>
#include <iosfwd>
#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

39
src/setup/RunEntry.cpp → src/setup/run.cpp

@ -1,22 +1,25 @@
#include "setup/RunEntry.hpp"
#include "setup/run.hpp"
#include <stdint.h>
#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<uint32_t>(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<int32_t>(is);
show_command = load_number<int32_t>(is);
} else {
showCmd = 0;
show_command = 0;
}
wait = stored_enum<StoredRunWait>(is).get();
wait = stored_enum<stored_run_wait_condition>(is).get();
stored_flag_reader<Options> flags(is);
stored_flag_reader<flags> 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",

60
src/setup/run.hpp

@ -0,0 +1,60 @@
#ifndef INNOEXTRACT_SETUP_RUN_HPP
#define INNOEXTRACT_SETUP_RUN_HPP
#include <string>
#include <iosfwd>
#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

18
src/setup/SetupTaskEntry.cpp → src/setup/task.cpp

@ -1,16 +1,19 @@
#include "setup/SetupTaskEntry.hpp"
#include "setup/task.hpp"
#include <stdint.h>
#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<Options> flags(is);
stored_flag_reader<flags> 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",

50
src/setup/task.hpp

@ -0,0 +1,50 @@
#ifndef INNOEXTRACT_SETUP_TASK_HPP
#define INNOEXTRACT_SETUP_TASK_HPP
#include <string>
#include <iosfwd>
#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

75
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<stored_type_flags>(is).get();
custom_type = (options & CustomSetupType);
if(version >= INNO_VERSION(4, 0, 3)) {
type = stored_enum<stored_setup_type>(is).get();
} else {
type = User;
}
size = (version >= INNO_VERSION(4, 0, 0)) ? load_number<uint64_t>(is) : load_number<uint32_t>(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",
)

49
src/setup/type.hpp

@ -0,0 +1,49 @@
#ifndef INNOEXTRACT_SETUP_TYPE_HPP
#define INNOEXTRACT_SETUP_TYPE_HPP
#include <stdint.h>
#include <string>
#include <iosfwd>
#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

205
src/setup/version.cpp

@ -3,45 +3,53 @@
#include <cstring>
#include <algorithm>
#include <iostream>
#include <istream>
#include <ostream>
#include <boost/static_assert.hpp>
#include <boost/lexical_cast.hpp>
#include <util/util.hpp>
#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<unsigned>(version_str.substr(1, 1));
unsigned b = boost::lexical_cast<unsigned>(version_str.substr(3, 1));
unsigned c = boost::lexical_cast<unsigned>(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<unsigned>(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<unsigned>(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<unsigned>(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<unsigned>(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

88
src/setup/version.hpp

@ -4,16 +4,24 @@
#include <stdint.h>
#include <iosfwd>
#include <exception>
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

145
src/setup/windows.cpp

@ -0,0 +1,145 @@
#include "setup/windows.hpp"
#include <stdint.h>
#include <ostream>
#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<uint16_t>(is);
} else {
build = 0;
}
minor = load_number<uint8_t>(is);
major = load_number<uint8_t>(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<uint8_t>(is);
nt_service_pack.major = load_number<uint8_t>(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

81
src/setup/windows.hpp

@ -0,0 +1,81 @@
#ifndef INNOEXTRACT_SETUP_WINDOWS_HPP
#define INNOEXTRACT_SETUP_WINDOWS_HPP
#include <iosfwd>
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

8
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<block_compression>::name;

4
src/stream/block.hpp

@ -6,7 +6,7 @@
#include <boost/shared_ptr.hpp>
struct inno_version;
namespace setup { struct version; }
namespace stream {
@ -26,7 +26,7 @@ public:
typedef std::istream type;
typedef boost::shared_ptr<type> pointer;
static pointer get(std::istream & base, const inno_version & version);
static pointer get(std::istream & base, const setup::version & version);
};

17
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<type>();
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",

24
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

43
src/stream/file.cpp

@ -5,8 +5,6 @@
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/restrict.hpp>
#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<io::filtering_istream> result = boost::make_shared<io::filtering_istream>();
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;
}

28
src/stream/file.hpp

@ -7,12 +7,31 @@
#include <boost/shared_ptr.hpp>
#include <boost/iostreams/chain.hpp>
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<boost::iostreams::input> base_type;
@ -22,8 +41,7 @@ public:
typedef std::istream type;
typedef boost::shared_ptr<type> 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);
};

6
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<get_enum<Enum>::type>::name = (Name); \
const char * enum_names<get_enum<Enum>::type>::names[] = { __VA_ARGS__ }; \
const size_t enum_names<get_enum<Enum>::type>::count \

Loading…
Cancel
Save