use std::collections::{HashMap, HashSet};
use crate::{
error::Error,
records::windows::WindowsVersionRange,
util::{
encoding::{read_ansi_bytes, read_setup_string},
read::Reader,
},
version::Version,
};
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[non_exhaustive]
pub enum HeaderString {
AppName,
AppVerName,
AppId,
AppCopyright,
AppPublisher,
AppPublisherUrl,
AppSupportPhone,
AppSupportUrl,
AppUpdatesUrl,
AppVersion,
DefaultDirName,
DefaultGroupName,
BaseFilename,
UninstallFilesDir,
UninstallDisplayName,
UninstallDisplayIcon,
AppMutex,
DefaultUserInfoName,
DefaultUserInfoOrg,
DefaultUserInfoSerial,
AppReadmeFile,
AppContact,
AppComments,
AppModifyPath,
CreateUninstallRegKey,
Uninstallable,
CloseApplicationsFilter,
SetupMutex,
ChangesEnvironment,
ChangesAssociations,
ArchitecturesAllowed,
ArchitecturesInstallIn64BitMode,
CloseApplicationsFilterExcludes,
SevenZipLibraryName,
UsePreviousAppDir,
UsePreviousGroup,
UsePreviousSetupType,
UsePreviousTasks,
UsePreviousUserInfo,
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[non_exhaustive]
pub enum HeaderAnsi {
LicenseText,
InfoBeforeText,
InfoAfterText,
CompiledCodeText,
}
#[derive(Clone, Copy, Debug, Default)]
pub struct EntryCounts {
pub languages: u32,
pub custom_messages: u32,
pub permissions: u32,
pub types: u32,
pub components: u32,
pub tasks: u32,
pub directories: u32,
pub iss_sig_keys: Option<u32>,
pub files: u32,
pub file_locations: u32,
pub icons: u32,
pub ini_entries: u32,
pub registry: u32,
pub install_deletes: u32,
pub uninstall_deletes: u32,
pub run: u32,
pub uninstall_run: u32,
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[non_exhaustive]
#[allow(missing_docs)] pub enum HeaderOption {
DisableStartupPrompt,
CreateAppDir,
AllowNoIcons,
AlwaysRestart,
AlwaysUsePersonalGroup,
WindowVisible,
WindowShowCaption,
WindowResizable,
WindowStartMaximized,
EnableDirDoesntExistWarning,
Password,
AllowRootDirectory,
DisableFinishedPage,
UsePreviousAppDir,
BackColorHorizontal,
UsePreviousGroup,
UpdateUninstallLogAppName,
UsePreviousSetupType,
DisableReadyMemo,
AlwaysShowComponentsList,
FlatComponentsList,
ShowComponentSizes,
UsePreviousTasks,
DisableReadyPage,
AlwaysShowDirOnReadyPage,
AlwaysShowGroupOnReadyPage,
AllowUNCPath,
UserInfoPage,
UsePreviousUserInfo,
UninstallRestartComputer,
RestartIfNeededByRun,
ShowTasksTreeLines,
AllowCancelDuringInstall,
WizardImageStretch,
AppendDefaultDirName,
AppendDefaultGroupName,
EncryptionUsed,
SetupLogging,
SignedUninstaller,
UsePreviousLanguage,
DisableWelcomePage,
CloseApplications,
RestartApplications,
AllowNetworkDrive,
ForceCloseApplications,
AppNameHasConsts,
UsePreviousPrivileges,
WizardResizable,
UninstallLogging,
}
stable_flag_enum!(HeaderOption, {
DisableStartupPrompt => "disable_startup_prompt",
CreateAppDir => "create_app_dir",
AllowNoIcons => "allow_no_icons",
AlwaysRestart => "always_restart",
AlwaysUsePersonalGroup => "always_use_personal_group",
WindowVisible => "window_visible",
WindowShowCaption => "window_show_caption",
WindowResizable => "window_resizable",
WindowStartMaximized => "window_start_maximized",
EnableDirDoesntExistWarning => "enable_dir_doesnt_exist_warning",
Password => "password",
AllowRootDirectory => "allow_root_directory",
DisableFinishedPage => "disable_finished_page",
UsePreviousAppDir => "use_previous_app_dir",
BackColorHorizontal => "back_color_horizontal",
UsePreviousGroup => "use_previous_group",
UpdateUninstallLogAppName => "update_uninstall_log_app_name",
UsePreviousSetupType => "use_previous_setup_type",
DisableReadyMemo => "disable_ready_memo",
AlwaysShowComponentsList => "always_show_components_list",
FlatComponentsList => "flat_components_list",
ShowComponentSizes => "show_component_sizes",
UsePreviousTasks => "use_previous_tasks",
DisableReadyPage => "disable_ready_page",
AlwaysShowDirOnReadyPage => "always_show_dir_on_ready_page",
AlwaysShowGroupOnReadyPage => "always_show_group_on_ready_page",
AllowUNCPath => "allow_unc_path",
UserInfoPage => "user_info_page",
UsePreviousUserInfo => "use_previous_user_info",
UninstallRestartComputer => "uninstall_restart_computer",
RestartIfNeededByRun => "restart_if_needed_by_run",
ShowTasksTreeLines => "show_tasks_tree_lines",
AllowCancelDuringInstall => "allow_cancel_during_install",
WizardImageStretch => "wizard_image_stretch",
AppendDefaultDirName => "append_default_dir_name",
AppendDefaultGroupName => "append_default_group_name",
EncryptionUsed => "encryption_used",
SetupLogging => "setup_logging",
SignedUninstaller => "signed_uninstaller",
UsePreviousLanguage => "use_previous_language",
DisableWelcomePage => "disable_welcome_page",
CloseApplications => "close_applications",
RestartApplications => "restart_applications",
AllowNetworkDrive => "allow_network_drive",
ForceCloseApplications => "force_close_applications",
AppNameHasConsts => "app_name_has_consts",
UsePreviousPrivileges => "use_previous_privileges",
WizardResizable => "wizard_resizable",
UninstallLogging => "uninstall_logging",
});
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum WizardStyle {
Classic,
Modern,
}
stable_name_enum!(WizardStyle, { Self::Classic => "classic", Self::Modern => "modern" });
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum ImageAlphaFormat {
Ignored,
Defined,
Premultiplied,
}
stable_name_enum!(ImageAlphaFormat, {
Self::Ignored => "ignored",
Self::Defined => "defined",
Self::Premultiplied => "premultiplied",
});
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum UninstallLogMode {
Append,
New,
Overwrite,
}
stable_name_enum!(UninstallLogMode, {
Self::Append => "append",
Self::New => "new",
Self::Overwrite => "overwrite",
});
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum AutoNoYes {
Auto,
No,
Yes,
}
stable_name_enum!(AutoNoYes, { Self::Auto => "auto", Self::No => "no", Self::Yes => "yes" });
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum YesNoAuto {
Yes,
No,
Auto,
}
stable_name_enum!(YesNoAuto, { Self::Yes => "yes", Self::No => "no", Self::Auto => "auto" });
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum PrivilegesRequired {
None,
PowerUser,
Admin,
Lowest,
}
stable_name_enum!(PrivilegesRequired, {
Self::None => "none",
Self::PowerUser => "power_user",
Self::Admin => "admin",
Self::Lowest => "lowest",
});
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum LanguageDetectionMethod {
UiLanguage,
Locale,
None,
}
stable_name_enum!(LanguageDetectionMethod, {
Self::UiLanguage => "ui_language",
Self::Locale => "locale",
Self::None => "none",
});
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum CompressMethod {
Stored,
Zlib,
Bzip2,
Lzma1,
Lzma2,
}
stable_name_enum!(CompressMethod, {
Self::Stored => "stored",
Self::Zlib => "zlib",
Self::Bzip2 => "bzip2",
Self::Lzma1 => "lzma1",
Self::Lzma2 => "lzma2",
});
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum Architecture {
Unknown,
X86,
Amd64,
IA64,
Arm32,
Arm64,
}
stable_name_enum!(Architecture, {
Self::Unknown => "unknown",
Self::X86 => "x86",
Self::Amd64 => "amd64",
Self::IA64 => "ia64",
Self::Arm32 => "arm32",
Self::Arm64 => "arm64",
});
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum PrivilegesRequiredOverride {
Commandline,
Dialog,
}
#[derive(Clone, Debug, Default)]
pub struct HeaderTail {
pub compiled_code_version: Option<u32>,
pub windows_version_range: WindowsVersionRange,
pub back_color: Option<u32>,
pub back_color2: Option<u32>,
pub wizard_style: Option<WizardStyle>,
pub wizard_style_raw: u8,
pub wizard_size_percent_x: u32,
pub wizard_size_percent_y: u32,
pub wizard_image_alpha_format: Option<ImageAlphaFormat>,
pub wizard_image_alpha_format_raw: u8,
pub legacy_password_sha1: Option<[u8; 20]>,
pub legacy_password_md5: Option<[u8; 16]>,
pub legacy_password_crc32: Option<u32>,
pub legacy_password_salt: Option<[u8; 8]>,
pub password_test: Option<u32>,
pub encryption_kdf_salt: Option<[u8; 16]>,
pub encryption_kdf_iterations: Option<u32>,
pub encryption_base_nonce: Option<[u8; 24]>,
pub extra_disk_space_required: i64,
pub slices_per_disk: u32,
pub uninstall_log_mode: Option<UninstallLogMode>,
pub uninstall_log_mode_raw: u8,
pub dir_exists_warning: Option<AutoNoYes>,
pub dir_exists_warning_raw: u8,
pub privileges_required: Option<PrivilegesRequired>,
pub privileges_required_raw: u8,
pub privileges_required_overrides: HashSet<PrivilegesRequiredOverride>,
pub privileges_required_overrides_raw: Vec<u8>,
pub show_language_dialog: Option<YesNoAuto>,
pub show_language_dialog_raw: u8,
pub language_detection_method: Option<LanguageDetectionMethod>,
pub language_detection_method_raw: u8,
pub compress_method: Option<CompressMethod>,
pub compress_method_raw: u8,
pub architectures_allowed: Option<HashSet<Architecture>>,
pub architectures_allowed_raw: Option<u8>,
pub architectures_install_in_64bit_mode: Option<HashSet<Architecture>>,
pub architectures_install_in_64bit_mode_raw: Option<u8>,
pub disable_dir_page: Option<AutoNoYes>,
pub disable_dir_page_raw: u8,
pub disable_program_group_page: Option<AutoNoYes>,
pub disable_program_group_page_raw: u8,
pub uninstall_display_size: u64,
pub options: HashSet<HeaderOption>,
pub options_raw: Vec<u8>,
}
#[derive(Clone, Debug)]
pub struct SetupHeader {
strings: HashMap<HeaderString, String>,
ansi: HashMap<HeaderAnsi, Vec<u8>>,
counts: EntryCounts,
tail: HeaderTail,
records_offset: usize,
tail_start_offset: usize,
}
impl SetupHeader {
pub fn parse(setup0: &[u8], version: &Version) -> Result<Self, Error> {
let mut reader = Reader::new(setup0);
let mut strings: HashMap<HeaderString, String> = HashMap::with_capacity(40);
let mut ansi: HashMap<HeaderAnsi, Vec<u8>> = HashMap::with_capacity(4);
read_header_strings_and_ansi(&mut reader, version, &mut strings, &mut ansi)?;
if version.at_least(2, 0, 6) && !version.at_least(6, 3, 0) && !version.is_unicode() {
reader.skip(32, "LeadBytes")?;
}
let counts = read_counts(&mut reader, version)?;
let tail_start_offset = reader.pos();
let tail = parse_tail(&mut reader, version)?;
let records_offset = reader.pos();
Ok(Self {
strings,
ansi,
counts,
tail,
records_offset,
tail_start_offset,
})
}
pub fn string(&self, field: HeaderString) -> Option<&str> {
self.strings.get(&field).map(String::as_str)
}
pub fn ansi(&self, field: HeaderAnsi) -> Option<&[u8]> {
self.ansi.get(&field).map(Vec::as_slice)
}
#[must_use]
pub fn app_name(&self) -> Option<&str> {
self.string(HeaderString::AppName)
}
#[must_use]
pub fn app_version(&self) -> Option<&str> {
self.string(HeaderString::AppVersion)
}
#[must_use]
pub fn app_publisher(&self) -> Option<&str> {
self.string(HeaderString::AppPublisher)
}
#[must_use]
pub fn app_id(&self) -> Option<&str> {
self.string(HeaderString::AppId)
}
#[must_use]
pub fn default_dir_name(&self) -> Option<&str> {
self.string(HeaderString::DefaultDirName)
}
#[must_use]
pub fn counts(&self) -> &EntryCounts {
&self.counts
}
#[must_use]
pub fn tail(&self) -> &HeaderTail {
&self.tail
}
#[must_use]
pub fn records_offset(&self) -> usize {
self.records_offset
}
#[must_use]
pub fn tail_start_offset(&self) -> usize {
self.tail_start_offset
}
#[must_use]
pub fn options(&self) -> &HashSet<HeaderOption> {
&self.tail.options
}
#[must_use]
pub fn has_option(&self, option: HeaderOption) -> bool {
self.tail.options.contains(&option)
}
}
fn read_header_strings_and_ansi(
reader: &mut Reader<'_>,
version: &Version,
strings: &mut HashMap<HeaderString, String>,
ansi: &mut HashMap<HeaderAnsi, Vec<u8>>,
) -> Result<(), Error> {
let put_str = |reader: &mut Reader<'_>,
field: HeaderString,
strings: &mut HashMap<HeaderString, String>|
-> Result<(), Error> {
let s = read_setup_string(reader, version, field_label(field))?;
strings.insert(field, s);
Ok(())
};
let put_ansi = |reader: &mut Reader<'_>,
field: HeaderAnsi,
ansi: &mut HashMap<HeaderAnsi, Vec<u8>>|
-> Result<(), Error> {
let bytes = read_ansi_bytes(reader, ansi_label(field))?;
ansi.insert(field, bytes);
Ok(())
};
put_str(reader, HeaderString::AppName, strings)?;
put_str(reader, HeaderString::AppVerName, strings)?;
if version.at_least(1, 3, 0) {
put_str(reader, HeaderString::AppId, strings)?;
}
put_str(reader, HeaderString::AppCopyright, strings)?;
if version.at_least(1, 3, 0) {
put_str(reader, HeaderString::AppPublisher, strings)?;
put_str(reader, HeaderString::AppPublisherUrl, strings)?;
}
if version.at_least(5, 1, 13) {
put_str(reader, HeaderString::AppSupportPhone, strings)?;
}
if version.at_least(1, 3, 0) {
put_str(reader, HeaderString::AppSupportUrl, strings)?;
put_str(reader, HeaderString::AppUpdatesUrl, strings)?;
put_str(reader, HeaderString::AppVersion, strings)?;
}
put_str(reader, HeaderString::DefaultDirName, strings)?;
put_str(reader, HeaderString::DefaultGroupName, strings)?;
if !version.at_least(3, 0, 0) {
let _ = read_ansi_bytes(reader, "UninstallIconName")?;
}
put_str(reader, HeaderString::BaseFilename, strings)?;
if version.at_least(1, 3, 0) && !version.at_least(5, 2, 5) {
put_ansi(reader, HeaderAnsi::LicenseText, ansi)?;
put_ansi(reader, HeaderAnsi::InfoBeforeText, ansi)?;
put_ansi(reader, HeaderAnsi::InfoAfterText, ansi)?;
}
if version.at_least(1, 3, 3) {
put_str(reader, HeaderString::UninstallFilesDir, strings)?;
}
if version.at_least(1, 3, 6) {
put_str(reader, HeaderString::UninstallDisplayName, strings)?;
put_str(reader, HeaderString::UninstallDisplayIcon, strings)?;
}
if version.at_least(1, 3, 14) {
put_str(reader, HeaderString::AppMutex, strings)?;
}
if version.at_least(3, 0, 0) {
put_str(reader, HeaderString::DefaultUserInfoName, strings)?;
put_str(reader, HeaderString::DefaultUserInfoOrg, strings)?;
}
if version.at_least(4, 0, 0) || (version.is_isx() && version.at_least_4(3, 0, 6, 1)) {
put_str(reader, HeaderString::DefaultUserInfoSerial, strings)?;
}
if (version.at_least(4, 0, 0) && !version.at_least(5, 2, 5))
|| (version.is_isx() && version.at_least(1, 3, 24))
{
put_ansi(reader, HeaderAnsi::CompiledCodeText, ansi)?;
}
if version.at_least(4, 2, 4) {
put_str(reader, HeaderString::AppReadmeFile, strings)?;
put_str(reader, HeaderString::AppContact, strings)?;
put_str(reader, HeaderString::AppComments, strings)?;
put_str(reader, HeaderString::AppModifyPath, strings)?;
}
if version.at_least(5, 3, 8) {
put_str(reader, HeaderString::CreateUninstallRegKey, strings)?;
}
if version.at_least(5, 3, 10) {
put_str(reader, HeaderString::Uninstallable, strings)?;
}
if version.at_least(5, 5, 0) {
put_str(reader, HeaderString::CloseApplicationsFilter, strings)?;
}
if version.at_least(5, 5, 6) {
put_str(reader, HeaderString::SetupMutex, strings)?;
}
if version.at_least(5, 6, 1) {
put_str(reader, HeaderString::ChangesEnvironment, strings)?;
put_str(reader, HeaderString::ChangesAssociations, strings)?;
}
if version.at_least(6, 3, 0) {
put_str(reader, HeaderString::ArchitecturesAllowed, strings)?;
put_str(
reader,
HeaderString::ArchitecturesInstallIn64BitMode,
strings,
)?;
}
if version.at_least(5, 2, 5) {
put_ansi(reader, HeaderAnsi::LicenseText, ansi)?;
put_ansi(reader, HeaderAnsi::InfoBeforeText, ansi)?;
put_ansi(reader, HeaderAnsi::InfoAfterText, ansi)?;
}
if version.at_least(5, 2, 1) && !version.at_least(5, 3, 10) {
let _ = read_setup_string(reader, version, "UninstallerSignature")?;
}
if version.at_least(5, 2, 5) {
put_ansi(reader, HeaderAnsi::CompiledCodeText, ansi)?;
}
if version.at_least(6, 4, 3) {
put_str(
reader,
HeaderString::CloseApplicationsFilterExcludes,
strings,
)?;
}
if version.at_least(6, 5, 0) {
put_str(reader, HeaderString::SevenZipLibraryName, strings)?;
}
if version.at_least(6, 7, 0) {
put_str(reader, HeaderString::UsePreviousAppDir, strings)?;
put_str(reader, HeaderString::UsePreviousGroup, strings)?;
put_str(reader, HeaderString::UsePreviousSetupType, strings)?;
put_str(reader, HeaderString::UsePreviousTasks, strings)?;
put_str(reader, HeaderString::UsePreviousUserInfo, strings)?;
}
Ok(())
}
fn field_label(f: HeaderString) -> &'static str {
match f {
HeaderString::AppName => "AppName",
HeaderString::AppVerName => "AppVerName",
HeaderString::AppId => "AppId",
HeaderString::AppCopyright => "AppCopyright",
HeaderString::AppPublisher => "AppPublisher",
HeaderString::AppPublisherUrl => "AppPublisherURL",
HeaderString::AppSupportPhone => "AppSupportPhone",
HeaderString::AppSupportUrl => "AppSupportURL",
HeaderString::AppUpdatesUrl => "AppUpdatesURL",
HeaderString::AppVersion => "AppVersion",
HeaderString::DefaultDirName => "DefaultDirName",
HeaderString::DefaultGroupName => "DefaultGroupName",
HeaderString::BaseFilename => "BaseFilename",
HeaderString::UninstallFilesDir => "UninstallFilesDir",
HeaderString::UninstallDisplayName => "UninstallDisplayName",
HeaderString::UninstallDisplayIcon => "UninstallDisplayIcon",
HeaderString::AppMutex => "AppMutex",
HeaderString::DefaultUserInfoName => "DefaultUserInfoName",
HeaderString::DefaultUserInfoOrg => "DefaultUserInfoOrg",
HeaderString::DefaultUserInfoSerial => "DefaultUserInfoSerial",
HeaderString::AppReadmeFile => "AppReadmeFile",
HeaderString::AppContact => "AppContact",
HeaderString::AppComments => "AppComments",
HeaderString::AppModifyPath => "AppModifyPath",
HeaderString::CreateUninstallRegKey => "CreateUninstallRegKey",
HeaderString::Uninstallable => "Uninstallable",
HeaderString::CloseApplicationsFilter => "CloseApplicationsFilter",
HeaderString::SetupMutex => "SetupMutex",
HeaderString::ChangesEnvironment => "ChangesEnvironment",
HeaderString::ChangesAssociations => "ChangesAssociations",
HeaderString::ArchitecturesAllowed => "ArchitecturesAllowed",
HeaderString::ArchitecturesInstallIn64BitMode => "ArchitecturesInstallIn64BitMode",
HeaderString::CloseApplicationsFilterExcludes => "CloseApplicationsFilterExcludes",
HeaderString::SevenZipLibraryName => "SevenZipLibraryName",
HeaderString::UsePreviousAppDir => "UsePreviousAppDir",
HeaderString::UsePreviousGroup => "UsePreviousGroup",
HeaderString::UsePreviousSetupType => "UsePreviousSetupType",
HeaderString::UsePreviousTasks => "UsePreviousTasks",
HeaderString::UsePreviousUserInfo => "UsePreviousUserInfo",
}
}
fn ansi_label(f: HeaderAnsi) -> &'static str {
match f {
HeaderAnsi::LicenseText => "LicenseText",
HeaderAnsi::InfoBeforeText => "InfoBeforeText",
HeaderAnsi::InfoAfterText => "InfoAfterText",
HeaderAnsi::CompiledCodeText => "CompiledCodeText",
}
}
fn read_counts(reader: &mut Reader<'_>, version: &Version) -> Result<EntryCounts, Error> {
Ok(EntryCounts {
languages: reader.u32_le("NumLanguageEntries")?,
custom_messages: reader.u32_le("NumCustomMessageEntries")?,
permissions: reader.u32_le("NumPermissionEntries")?,
types: reader.u32_le("NumTypeEntries")?,
components: reader.u32_le("NumComponentEntries")?,
tasks: reader.u32_le("NumTaskEntries")?,
directories: reader.u32_le("NumDirEntries")?,
iss_sig_keys: if version.at_least(6, 5, 0) {
Some(reader.u32_le("NumISSigKeyEntries")?)
} else {
None
},
files: reader.u32_le("NumFileEntries")?,
file_locations: reader.u32_le("NumFileLocationEntries")?,
icons: reader.u32_le("NumIconEntries")?,
ini_entries: reader.u32_le("NumIniEntries")?,
registry: reader.u32_le("NumRegistryEntries")?,
install_deletes: reader.u32_le("NumInstallDeleteEntries")?,
uninstall_deletes: reader.u32_le("NumUninstallDeleteEntries")?,
run: reader.u32_le("NumRunEntries")?,
uninstall_run: reader.u32_le("NumUninstallRunEntries")?,
})
}
fn parse_tail(reader: &mut Reader<'_>, version: &Version) -> Result<HeaderTail, Error> {
let compiled_code_version = if version.at_least_4(7, 0, 0, 3) {
Some(reader.u32_le("CompiledCodeVersion")?)
} else {
None
};
let mut tail = HeaderTail {
compiled_code_version,
windows_version_range: WindowsVersionRange::read(reader, version)?,
..HeaderTail::default()
};
if !version.at_least_4(6, 4, 0, 1) {
tail.back_color = Some(reader.u32_le("BackColor")?);
if version.at_least(1, 3, 3) {
tail.back_color2 = Some(reader.u32_le("BackColor2")?);
}
}
if !version.at_least(5, 5, 7) {
let _image_back_color = reader.u32_le("ImageBackColor")?;
}
if version.at_least(6, 6, 0) {
tail.wizard_size_percent_x = reader.u32_le("WizardSizePercentX")?;
tail.wizard_size_percent_y = reader.u32_le("WizardSizePercentY")?;
let raw = reader.u8("WizardDarkStyle")?;
tail.wizard_style_raw = raw;
tail.wizard_style = None;
} else if version.at_least(6, 0, 0) {
let raw = reader.u8("WizardStyle")?;
tail.wizard_style_raw = raw;
tail.wizard_style = decode_wizard_style(raw);
tail.wizard_size_percent_x = reader.u32_le("WizardSizePercentX")?;
tail.wizard_size_percent_y = reader.u32_le("WizardSizePercentY")?;
}
if version.at_least(5, 5, 7) {
let raw = reader.u8("WizardImageAlphaFormat")?;
tail.wizard_image_alpha_format_raw = raw;
tail.wizard_image_alpha_format = decode_alpha_format(raw);
}
if version.at_least(6, 5, 0) {
let _wiz_image_back = reader.u32_le("WizardImageBackColor")?;
let _wiz_small_image_back = reader.u32_le("WizardSmallImageBackColor")?;
if version.at_least(6, 7, 0) {
let _wiz_back_color = reader.u32_le("WizardBackColor")?;
}
}
if version.at_least(6, 6, 0) {
let _wiz_image_back_dyn = reader.u32_le("WizardImageBackColorDynamicDark")?;
let _wiz_small_image_back_dyn = reader.u32_le("WizardSmallImageBackColorDynamicDark")?;
if version.at_least(6, 7, 0) {
let _wiz_back_color_dyn = reader.u32_le("WizardBackColorDynamicDark")?;
}
}
if version.at_least(6, 6, 1) {
let _wiz_image_opacity = reader.u8("WizardImageOpacity")?;
if version.at_least(6, 7, 0) {
let _wiz_back_image_opacity = reader.u8("WizardBackImageOpacity")?;
let _wiz_light_control_styling = reader.u8("WizardLightControlStyling")?;
}
}
if version.at_least(6, 5, 0) {
} else if version.at_least(6, 4, 0) {
tail.password_test = Some(reader.u32_le("PasswordTest")?);
tail.encryption_kdf_salt = Some(reader.array::<16>("EncryptionKDFSalt")?);
tail.encryption_kdf_iterations = Some(reader.u32_le("EncryptionKDFIterations")?);
tail.encryption_base_nonce = Some(reader.array::<24>("EncryptionBaseNonce")?);
} else if version.at_least(5, 3, 9) {
tail.legacy_password_sha1 = Some(reader.array::<20>("PasswordHash")?);
if version.at_least(4, 2, 2) {
tail.legacy_password_salt = Some(reader.array::<8>("PasswordSalt")?);
}
} else if version.at_least(4, 2, 0) {
tail.legacy_password_md5 = Some(reader.array::<16>("PasswordHashMD5")?);
if version.at_least(4, 2, 2) {
tail.legacy_password_salt = Some(reader.array::<8>("PasswordSalt")?);
}
} else {
tail.legacy_password_crc32 = Some(reader.u32_le("PasswordHashCRC32")?);
}
if version.at_least(4, 0, 0) {
tail.extra_disk_space_required = reader.i64_le("ExtraDiskSpaceRequired")?;
tail.slices_per_disk = reader.u32_le("SlicesPerDisk")?;
} else {
let v = reader.i32_le("ExtraDiskSpaceRequired")?;
tail.extra_disk_space_required = i64::from(v);
tail.slices_per_disk = 1;
}
if version.at_least(3, 0, 0) && !version.at_least(3, 0, 3) {
let _install_mode = reader.u8("InstallMode")?;
}
if version.at_least(1, 3, 0) {
let raw = reader.u8("UninstallLogMode")?;
tail.uninstall_log_mode_raw = raw;
tail.uninstall_log_mode = decode_uninstall_log_mode(raw);
}
if !version.at_least(5, 0, 0) && version.at_least(2, 0, 0) {
let _uninstall_style = reader.u8("UninstallStyle")?;
}
if version.at_least(1, 3, 6) {
let raw = reader.u8("DirExistsWarning")?;
tail.dir_exists_warning_raw = raw;
tail.dir_exists_warning = decode_auto_no_yes(raw);
}
if version.at_least(3, 0, 0) && !version.at_least(3, 0, 3) {
let _val = reader.u8("RestartMode")?;
}
if version.at_least(5, 3, 7) {
let raw = reader.u8("PrivilegesRequired")?;
tail.privileges_required_raw = raw;
tail.privileges_required = decode_privileges_required_v1(raw);
} else if version.at_least(3, 0, 4) {
let raw = reader.u8("PrivilegesRequired")?;
tail.privileges_required_raw = raw;
tail.privileges_required = decode_privileges_required_v0(raw);
}
if version.at_least(5, 7, 0) {
let raw = reader.set_bytes(2, true, "PrivilegesRequiredOverridesAllowed")?;
tail.privileges_required_overrides = decode_overrides_set(&raw);
tail.privileges_required_overrides_raw = raw;
}
if version.at_least(4, 0, 10) {
let raw = reader.u8("ShowLanguageDialog")?;
tail.show_language_dialog_raw = raw;
tail.show_language_dialog = decode_yes_no_auto(raw);
let raw = reader.u8("LanguageDetectionMethod")?;
tail.language_detection_method_raw = raw;
tail.language_detection_method = decode_language_detection(raw);
}
if version.at_least(4, 1, 5) {
let raw = reader.u8("CompressMethod")?;
tail.compress_method_raw = raw;
tail.compress_method = decode_compress_method(raw, version);
}
if version.at_least(6, 3, 0) {
} else if version.at_least(5, 6, 0) {
let raw = reader.set_bytes(5, true, "ArchitecturesAllowed")?;
tail.architectures_allowed_raw = raw.first().copied();
tail.architectures_allowed = Some(decode_arch_set_v1(&raw));
let raw = reader.set_bytes(5, true, "ArchitecturesInstallIn64BitMode")?;
tail.architectures_install_in_64bit_mode_raw = raw.first().copied();
tail.architectures_install_in_64bit_mode = Some(decode_arch_set_v1(&raw));
} else if version.at_least(5, 1, 0) {
let raw = reader.set_bytes(4, true, "ArchitecturesAllowed")?;
tail.architectures_allowed_raw = raw.first().copied();
tail.architectures_allowed = Some(decode_arch_set_v0(&raw));
let raw = reader.set_bytes(4, true, "ArchitecturesInstallIn64BitMode")?;
tail.architectures_install_in_64bit_mode_raw = raw.first().copied();
tail.architectures_install_in_64bit_mode = Some(decode_arch_set_v0(&raw));
}
if version.at_least(5, 2, 1) && !version.at_least(5, 3, 10) {
let _sz = reader.u32_le("SignedUninstallerOriginalSize")?;
let _crc = reader.u32_le("SignedUninstallerHeaderChecksum")?;
}
if version.at_least(5, 3, 3) {
let raw = reader.u8("DisableDirPage")?;
tail.disable_dir_page_raw = raw;
tail.disable_dir_page = decode_auto_no_yes(raw);
let raw = reader.u8("DisableProgramGroupPage")?;
tail.disable_program_group_page_raw = raw;
tail.disable_program_group_page = decode_auto_no_yes(raw);
}
if version.at_least(5, 5, 0) {
tail.uninstall_display_size = reader.u64_le("UninstallDisplaySize")?;
} else if version.at_least(5, 3, 6) {
let v = reader.u32_le("UninstallDisplaySize")?;
tail.uninstall_display_size = u64::from(v);
}
if matches!(
(version.a, version.b, version.c, version.d),
(5, 3, 10, 1) | (5, 4, 2, 1) | (5, 5, 0, 1)
) {
let _pad = reader.u8("BlackBoxPad")?;
}
let bit_count = options_bit_count(version);
let raw = reader.set_bytes(bit_count, true, "Options")?;
tail.options = decode_options(&raw, version);
tail.options_raw = raw;
Ok(tail)
}
fn decode_wizard_style(b: u8) -> Option<WizardStyle> {
match b {
0 => Some(WizardStyle::Classic),
1 => Some(WizardStyle::Modern),
_ => None,
}
}
fn decode_alpha_format(b: u8) -> Option<ImageAlphaFormat> {
match b {
0 => Some(ImageAlphaFormat::Ignored),
1 => Some(ImageAlphaFormat::Defined),
2 => Some(ImageAlphaFormat::Premultiplied),
_ => None,
}
}
fn decode_uninstall_log_mode(b: u8) -> Option<UninstallLogMode> {
match b {
0 => Some(UninstallLogMode::Append),
1 => Some(UninstallLogMode::New),
2 => Some(UninstallLogMode::Overwrite),
_ => None,
}
}
fn decode_auto_no_yes(b: u8) -> Option<AutoNoYes> {
match b {
0 => Some(AutoNoYes::Auto),
1 => Some(AutoNoYes::No),
2 => Some(AutoNoYes::Yes),
_ => None,
}
}
fn decode_yes_no_auto(b: u8) -> Option<YesNoAuto> {
match b {
0 => Some(YesNoAuto::Yes),
1 => Some(YesNoAuto::No),
2 => Some(YesNoAuto::Auto),
_ => None,
}
}
fn decode_privileges_required_v1(b: u8) -> Option<PrivilegesRequired> {
match b {
0 => Some(PrivilegesRequired::None),
1 => Some(PrivilegesRequired::PowerUser),
2 => Some(PrivilegesRequired::Admin),
3 => Some(PrivilegesRequired::Lowest),
_ => None,
}
}
fn decode_privileges_required_v0(b: u8) -> Option<PrivilegesRequired> {
match b {
0 => Some(PrivilegesRequired::None),
1 => Some(PrivilegesRequired::PowerUser),
2 => Some(PrivilegesRequired::Admin),
_ => None,
}
}
fn decode_language_detection(b: u8) -> Option<LanguageDetectionMethod> {
match b {
0 => Some(LanguageDetectionMethod::UiLanguage),
1 => Some(LanguageDetectionMethod::Locale),
2 => Some(LanguageDetectionMethod::None),
_ => None,
}
}
fn decode_compress_method(b: u8, version: &Version) -> Option<CompressMethod> {
if version.at_least(5, 3, 9) {
match b {
0 => Some(CompressMethod::Stored),
1 => Some(CompressMethod::Zlib),
2 => Some(CompressMethod::Bzip2),
3 => Some(CompressMethod::Lzma1),
4 => Some(CompressMethod::Lzma2),
_ => None,
}
} else if version.at_least(4, 2, 6) {
match b {
0 => Some(CompressMethod::Stored),
1 => Some(CompressMethod::Zlib),
2 => Some(CompressMethod::Bzip2),
3 => Some(CompressMethod::Lzma1),
_ => None,
}
} else if version.at_least(4, 2, 5) {
match b {
0 => Some(CompressMethod::Stored),
1 => Some(CompressMethod::Bzip2),
2 => Some(CompressMethod::Lzma1),
_ => None,
}
} else if version.at_least(4, 1, 5) {
match b {
0 => Some(CompressMethod::Zlib),
1 => Some(CompressMethod::Bzip2),
2 => Some(CompressMethod::Lzma1),
_ => None,
}
} else {
None
}
}
fn decode_overrides_set(raw: &[u8]) -> HashSet<PrivilegesRequiredOverride> {
let mut out = HashSet::new();
if bit_at(raw, 0) {
out.insert(PrivilegesRequiredOverride::Commandline);
}
if bit_at(raw, 1) {
out.insert(PrivilegesRequiredOverride::Dialog);
}
out
}
fn decode_arch_set_v1(raw: &[u8]) -> HashSet<Architecture> {
let table = [
Architecture::Unknown,
Architecture::X86,
Architecture::Amd64,
Architecture::IA64,
Architecture::Arm64,
];
decode_arch_with_table(raw, &table)
}
fn decode_arch_set_v0(raw: &[u8]) -> HashSet<Architecture> {
let table = [
Architecture::Unknown,
Architecture::X86,
Architecture::Amd64,
Architecture::IA64,
];
decode_arch_with_table(raw, &table)
}
fn decode_arch_with_table(raw: &[u8], table: &[Architecture]) -> HashSet<Architecture> {
let mut out = HashSet::new();
for (i, &arch) in table.iter().enumerate() {
if bit_at(raw, i) {
out.insert(arch);
}
}
out
}
fn bit_at(raw: &[u8], bit: usize) -> bool {
let byte_idx = bit / 8;
let bit_idx = bit % 8;
raw.get(byte_idx)
.copied()
.is_some_and(|b| (b >> bit_idx) & 1 == 1)
}
fn options_bit_count(version: &Version) -> usize {
if version.at_least(5, 5, 0) {
static_options_bit_table(version).len()
} else {
dynamic_options_bit_table(version).len()
}
}
fn decode_options(raw: &[u8], version: &Version) -> HashSet<HeaderOption> {
let mut out = HashSet::new();
if version.at_least(5, 5, 0) {
for (i, slot) in static_options_bit_table(version).iter().enumerate() {
if bit_at(raw, i)
&& let Some(opt) = slot
{
out.insert(*opt);
}
}
} else {
for (i, slot) in dynamic_options_bit_table(version).into_iter().enumerate() {
if bit_at(raw, i)
&& let Some(opt) = slot
{
out.insert(opt);
}
}
}
out
}
fn static_options_bit_table(version: &Version) -> &'static [Option<HeaderOption>] {
if version.at_least(6, 7, 0) {
OPTIONS_V6_7
} else if version.at_least(6, 5, 0) {
OPTIONS_V6_5
} else if version.at_least(6, 4, 0) {
OPTIONS_V6_4
} else if version.at_least(6, 3, 0) {
OPTIONS_V6_3
} else if version.at_least(6, 0, 0) {
OPTIONS_V6_1
} else if version.at_least(5, 5, 7) {
OPTIONS_V5_5_7
} else {
OPTIONS_V5_5_0
}
}
fn dynamic_options_bit_table(version: &Version) -> Vec<Option<HeaderOption>> {
let mut t: Vec<Option<HeaderOption>> = Vec::with_capacity(48);
t.push(Some(HeaderOption::DisableStartupPrompt));
if !version.at_least(5, 3, 10) {
t.push(None); }
t.push(Some(HeaderOption::CreateAppDir));
if !version.at_least(5, 3, 3) {
t.push(None); }
if !version.at_least(1, 3, 6) {
t.push(None); }
if !version.at_least(5, 3, 3) {
t.push(None); }
t.push(Some(HeaderOption::AllowNoIcons));
if !version.at_least(3, 0, 0) || version.at_least(3, 0, 3) {
t.push(Some(HeaderOption::AlwaysRestart));
}
if !version.at_least(1, 3, 3) {
t.push(None); }
t.push(Some(HeaderOption::AlwaysUsePersonalGroup));
if !version.at_least_4(6, 4, 0, 1) {
t.push(Some(HeaderOption::WindowVisible));
t.push(Some(HeaderOption::WindowShowCaption));
t.push(Some(HeaderOption::WindowResizable));
t.push(Some(HeaderOption::WindowStartMaximized));
}
t.push(Some(HeaderOption::EnableDirDoesntExistWarning));
if !version.at_least(4, 1, 2) {
t.push(None); }
t.push(Some(HeaderOption::Password));
if version.at_least(1, 2, 6) {
t.push(Some(HeaderOption::AllowRootDirectory));
}
if version.at_least(1, 2, 14) {
t.push(Some(HeaderOption::DisableFinishedPage));
}
if !version.at_least(3, 0, 4) {
t.push(None); }
if !version.at_least(3, 0, 0) {
t.push(None); }
if !version.at_least(1, 3, 6) {
t.push(None); }
if !version.at_least(5, 6, 1) {
t.push(None); }
if version.at_least(1, 3, 0) && !version.at_least(5, 3, 8) {
t.push(None); }
if version.at_least(1, 3, 1) {
t.push(Some(HeaderOption::UsePreviousAppDir));
}
if version.at_least(1, 3, 3) && !version.at_least_4(6, 4, 0, 1) {
t.push(Some(HeaderOption::BackColorHorizontal));
}
if version.at_least(1, 3, 10) {
t.push(Some(HeaderOption::UsePreviousGroup));
}
if version.at_least(1, 3, 20) {
t.push(Some(HeaderOption::UpdateUninstallLogAppName));
}
if version.at_least(2, 0, 0) || (version.is_isx() && version.at_least(1, 3, 10)) {
t.push(Some(HeaderOption::UsePreviousSetupType));
}
if version.at_least(2, 0, 0) {
t.push(Some(HeaderOption::DisableReadyMemo));
t.push(Some(HeaderOption::AlwaysShowComponentsList));
t.push(Some(HeaderOption::FlatComponentsList));
t.push(Some(HeaderOption::ShowComponentSizes));
t.push(Some(HeaderOption::UsePreviousTasks));
t.push(Some(HeaderOption::DisableReadyPage));
}
if version.at_least(2, 0, 7) {
t.push(Some(HeaderOption::AlwaysShowDirOnReadyPage));
t.push(Some(HeaderOption::AlwaysShowGroupOnReadyPage));
}
if version.at_least(2, 0, 17) && !version.at_least(4, 1, 5) {
t.push(None); }
if version.at_least(2, 0, 18) {
t.push(Some(HeaderOption::AllowUNCPath));
}
if version.at_least(3, 0, 0) {
t.push(Some(HeaderOption::UserInfoPage));
t.push(Some(HeaderOption::UsePreviousUserInfo));
}
if version.at_least(3, 0, 1) {
t.push(Some(HeaderOption::UninstallRestartComputer));
}
if version.at_least(3, 0, 3) {
t.push(Some(HeaderOption::RestartIfNeededByRun));
}
if version.at_least(4, 0, 0) || (version.is_isx() && version.at_least(3, 0, 3)) {
t.push(Some(HeaderOption::ShowTasksTreeLines));
}
if version.at_least(4, 0, 0) && !version.at_least(4, 0, 10) {
t.push(None); }
if version.at_least(4, 0, 1) && !version.at_least(4, 0, 10) {
t.push(None); }
if version.at_least(4, 0, 9) {
t.push(Some(HeaderOption::AllowCancelDuringInstall));
}
if version.at_least(4, 1, 3) {
t.push(Some(HeaderOption::WizardImageStretch));
}
if version.at_least(4, 1, 8) {
t.push(Some(HeaderOption::AppendDefaultDirName));
t.push(Some(HeaderOption::AppendDefaultGroupName));
}
if version.at_least(4, 2, 2) {
t.push(Some(HeaderOption::EncryptionUsed));
}
if version.at_least(5, 0, 4) && !version.at_least(5, 6, 1) {
t.push(None); }
if version.at_least(5, 1, 7) && !version.is_unicode() {
t.push(None); }
if version.at_least(5, 1, 13) {
t.push(Some(HeaderOption::SetupLogging));
}
if version.at_least(5, 2, 1) {
t.push(Some(HeaderOption::SignedUninstaller));
}
if version.at_least(5, 3, 8) {
t.push(Some(HeaderOption::UsePreviousLanguage));
}
if version.at_least(5, 3, 9) {
t.push(Some(HeaderOption::DisableWelcomePage));
}
if version.at_least(5, 5, 0) {
t.push(Some(HeaderOption::CloseApplications));
t.push(Some(HeaderOption::RestartApplications));
t.push(Some(HeaderOption::AllowNetworkDrive));
}
if version.at_least(5, 5, 7) {
t.push(Some(HeaderOption::ForceCloseApplications));
}
if version.at_least(6, 0, 0) {
t.push(Some(HeaderOption::AppNameHasConsts));
t.push(Some(HeaderOption::UsePreviousPrivileges));
t.push(Some(HeaderOption::WizardResizable));
}
if version.at_least(6, 3, 0) {
t.push(Some(HeaderOption::UninstallLogging));
}
t
}
const OPTIONS_V5_5_0: &[Option<HeaderOption>] = &[
Some(HeaderOption::DisableStartupPrompt),
Some(HeaderOption::CreateAppDir),
Some(HeaderOption::AllowNoIcons),
Some(HeaderOption::AlwaysRestart),
Some(HeaderOption::AlwaysUsePersonalGroup),
Some(HeaderOption::WindowVisible),
Some(HeaderOption::WindowShowCaption),
Some(HeaderOption::WindowResizable),
Some(HeaderOption::WindowStartMaximized),
Some(HeaderOption::EnableDirDoesntExistWarning),
Some(HeaderOption::Password),
Some(HeaderOption::AllowRootDirectory),
Some(HeaderOption::DisableFinishedPage),
None, Some(HeaderOption::UsePreviousAppDir),
Some(HeaderOption::BackColorHorizontal),
Some(HeaderOption::UsePreviousGroup),
Some(HeaderOption::UpdateUninstallLogAppName),
Some(HeaderOption::UsePreviousSetupType),
Some(HeaderOption::DisableReadyMemo),
Some(HeaderOption::AlwaysShowComponentsList),
Some(HeaderOption::FlatComponentsList),
Some(HeaderOption::ShowComponentSizes),
Some(HeaderOption::UsePreviousTasks),
Some(HeaderOption::DisableReadyPage),
Some(HeaderOption::AlwaysShowDirOnReadyPage),
Some(HeaderOption::AlwaysShowGroupOnReadyPage),
Some(HeaderOption::AllowUNCPath),
Some(HeaderOption::UserInfoPage),
Some(HeaderOption::UsePreviousUserInfo),
Some(HeaderOption::UninstallRestartComputer),
Some(HeaderOption::RestartIfNeededByRun),
Some(HeaderOption::ShowTasksTreeLines),
Some(HeaderOption::AllowCancelDuringInstall),
Some(HeaderOption::WizardImageStretch),
Some(HeaderOption::AppendDefaultDirName),
Some(HeaderOption::AppendDefaultGroupName),
Some(HeaderOption::EncryptionUsed),
None, None, Some(HeaderOption::SetupLogging),
Some(HeaderOption::SignedUninstaller),
Some(HeaderOption::UsePreviousLanguage),
Some(HeaderOption::DisableWelcomePage),
Some(HeaderOption::CloseApplications),
Some(HeaderOption::RestartApplications),
Some(HeaderOption::AllowNetworkDrive),
];
const OPTIONS_V5_5_7: &[Option<HeaderOption>] = &[
Some(HeaderOption::DisableStartupPrompt),
Some(HeaderOption::CreateAppDir),
Some(HeaderOption::AllowNoIcons),
Some(HeaderOption::AlwaysRestart),
Some(HeaderOption::AlwaysUsePersonalGroup),
Some(HeaderOption::WindowVisible),
Some(HeaderOption::WindowShowCaption),
Some(HeaderOption::WindowResizable),
Some(HeaderOption::WindowStartMaximized),
Some(HeaderOption::EnableDirDoesntExistWarning),
Some(HeaderOption::Password),
Some(HeaderOption::AllowRootDirectory),
Some(HeaderOption::DisableFinishedPage),
None, Some(HeaderOption::UsePreviousAppDir),
Some(HeaderOption::BackColorHorizontal),
Some(HeaderOption::UsePreviousGroup),
Some(HeaderOption::UpdateUninstallLogAppName),
Some(HeaderOption::UsePreviousSetupType),
Some(HeaderOption::DisableReadyMemo),
Some(HeaderOption::AlwaysShowComponentsList),
Some(HeaderOption::FlatComponentsList),
Some(HeaderOption::ShowComponentSizes),
Some(HeaderOption::UsePreviousTasks),
Some(HeaderOption::DisableReadyPage),
Some(HeaderOption::AlwaysShowDirOnReadyPage),
Some(HeaderOption::AlwaysShowGroupOnReadyPage),
Some(HeaderOption::AllowUNCPath),
Some(HeaderOption::UserInfoPage),
Some(HeaderOption::UsePreviousUserInfo),
Some(HeaderOption::UninstallRestartComputer),
Some(HeaderOption::RestartIfNeededByRun),
Some(HeaderOption::ShowTasksTreeLines),
Some(HeaderOption::AllowCancelDuringInstall),
Some(HeaderOption::WizardImageStretch),
Some(HeaderOption::AppendDefaultDirName),
Some(HeaderOption::AppendDefaultGroupName),
Some(HeaderOption::EncryptionUsed),
None, None, Some(HeaderOption::SetupLogging),
Some(HeaderOption::SignedUninstaller),
Some(HeaderOption::UsePreviousLanguage),
Some(HeaderOption::DisableWelcomePage),
Some(HeaderOption::CloseApplications),
Some(HeaderOption::RestartApplications),
Some(HeaderOption::AllowNetworkDrive),
Some(HeaderOption::ForceCloseApplications),
];
const OPTIONS_V6_1: &[Option<HeaderOption>] = &[
Some(HeaderOption::DisableStartupPrompt),
Some(HeaderOption::CreateAppDir),
Some(HeaderOption::AllowNoIcons),
Some(HeaderOption::AlwaysRestart),
Some(HeaderOption::AlwaysUsePersonalGroup),
Some(HeaderOption::WindowVisible),
Some(HeaderOption::WindowShowCaption),
Some(HeaderOption::WindowResizable),
Some(HeaderOption::WindowStartMaximized),
Some(HeaderOption::EnableDirDoesntExistWarning),
Some(HeaderOption::Password),
Some(HeaderOption::AllowRootDirectory),
Some(HeaderOption::DisableFinishedPage),
Some(HeaderOption::UsePreviousAppDir),
Some(HeaderOption::BackColorHorizontal),
Some(HeaderOption::UsePreviousGroup),
Some(HeaderOption::UpdateUninstallLogAppName),
Some(HeaderOption::UsePreviousSetupType),
Some(HeaderOption::DisableReadyMemo),
Some(HeaderOption::AlwaysShowComponentsList),
Some(HeaderOption::FlatComponentsList),
Some(HeaderOption::ShowComponentSizes),
Some(HeaderOption::UsePreviousTasks),
Some(HeaderOption::DisableReadyPage),
Some(HeaderOption::AlwaysShowDirOnReadyPage),
Some(HeaderOption::AlwaysShowGroupOnReadyPage),
Some(HeaderOption::AllowUNCPath),
Some(HeaderOption::UserInfoPage),
Some(HeaderOption::UsePreviousUserInfo),
Some(HeaderOption::UninstallRestartComputer),
Some(HeaderOption::RestartIfNeededByRun),
Some(HeaderOption::ShowTasksTreeLines),
Some(HeaderOption::AllowCancelDuringInstall),
Some(HeaderOption::WizardImageStretch),
Some(HeaderOption::AppendDefaultDirName),
Some(HeaderOption::AppendDefaultGroupName),
Some(HeaderOption::EncryptionUsed),
Some(HeaderOption::SetupLogging),
Some(HeaderOption::SignedUninstaller),
Some(HeaderOption::UsePreviousLanguage),
Some(HeaderOption::DisableWelcomePage),
Some(HeaderOption::CloseApplications),
Some(HeaderOption::RestartApplications),
Some(HeaderOption::AllowNetworkDrive),
Some(HeaderOption::ForceCloseApplications),
Some(HeaderOption::AppNameHasConsts),
Some(HeaderOption::UsePreviousPrivileges),
Some(HeaderOption::WizardResizable),
];
const OPTIONS_V6_3: &[Option<HeaderOption>] = &[
Some(HeaderOption::DisableStartupPrompt),
Some(HeaderOption::CreateAppDir),
Some(HeaderOption::AllowNoIcons),
Some(HeaderOption::AlwaysRestart),
Some(HeaderOption::AlwaysUsePersonalGroup),
Some(HeaderOption::WindowVisible),
Some(HeaderOption::WindowShowCaption),
Some(HeaderOption::WindowResizable),
Some(HeaderOption::WindowStartMaximized),
Some(HeaderOption::EnableDirDoesntExistWarning),
Some(HeaderOption::Password),
Some(HeaderOption::AllowRootDirectory),
Some(HeaderOption::DisableFinishedPage),
Some(HeaderOption::UsePreviousAppDir),
Some(HeaderOption::BackColorHorizontal),
Some(HeaderOption::UsePreviousGroup),
Some(HeaderOption::UpdateUninstallLogAppName),
Some(HeaderOption::UsePreviousSetupType),
Some(HeaderOption::DisableReadyMemo),
Some(HeaderOption::AlwaysShowComponentsList),
Some(HeaderOption::FlatComponentsList),
Some(HeaderOption::ShowComponentSizes),
Some(HeaderOption::UsePreviousTasks),
Some(HeaderOption::DisableReadyPage),
Some(HeaderOption::AlwaysShowDirOnReadyPage),
Some(HeaderOption::AlwaysShowGroupOnReadyPage),
Some(HeaderOption::AllowUNCPath),
Some(HeaderOption::UserInfoPage),
Some(HeaderOption::UsePreviousUserInfo),
Some(HeaderOption::UninstallRestartComputer),
Some(HeaderOption::RestartIfNeededByRun),
Some(HeaderOption::ShowTasksTreeLines),
Some(HeaderOption::AllowCancelDuringInstall),
Some(HeaderOption::WizardImageStretch),
Some(HeaderOption::AppendDefaultDirName),
Some(HeaderOption::AppendDefaultGroupName),
Some(HeaderOption::EncryptionUsed),
Some(HeaderOption::SetupLogging),
Some(HeaderOption::SignedUninstaller),
Some(HeaderOption::UsePreviousLanguage),
Some(HeaderOption::DisableWelcomePage),
Some(HeaderOption::CloseApplications),
Some(HeaderOption::RestartApplications),
Some(HeaderOption::AllowNetworkDrive),
Some(HeaderOption::ForceCloseApplications),
Some(HeaderOption::AppNameHasConsts),
Some(HeaderOption::UsePreviousPrivileges),
Some(HeaderOption::WizardResizable),
Some(HeaderOption::UninstallLogging),
];
const OPTIONS_V6_4: &[Option<HeaderOption>] = &[
Some(HeaderOption::DisableStartupPrompt),
Some(HeaderOption::CreateAppDir),
Some(HeaderOption::AllowNoIcons),
Some(HeaderOption::AlwaysRestart),
Some(HeaderOption::AlwaysUsePersonalGroup),
Some(HeaderOption::EnableDirDoesntExistWarning),
Some(HeaderOption::Password),
Some(HeaderOption::AllowRootDirectory),
Some(HeaderOption::DisableFinishedPage),
Some(HeaderOption::UsePreviousAppDir),
Some(HeaderOption::UsePreviousGroup),
Some(HeaderOption::UpdateUninstallLogAppName),
Some(HeaderOption::UsePreviousSetupType),
Some(HeaderOption::DisableReadyMemo),
Some(HeaderOption::AlwaysShowComponentsList),
Some(HeaderOption::FlatComponentsList),
Some(HeaderOption::ShowComponentSizes),
Some(HeaderOption::UsePreviousTasks),
Some(HeaderOption::DisableReadyPage),
Some(HeaderOption::AlwaysShowDirOnReadyPage),
Some(HeaderOption::AlwaysShowGroupOnReadyPage),
Some(HeaderOption::AllowUNCPath),
Some(HeaderOption::UserInfoPage),
Some(HeaderOption::UsePreviousUserInfo),
Some(HeaderOption::UninstallRestartComputer),
Some(HeaderOption::RestartIfNeededByRun),
Some(HeaderOption::ShowTasksTreeLines),
Some(HeaderOption::AllowCancelDuringInstall),
Some(HeaderOption::WizardImageStretch),
Some(HeaderOption::AppendDefaultDirName),
Some(HeaderOption::AppendDefaultGroupName),
Some(HeaderOption::EncryptionUsed),
Some(HeaderOption::SetupLogging),
Some(HeaderOption::SignedUninstaller),
Some(HeaderOption::UsePreviousLanguage),
Some(HeaderOption::DisableWelcomePage),
Some(HeaderOption::CloseApplications),
Some(HeaderOption::RestartApplications),
Some(HeaderOption::AllowNetworkDrive),
Some(HeaderOption::ForceCloseApplications),
Some(HeaderOption::AppNameHasConsts),
Some(HeaderOption::UsePreviousPrivileges),
Some(HeaderOption::WizardResizable),
Some(HeaderOption::UninstallLogging),
];
const OPTIONS_V6_5: &[Option<HeaderOption>] = &[
Some(HeaderOption::DisableStartupPrompt),
Some(HeaderOption::CreateAppDir),
Some(HeaderOption::AllowNoIcons),
Some(HeaderOption::AlwaysRestart),
Some(HeaderOption::AlwaysUsePersonalGroup),
Some(HeaderOption::EnableDirDoesntExistWarning),
Some(HeaderOption::Password),
Some(HeaderOption::AllowRootDirectory),
Some(HeaderOption::DisableFinishedPage),
Some(HeaderOption::UsePreviousAppDir),
Some(HeaderOption::UsePreviousGroup),
Some(HeaderOption::UpdateUninstallLogAppName),
Some(HeaderOption::UsePreviousSetupType),
Some(HeaderOption::DisableReadyMemo),
Some(HeaderOption::AlwaysShowComponentsList),
Some(HeaderOption::FlatComponentsList),
Some(HeaderOption::ShowComponentSizes),
Some(HeaderOption::UsePreviousTasks),
Some(HeaderOption::DisableReadyPage),
Some(HeaderOption::AlwaysShowDirOnReadyPage),
Some(HeaderOption::AlwaysShowGroupOnReadyPage),
Some(HeaderOption::AllowUNCPath),
Some(HeaderOption::UserInfoPage),
Some(HeaderOption::UsePreviousUserInfo),
Some(HeaderOption::UninstallRestartComputer),
Some(HeaderOption::RestartIfNeededByRun),
Some(HeaderOption::ShowTasksTreeLines),
Some(HeaderOption::AllowCancelDuringInstall),
Some(HeaderOption::WizardImageStretch),
Some(HeaderOption::AppendDefaultDirName),
Some(HeaderOption::AppendDefaultGroupName),
Some(HeaderOption::SetupLogging),
Some(HeaderOption::SignedUninstaller),
Some(HeaderOption::UsePreviousLanguage),
Some(HeaderOption::DisableWelcomePage),
Some(HeaderOption::CloseApplications),
Some(HeaderOption::RestartApplications),
Some(HeaderOption::AllowNetworkDrive),
Some(HeaderOption::ForceCloseApplications),
Some(HeaderOption::AppNameHasConsts),
Some(HeaderOption::UsePreviousPrivileges),
Some(HeaderOption::WizardResizable),
Some(HeaderOption::UninstallLogging),
];
const OPTIONS_V6_7: &[Option<HeaderOption>] = &[
Some(HeaderOption::DisableStartupPrompt),
Some(HeaderOption::CreateAppDir),
Some(HeaderOption::AllowNoIcons),
Some(HeaderOption::AlwaysRestart),
Some(HeaderOption::AlwaysUsePersonalGroup),
Some(HeaderOption::EnableDirDoesntExistWarning),
Some(HeaderOption::Password),
Some(HeaderOption::AllowRootDirectory),
Some(HeaderOption::DisableFinishedPage),
Some(HeaderOption::UpdateUninstallLogAppName),
Some(HeaderOption::DisableReadyMemo),
Some(HeaderOption::AlwaysShowComponentsList),
Some(HeaderOption::FlatComponentsList),
Some(HeaderOption::ShowComponentSizes),
Some(HeaderOption::DisableReadyPage),
Some(HeaderOption::AlwaysShowDirOnReadyPage),
Some(HeaderOption::AlwaysShowGroupOnReadyPage),
Some(HeaderOption::AllowUNCPath),
Some(HeaderOption::UserInfoPage),
Some(HeaderOption::UninstallRestartComputer),
Some(HeaderOption::RestartIfNeededByRun),
Some(HeaderOption::ShowTasksTreeLines),
Some(HeaderOption::AllowCancelDuringInstall),
Some(HeaderOption::WizardImageStretch),
Some(HeaderOption::AppendDefaultDirName),
Some(HeaderOption::AppendDefaultGroupName),
Some(HeaderOption::SetupLogging),
Some(HeaderOption::SignedUninstaller),
Some(HeaderOption::UsePreviousLanguage),
Some(HeaderOption::DisableWelcomePage),
Some(HeaderOption::CloseApplications),
Some(HeaderOption::RestartApplications),
Some(HeaderOption::AllowNetworkDrive),
Some(HeaderOption::ForceCloseApplications),
Some(HeaderOption::AppNameHasConsts),
Some(HeaderOption::UsePreviousPrivileges),
Some(HeaderOption::UninstallLogging),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
];