use std::collections::HashSet;
use crate::{
error::Error,
records::{item::ItemConditions, windows::WindowsVersionRange},
util::{encoding::read_setup_string, read::Reader},
version::Version,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum CloseOnExit {
NoSetting,
Close,
DontClose,
}
stable_name_enum!(CloseOnExit, {
Self::NoSetting => "no_setting",
Self::Close => "close",
Self::DontClose => "dont_close",
});
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum IconFlag {
NeverUninstall,
RunMinimized,
CreateOnlyIfFileExists,
UseAppPaths,
FolderShortcut,
ExcludeFromShowInNewInstall,
PreventPinning,
HasAppUserModelToastActivatorCLSID,
}
stable_flag_enum!(IconFlag, {
NeverUninstall => "never_uninstall",
RunMinimized => "run_minimized",
CreateOnlyIfFileExists => "create_only_if_file_exists",
UseAppPaths => "use_app_paths",
FolderShortcut => "folder_shortcut",
ExcludeFromShowInNewInstall => "exclude_from_show_in_new_install",
PreventPinning => "prevent_pinning",
HasAppUserModelToastActivatorCLSID => "has_app_user_model_toast_activator_clsid",
});
#[derive(Clone, Debug)]
pub struct IconEntry {
pub name: String,
pub filename: String,
pub parameters: String,
pub working_dir: String,
pub icon_file: String,
pub comment: String,
pub conditions: ItemConditions,
pub app_user_model_id: String,
pub app_user_model_toast_activator_clsid: Option<[u8; 16]>,
pub winver: WindowsVersionRange,
pub icon_index: i32,
pub show_command: i32,
pub close_on_exit: Option<CloseOnExit>,
pub close_on_exit_raw: u8,
pub hotkey: u16,
pub flags: HashSet<IconFlag>,
pub options_raw: Vec<u8>,
}
impl IconEntry {
pub(crate) fn read(reader: &mut Reader<'_>, version: &Version) -> Result<Self, Error> {
let name = read_setup_string(reader, version, "Icon.Name")?;
let filename = read_setup_string(reader, version, "Icon.Filename")?;
let parameters = read_setup_string(reader, version, "Icon.Parameters")?;
let working_dir = read_setup_string(reader, version, "Icon.WorkingDir")?;
let icon_file = read_setup_string(reader, version, "Icon.IconFile")?;
let comment = read_setup_string(reader, version, "Icon.Comment")?;
let conditions = ItemConditions::read(reader, version)?;
let app_user_model_id = if version.at_least(5, 3, 5) {
read_setup_string(reader, version, "Icon.AppUserModelID")?
} else {
String::new()
};
let app_user_model_toast_activator_clsid = if version.at_least(6, 1, 0) {
Some(reader.array::<16>("Icon.ToastActivatorCLSID")?)
} else {
None
};
let winver = WindowsVersionRange::read(reader, version)?;
let icon_index = reader.i32_le("Icon.IconIndex")?;
let show_command = if version.at_least(1, 3, 24) {
reader.i32_le("Icon.ShowCmd")?
} else {
1
};
let (close_on_exit, close_on_exit_raw) = if version.at_least(1, 3, 15) {
let raw = reader.u8("Icon.CloseOnExit")?;
(decode_close_on_exit(raw), raw)
} else {
(None, 0)
};
let hotkey = if version.at_least(2, 0, 7) {
reader.u16_le("Icon.HotKey")?
} else {
0
};
let table = icon_flag_table(version);
let raw = reader.set_bytes(table.len(), true, "Icon.Options")?;
let flags = super::decode_packed_flags(&raw, &table);
Ok(Self {
name,
filename,
parameters,
working_dir,
icon_file,
comment,
conditions,
app_user_model_id,
app_user_model_toast_activator_clsid,
winver,
icon_index,
show_command,
close_on_exit,
close_on_exit_raw,
hotkey,
flags,
options_raw: raw,
})
}
}
fn decode_close_on_exit(b: u8) -> Option<CloseOnExit> {
match b {
0 => Some(CloseOnExit::NoSetting),
1 => Some(CloseOnExit::Close),
2 => Some(CloseOnExit::DontClose),
_ => None,
}
}
fn icon_flag_table(version: &Version) -> Vec<IconFlag> {
let mut t = vec![IconFlag::NeverUninstall];
if !version.at_least(1, 3, 26) {
t.push(IconFlag::RunMinimized);
}
t.push(IconFlag::CreateOnlyIfFileExists);
t.push(IconFlag::UseAppPaths);
if version.at_least(5, 0, 3) && !version.at_least(6, 3, 0) {
t.push(IconFlag::FolderShortcut);
}
if version.at_least(5, 4, 2) {
t.push(IconFlag::ExcludeFromShowInNewInstall);
}
if version.at_least(5, 5, 0) {
t.push(IconFlag::PreventPinning);
}
if version.at_least(6, 1, 0) {
t.push(IconFlag::HasAppUserModelToastActivatorCLSID);
}
t
}