Initial update

This commit is contained in:
Caelan Sayler
2024-06-02 15:33:16 +01:00
parent ac498494bd
commit bbda38c953
8 changed files with 247 additions and 198 deletions

224
src/Rust/Cargo.lock generated
View File

@@ -95,6 +95,15 @@ version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "as-slice"
version = "0.2.1"
@@ -142,9 +151,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "bumpalo"
version = "3.15.0"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytemuck"
@@ -191,7 +200,7 @@ dependencies = [
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.0",
"windows-targets 0.52.5",
]
[[package]]
@@ -360,6 +369,17 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "derive_arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.49",
]
[[package]]
name = "dialog"
version = "0.3.0"
@@ -418,6 +438,17 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "displaydoc"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.49",
]
[[package]]
name = "either"
version = "1.10.0"
@@ -570,9 +601,9 @@ dependencies = [
[[package]]
name = "gif"
version = "0.12.0"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"
dependencies = [
"color_quant",
"weezl",
@@ -616,7 +647,7 @@ dependencies = [
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
"windows-core 0.52.0",
]
[[package]]
@@ -640,17 +671,18 @@ dependencies = [
[[package]]
name = "image"
version = "0.24.8"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23"
checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"gif",
"jpeg-decoder",
"num-traits",
"png",
"zune-core",
"zune-jpeg",
]
[[package]]
@@ -687,12 +719,6 @@ dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
[[package]]
name = "js-sys"
version = "0.3.68"
@@ -742,10 +768,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "log"
version = "0.4.20"
name = "lockfree-object-pool"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "malloc_buf"
@@ -758,9 +790,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.7.1"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "memmap2"
@@ -1723,14 +1755,14 @@ checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
[[package]]
name = "webview2-com"
version = "0.28.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0ae9c7e420783826cf769d2c06ac9ba462f450eca5893bb8c6c6529a4e5dd33"
checksum = "5c914dd492a52f0377bef56fd1b6e74a79090f9ee631d625d5b505a00e4538b6"
dependencies = [
"webview2-com-macros",
"webview2-com-sys",
"windows",
"windows-core",
"windows-core 0.56.0",
"windows-implement",
"windows-interface",
]
@@ -1748,13 +1780,13 @@ dependencies = [
[[package]]
name = "webview2-com-sys"
version = "0.28.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6ad85fceee6c42fa3d61239eba5a11401bf38407a849ed5ea1b407df08cca72"
checksum = "2a46bcf03482ec28eeb764ca788f67998cde4213adfbbfa90462622058530f5e"
dependencies = [
"thiserror",
"windows",
"windows-core",
"windows-core 0.56.0",
]
[[package]]
@@ -1830,14 +1862,12 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.52.0"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
dependencies = [
"windows-core",
"windows-implement",
"windows-interface",
"windows-targets 0.52.0",
"windows-core 0.56.0",
"windows-targets 0.52.5",
]
[[package]]
@@ -1846,14 +1876,26 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.0",
"windows-targets 0.52.5",
]
[[package]]
name = "windows-core"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-targets 0.52.5",
]
[[package]]
name = "windows-implement"
version = "0.52.0"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946"
checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
dependencies = [
"proc-macro2",
"quote",
@@ -1862,15 +1904,24 @@ dependencies = [
[[package]]
name = "windows-interface"
version = "0.52.0"
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1"
checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.49",
]
[[package]]
name = "windows-result"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b"
dependencies = [
"windows-targets 0.52.5",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
@@ -1886,7 +1937,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
"windows-targets 0.52.5",
]
[[package]]
@@ -1906,17 +1957,18 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.52.0"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
"windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.5",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.5",
"windows_x86_64_gnu 0.52.5",
"windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
]
[[package]]
@@ -1927,9 +1979,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
@@ -1939,9 +1991,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
@@ -1951,9 +2003,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
@@ -1963,9 +2021,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
@@ -1975,9 +2033,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -1987,9 +2045,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
@@ -1999,9 +2057,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "winnow"
@@ -2023,9 +2081,9 @@ dependencies = [
[[package]]
name = "winsafe"
version = "0.0.19"
version = "0.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
checksum = "9c4afa7176f9fadc45817419f5fe481b9e8b90299c62af90e8c19486d0320274"
[[package]]
name = "xml"
@@ -2050,14 +2108,33 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "zip"
version = "0.6.6"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
checksum = "1dd56a4d5921bc2f99947ac5b3abe5f510b1be7376fdc5e9fce4a23c6a93e87c"
dependencies = [
"byteorder",
"arbitrary",
"crc32fast",
"crossbeam-utils",
"displaydoc",
"flate2",
"indexmap",
"memchr",
"thiserror",
"zopfli",
]
[[package]]
name = "zopfli"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946"
dependencies = [
"bumpalo",
"crc32fast",
"lockfree-object-pool",
"log",
"once_cell",
"simd-adler32",
]
[[package]]
@@ -2087,3 +2164,18 @@ dependencies = [
"cc",
"pkg-config",
]
[[package]]
name = "zune-core"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
[[package]]
name = "zune-jpeg"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448"
dependencies = [
"zune-core",
]

View File

@@ -47,7 +47,7 @@ rpath = false # disable rpath
[dependencies]
anyhow = "1.0"
pretty-bytes-rust = "0.3"
zip = { version = "0.6", default-features = false, features = ["deflate"] }
zip = { version = "2.1", default-features = false, features = ["deflate"] }
regex = "1.10"
rand = "0.8"
log = "0.4"
@@ -89,13 +89,13 @@ libc = "0.2"
[target.'cfg(windows)'.dependencies]
fs_extra = "1.2"
memmap2 = "0.9"
winsafe = { version = "0.0.19", features = ["version", "user", "gui"] }
image = { version = "0.24", default-features = false, features = [
winsafe = { version = "0.0.21", features = ["version", "user", "gui"] }
image = { version = "0.25.1", default-features = false, features = [
"gif",
"jpeg",
"png",
] }
windows = { version = "0.52", default-features = false, features = [
windows = { version = "0.56", default-features = false, features = [
"Win32_Foundation",
"Win32_Security",
"Win32_System_Com",
@@ -127,7 +127,7 @@ windows-sys = { version = "0.52", default-features = false, features = [
"Wdk_System_Threading",
] }
normpath = "1.0.1"
webview2-com = "0.28.0"
webview2-com = "0.30"
[dev-dependencies]
tempfile = "3.9"

View File

@@ -30,7 +30,7 @@ fn main() {
.set("ProductName", "Velopack")
.set("ProductVersion", version)
.set("FileDescription", &desc)
.set("LegalCopyright", "Caelan Sayler (c) 2023")
.set("LegalCopyright", "Caelan Sayler (c) 2023, Velopack (c) 2024")
.compile()
.unwrap();
}
@@ -39,6 +39,7 @@ fn main() {
fn delay_load() {
delay_load_exe("update");
delay_load_exe("setup");
delay_load_exe("stub");
println!("cargo:rustc-link-arg=/DEPENDENTLOADFLAG:0x800");
println!("cargo:rustc-link-arg=/WX");
println!("cargo:rustc-link-arg=/IGNORE:4099"); // PDB was not found

View File

@@ -1,7 +1,7 @@
use super::{bundle::Manifest, dialogs_common::*, dialogs_const::*};
use anyhow::Result;
use std::path::PathBuf;
use winsafe::{self as w, co, prelude::*, WString};
use winsafe::{self as w, co, prelude::*};
pub fn show_restart_required(app: &Manifest) {
show_warn(
@@ -46,32 +46,32 @@ pub fn show_uninstall_complete_with_errors_dialog(app: &Manifest, log_path: Opti
return;
}
let mut setup_name = WString::from_str(format!("{} Uninstall", app.title));
let mut instruction = WString::from_str(format!("{} uninstall has completed with errors.", app.title));
let mut content = WString::from_str(
"There may be left-over files or directories on your system. You can attempt to remove these manually or re-install the application and try again.",
);
let setup_name = format!("{} Uninstall", app.title);
let instruction = format!("{} uninstall has completed with errors.", app.title);
let content =
"There may be left-over files or directories on your system. You can attempt to remove these manually or re-install the application and try again.";
let mut config: w::TASKDIALOGCONFIG = Default::default();
config.dwFlags = co::TDF::ENABLE_HYPERLINKS | co::TDF::SIZE_TO_CONTENT;
config.dwCommonButtons = co::TDCBF::OK;
config.set_pszMainIcon(w::IconIdTdicon::Tdicon(co::TD_ICON::WARNING));
config.set_pszWindowTitle(Some(&mut setup_name));
config.set_pszMainInstruction(Some(&mut instruction));
config.set_pszContent(Some(&mut content));
config.flags = co::TDF::ENABLE_HYPERLINKS | co::TDF::SIZE_TO_CONTENT;
config.common_buttons = co::TDCBF::OK;
config.main_icon = w::IconIdTd::Td(co::TD_ICON::WARNING);
config.window_title = Some(setup_name.as_str());
config.main_instruction = Some(instruction.as_str());
config.content = Some(content);
let footer_path = log_path.map(|p| p.to_string_lossy().to_string()).unwrap_or("".to_string());
let mut footer = WString::from_str(format!("Log file: '<A HREF=\"na\">{}</A>'", footer_path));
let footer = format!("Log file: '<A HREF=\"na\">{}</A>'", footer_path);
if let Some(log_path) = log_path {
if log_path.exists() {
config.set_pszFooterIcon(w::IconId::Id(co::TD_ICON::INFORMATION.into()));
config.set_pszFooter(Some(&mut footer));
config.lpCallbackData = log_path as *const PathBuf as usize;
config.pfCallback = Some(task_dialog_callback);
config.footer_icon = w::IconId::Id(co::TD_ICON::INFORMATION.into());
config.footer_text = Some(footer.as_str());
config.callback_data = log_path as *const PathBuf as usize;
config.callback = Some(task_dialog_callback);
}
}
let _ = w::TaskDialogIndirect(&config, None);
let _ = w::TaskDialogIndirect(&config);
}
pub fn show_overwrite_repair_dialog(app: &Manifest, root_path: &PathBuf, root_is_default: bool) -> bool {
@@ -81,63 +81,50 @@ pub fn show_overwrite_repair_dialog(app: &Manifest, root_path: &PathBuf, root_is
// these are the defaults, if we can't detect the current app version - we call it "Repair"
let mut config: w::TASKDIALOGCONFIG = Default::default();
config.set_pszMainIcon(w::IconIdTdicon::Tdicon(co::TD_ICON::WARNING));
config.main_icon = w::IconIdTd::Td(co::TD_ICON::WARNING);
let mut setup_name = WString::from_str(format!("{} Setup {}", app.title, app.version));
let mut instruction = WString::from_str(format!("{} is already installed.", app.title));
let mut content = WString::from_str("This application is installed on your computer. If it is not functioning correctly, you can attempt to repair it.");
let mut btn_yes_txt = WString::from_str(format!("Repair\nErase the application and re-install version {}.", app.version));
let mut btn_cancel_txt = WString::from_str("Cancel\nBackup or save your work first");
let mut setup_name = format!("{} Setup {}", app.title, app.version);
let mut instruction = format!("{} is already installed.", app.title);
let mut content = "This application is installed on your computer. If it is not functioning correctly, you can attempt to repair it.".to_owned();
let mut btn_yes_txt = format!("Repair\nErase the application and re-install version {}.", app.version);
let btn_cancel_txt = "Cancel\nBackup or save your work first";
// if we can detect the current app version, we call it "Update" or "Downgrade"
let possible_update = root_path.join("Update.exe");
let old_app = super::detect_manifest_from_update_path(&possible_update).map(|v| v.1).ok();
if let Some(old) = old_app {
if old.version < app.version {
instruction = WString::from_str(format!("An older version of {} is installed.", app.title));
content = WString::from_str(format!("Would you like to update from {} to {}?", old.version, app.version));
btn_yes_txt = WString::from_str(format!("Update\nTo version {}", app.version));
config.set_pszMainIcon(w::IconIdTdicon::Tdicon(co::TD_ICON::INFORMATION));
instruction = format!("An older version of {} is installed.", app.title);
content = format!("Would you like to update from {} to {}?", old.version, app.version);
btn_yes_txt = format!("Update\nTo version {}", app.version);
config.main_icon = w::IconIdTd::Td(co::TD_ICON::INFORMATION);
} else if old.version > app.version {
instruction = WString::from_str(format!("A newer version of {} is installed.", app.title));
content = WString::from_str(format!(
"You already have {} installed. Would you like to downgrade this application to an older version?",
old.version
));
btn_yes_txt = WString::from_str(format!("Downgrade\nTo version {}", app.version));
instruction = format!("A newer version of {} is installed.", app.title);
content = format!("You already have {} installed. Would you like to downgrade this application to an older version?", old.version);
btn_yes_txt = format!("Downgrade\nTo version {}", app.version);
}
}
let mut footer = if root_is_default {
WString::from_str(format!("The install directory is '<A HREF=\"na\">%LocalAppData%\\{}</A>'", app.id))
format!("The install directory is '<A HREF=\"na\">%LocalAppData%\\{}</A>'", app.id)
} else {
WString::from_str(format!("The install directory is '<A HREF=\"na\">{}</A>'", root_path.display()))
format!("The install directory is '<A HREF=\"na\">{}</A>'", root_path.display())
};
let mut btn_yes = w::TASKDIALOG_BUTTON::default();
btn_yes.set_nButtonID(co::DLGID::YES.into());
btn_yes.set_pszButtonText(Some(&mut btn_yes_txt));
let btn_yes_txt = btn_yes_txt.as_str();
let buttons = [(co::DLGID::YES.into(), btn_yes_txt), (co::DLGID::CANCEL.into(), btn_cancel_txt)];
config.buttons = &buttons;
let mut btn_cancel = w::TASKDIALOG_BUTTON::default();
btn_cancel.set_nButtonID(co::DLGID::CANCEL.into());
btn_cancel.set_pszButtonText(Some(&mut btn_cancel_txt));
config.flags = co::TDF::ENABLE_HYPERLINKS | co::TDF::USE_COMMAND_LINKS;
config.window_title = Some(&mut setup_name);
config.main_instruction = Some(&mut instruction);
config.content = Some(&mut content);
config.footer_icon = w::IconId::Id(co::TD_ICON::INFORMATION.into());
config.footer_text = Some(&mut footer);
config.callback_data = root_path as *const PathBuf as usize;
config.callback = Some(task_dialog_callback);
let mut custom_btns = Vec::with_capacity(2);
custom_btns.push(btn_yes);
custom_btns.push(btn_cancel);
config.dwFlags = co::TDF::ENABLE_HYPERLINKS | co::TDF::USE_COMMAND_LINKS;
config.set_pButtons(Some(&mut custom_btns));
config.set_pszWindowTitle(Some(&mut setup_name));
config.set_pszMainInstruction(Some(&mut instruction));
config.set_pszContent(Some(&mut content));
config.set_pszFooterIcon(w::IconId::Id(co::TD_ICON::INFORMATION.into()));
config.set_pszFooter(Some(&mut footer));
config.lpCallbackData = root_path as *const PathBuf as usize;
config.pfCallback = Some(task_dialog_callback);
let (btn, _) = w::TaskDialogIndirect(&config, None).ok().unwrap_or_else(|| (co::DLGID::YES, 0));
let (btn, _, _) = w::TaskDialogIndirect(&config).ok().unwrap_or_else(|| (co::DLGID::YES, 0, true));
return btn == co::DLGID::YES;
}
@@ -154,40 +141,24 @@ extern "system" fn task_dialog_callback(_: w::HWND, msg: co::TDN, _: usize, _: i
pub fn generate_confirm(title: &str, header: Option<&str>, body: &str, ok_text: Option<&str>, btns: DialogButton, ico: DialogIcon) -> Result<DialogResult> {
let hparent = w::HWND::GetDesktopWindow();
let mut ok_text_buf = WString::from_opt_str(ok_text);
let mut custom_btns = if ok_text.is_some() {
let mut td_btn = w::TASKDIALOG_BUTTON::default();
td_btn.set_nButtonID(co::DLGID::OK.into());
td_btn.set_pszButtonText(Some(&mut ok_text_buf));
let mut custom_btns = Vec::with_capacity(1);
custom_btns.push(td_btn);
custom_btns
} else {
Vec::<w::TASKDIALOG_BUTTON>::default()
};
let hwnd = unsafe { hparent.raw_copy() };
let custom_btns: Vec<(u16, &str)> = if ok_text.is_some() { vec![(co::DLGID::OK.into(), ok_text.unwrap())] } else { vec![] };
let mut tdc = w::TASKDIALOGCONFIG::default();
tdc.hwndParent = unsafe { hparent.raw_copy() };
tdc.dwFlags = co::TDF::ALLOW_DIALOG_CANCELLATION | co::TDF::POSITION_RELATIVE_TO_WINDOW;
tdc.dwCommonButtons = btns.to_win();
tdc.set_pszMainIcon(w::IconIdTdicon::Tdicon(ico.to_win()));
tdc.hwnd_parent = Some(&hwnd);
tdc.flags = co::TDF::ALLOW_DIALOG_CANCELLATION | co::TDF::POSITION_RELATIVE_TO_WINDOW;
tdc.common_buttons = btns.to_win();
tdc.main_icon = w::IconIdTd::Td(ico.to_win());
if ok_text.is_some() {
tdc.set_pButtons(Some(&mut custom_btns));
tdc.buttons = &custom_btns;
}
let mut title_buf = WString::from_str(title);
tdc.set_pszWindowTitle(Some(&mut title_buf));
tdc.window_title = Some(title);
tdc.main_instruction = header;
tdc.content = Some(body);
let mut header_buf = WString::from_opt_str(header);
if header.is_some() {
tdc.set_pszMainInstruction(Some(&mut header_buf));
}
let mut body_buf = WString::from_str(body);
tdc.set_pszContent(Some(&mut body_buf));
let result = w::TaskDialogIndirect(&tdc, None).map(|(dlg_id, _)| dlg_id)?;
let result = w::TaskDialogIndirect(&tdc).map(|(dlg_id, _, _)| dlg_id)?;
Ok(DialogResult::from_win(result))
}

View File

@@ -56,11 +56,7 @@ pub fn wait_for_parent_to_exit(ms_to_wait: u32) -> Result<()> {
}
fn get_pid_start_time(process: w::HPROCESS) -> Result<u64> {
let mut creation = w::FILETIME::default();
let mut exit = w::FILETIME::default();
let mut kernel = w::FILETIME::default();
let mut user = w::FILETIME::default();
process.GetProcessTimes(&mut creation, &mut exit, &mut kernel, &mut user)?;
let (creation, _, _, _) = process.GetProcessTimes()?;
Ok(((creation.dwHighDateTime as u64) << 32) | creation.dwLowDateTime as u64)
}

View File

@@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
use std::time::Duration;
use winsafe::{self as w, co};
use windows::core::{ComInterface, IntoParam, Param, Result as WindowsResult, GUID, HSTRING, PCWSTR};
use windows::core::{Interface, Result as WindowsResult, GUID, HSTRING, PCWSTR};
use windows::Win32::Foundation::HWND;
use windows::Win32::Storage::EnhancedStorage::PKEY_AppUserModel_ID;
use windows::Win32::System::Com::StructuredStorage::InitPropVariantFromStringVector;
@@ -18,13 +18,16 @@ use windows::Win32::UI::Shell::{IShellLinkW, ShellLink};
#[inline]
fn init_com() -> WindowsResult<()> {
unsafe { CoInitializeEx(None, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE) }?;
let hr = unsafe { CoInitializeEx(None, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE) };
if hr.is_err() {
return Err(hr.into());
}
std::thread::sleep(Duration::from_millis(1));
Ok(())
}
#[inline]
fn create_instance<T: ComInterface>(clsid: &GUID) -> WindowsResult<T> {
fn create_instance<T: Interface>(clsid: &GUID) -> WindowsResult<T> {
unsafe { CoCreateInstance(clsid, None, CLSCTX_ALL) }
}
@@ -88,8 +91,9 @@ fn _create_lnk(output: &str, target: &str, work_dir: &str, app_model_id: Option<
// Docs: https://docs.microsoft.com/windows/win32/properties/props-system-appusermodel-id
if let Some(app_model_id) = app_model_id {
let store: IPropertyStore = link.cast()?;
let id: Param<PCWSTR> = HSTRING::from(app_model_id).into_param();
let id: PCWSTR = id.abi();
let hstring = HSTRING::from(app_model_id);
let widearr = hstring.as_wide();
let id: PCWSTR = PCWSTR(widearr.as_ptr());
let variant = InitPropVariantFromStringVector(Some(&[id]))?;
store.SetValue(&PKEY_AppUserModel_ID, &variant)?;
store.Commit()?;

View File

@@ -8,12 +8,10 @@ use std::{
sync::mpsc::{self, Receiver, Sender},
thread,
};
use w::WString;
use winsafe::{self as w, co, guard::DeleteObjectGuard, gui, prelude::*};
use winsafe::{self as w, co, guard::DeleteObjectGuard, gui, msg, prelude::*};
const TMR_GIF: usize = 1;
const MSG_NOMESSAGE: i16 = -99;
pub const MSG_CLOSE: i16 = -1;
// pub const MSG_INDEFINITE: i16 = -2;
@@ -168,7 +166,7 @@ impl SplashWindow {
if msg == MSG_NOMESSAGE {
break;
} else if msg == MSG_CLOSE {
self2.wnd.hwnd().SendMessage(w::msg::wm::Close {});
unsafe { self2.wnd.hwnd().SendMessage(msg::wm::Close {}) };
return Ok(());
} else if msg >= 0 {
let mut p = self2.progress.borrow_mut();
@@ -291,22 +289,14 @@ pub struct ComCtlProgressWindow {
}
fn show_com_ctl_progress_dialog(rx: Receiver<i16>, window_title: &str, content: &str) {
let mut window_title = WString::from_str(window_title);
let mut content = WString::from_str(content);
let mut ok_text_buf = WString::from_str("Hide");
let mut td_btn = w::TASKDIALOG_BUTTON::default();
td_btn.set_nButtonID(co::DLGID::OK.into());
td_btn.set_pszButtonText(Some(&mut ok_text_buf));
let mut custom_btns = Vec::with_capacity(1);
custom_btns.push(td_btn);
let buttons = vec![(co::DLGID::OK.into(), "Hide")];
let mut config: w::TASKDIALOGCONFIG = Default::default();
config.dwFlags = co::TDF::SIZE_TO_CONTENT | co::TDF::SHOW_PROGRESS_BAR | co::TDF::CALLBACK_TIMER;
config.set_pszMainIcon(w::IconIdTdicon::Tdicon(co::TD_ICON::INFORMATION));
config.set_pszWindowTitle(Some(&mut window_title));
config.set_pszMainInstruction(Some(&mut content));
config.set_pButtons(Some(&mut custom_btns));
config.flags = co::TDF::SIZE_TO_CONTENT | co::TDF::SHOW_PROGRESS_BAR | co::TDF::CALLBACK_TIMER;
config.main_icon = w::IconIdTd::Td(co::TD_ICON::INFORMATION);
config.window_title = Some(window_title);
config.main_instruction = Some(content);
config.buttons = &buttons;
// if (_icon != null) {
// config.dwFlags |= TASKDIALOG_FLAGS.TDF_USE_HICON_MAIN;
@@ -314,10 +304,10 @@ fn show_com_ctl_progress_dialog(rx: Receiver<i16>, window_title: &str, content:
// }
let me = ComCtlProgressWindow { rx: Rc::new(rx) };
config.lpCallbackData = &me as *const ComCtlProgressWindow as usize;
config.pfCallback = Some(task_dialog_callback);
config.callback_data = &me as *const ComCtlProgressWindow as usize;
config.callback = Some(task_dialog_callback);
let _ = w::TaskDialogIndirect(&config, None);
let _ = w::TaskDialogIndirect(&config);
}
extern "system" fn task_dialog_callback(hwnd: w::HWND, msg: co::TDN, _: usize, _: isize, lp_ref_data: usize) -> co::HRESULT {
@@ -338,7 +328,7 @@ extern "system" fn task_dialog_callback(hwnd: w::HWND, msg: co::TDN, _: usize, _
}
}
if progress > 0 {
hwnd.SendMessage(MsgSetProgressPos { pos: progress as usize });
unsafe { hwnd.SendMessage(MsgSetProgressPos { pos: progress as usize }); }
}
}

View File

@@ -1,5 +1,5 @@
use crate::shared::{self, runtime_arch::RuntimeArch};
use anyhow::{anyhow, bail, Result};
use anyhow::{anyhow, Result};
use normpath::PathExt;
use std::{
ffi::OsStr,
@@ -55,14 +55,9 @@ pub fn create_global_mutex(app: &shared::bundle::Manifest) -> Result<MutexDropGu
let pw = PCWSTR(encoded.as_ptr());
let mutex = unsafe { CreateMutexW(None, true, pw) }?;
match unsafe { GetLastError() } {
Ok(_) => Ok(MutexDropGuard { mutex }),
Err(err) => {
if err == Foundation::ERROR_ALREADY_EXISTS.into() {
bail!("Another installer or updater for this application is running, quit that process and try again.");
} else {
bail!("Unable to create global mutex: {}", err);
}
}
Foundation::ERROR_SUCCESS => Ok(MutexDropGuard { mutex }),
Foundation::ERROR_ALREADY_EXISTS => Err(anyhow!("Another installer or updater for this application is running, quit that process and try again.")),
err => Err(anyhow!("Unable to create global mutex. Error code {:?}", err)),
}
}