Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
Fix bug windows code
Browse files Browse the repository at this point in the history
  • Loading branch information
caesay committed Dec 25, 2023
1 parent 543d2dc commit d2a6398
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 73 deletions.
2 changes: 1 addition & 1 deletion src/Rust/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"rust-analyzer.cargo.features": ["windows"]
"rust-analyzer.cargo.features": ["windows"],
"rust-analyzer.showUnlinkedFileNotification": false
}
2 changes: 0 additions & 2 deletions src/Rust/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
mod apply;
pub use apply::*;

#[cfg(target_os = "windows")]
mod start;
#[cfg(target_os = "windows")]
pub use start::*;

#[cfg(target_os = "windows")]
Expand Down
21 changes: 13 additions & 8 deletions src/Rust/src/commands/start.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::shared;
use anyhow::{bail, Result};
use std::path::Path;

pub fn start(wait_for_parent: bool, exe_name: Option<&String>, exe_args: Option<Vec<&str>>, legacy_args: Option<&String>) -> Result<()> {
#[cfg(target_os = "windows")]
pub fn start(wait_for_parent: bool, exe_args: Option<Vec<&str>>, legacy_args: Option<&String>) -> Result<()> {
if legacy_args.is_some() && exe_args.is_some() {
bail!("Cannot use both legacy args and new args format.");
}
Expand All @@ -14,12 +14,8 @@ pub fn start(wait_for_parent: bool, exe_name: Option<&String>, exe_args: Option<
let (root_path, app) = shared::detect_current_manifest()?;

let current = app.get_current_path(&root_path);
let exe_to_execute = if let Some(exe) = exe_name {
Path::new(&current).join(exe)
} else {
let exe = app.get_main_exe_path(&root_path);
Path::new(&exe).to_path_buf()
};
let exe = app.get_main_exe_path(&root_path);
let exe_to_execute = std::path::Path::new(&exe);

if !exe_to_execute.exists() {
bail!("Unable to find executable to start: '{}'", exe_to_execute.to_string_lossy());
Expand All @@ -39,3 +35,12 @@ pub fn start(wait_for_parent: bool, exe_name: Option<&String>, exe_args: Option<

Ok(())
}

#[cfg(target_os = "macos")]
pub fn start(wait_for_parent: bool, exe_args: Option<Vec<&str>>, legacy_args: Option<&String>) -> Result<()> {
if wait_for_parent {
shared::wait_for_parent_to_exit(60_000)?; // 1 minute
}
let (root_path, app) = shared::detect_current_manifest()?;
shared::start_package(&app, &root_path, exe_args)
}
48 changes: 48 additions & 0 deletions src/Rust/src/shared/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,58 @@ use zip::ZipArchive;

#[cfg(target_os = "windows")]
use chrono::{Datelike, Local as DateTime};
#[cfg(target_os = "windows")]
use winsafe::{self as w, co, prelude::*};
#[cfg(target_os = "windows")]
use memmap2::Mmap;

pub trait ReadSeek: Read + Seek {}
impl<T: Read + Seek> ReadSeek for T {}

#[cfg(target_os = "windows")]
static BUNDLE_PLACEHOLDER: [u8; 48] = [
0, 0, 0, 0, 0, 0, 0, 0, // 8 bytes for package offset
0, 0, 0, 0, 0, 0, 0, 0, // 8 bytes for package length
0x94, 0xf0, 0xb1, 0x7b, 0x68, 0x93, 0xe0, 0x29, // 32 bytes for bundle signature
0x37, 0xeb, 0x34, 0xef, 0x53, 0xaa, 0xe7, 0xd4, //
0x2b, 0x54, 0xf5, 0x70, 0x7e, 0xf5, 0xd6, 0xf5, //
0x78, 0x54, 0x98, 0x3e, 0x5e, 0x94, 0xed, 0x7d, //
];

#[cfg(target_os = "windows")]
pub fn header_offset_and_length() -> (i64, i64) {
let offset = i64::from_ne_bytes(BUNDLE_PLACEHOLDER[0..8].try_into().unwrap());
let length = i64::from_ne_bytes(BUNDLE_PLACEHOLDER[8..16].try_into().unwrap());
(offset, length)
}

#[cfg(target_os = "windows")]
pub fn load_bundle_from_mmap<'a>(mmap: &'a Mmap, debug_pkg: &Option<&PathBuf>) -> Result<BundleInfo<'a>> {
info!("Reading bundle header...");
let (offset, length) = header_offset_and_length();
info!("Bundle offset = {}, length = {}", offset, length);

let zip_range: &'a [u8] = &mmap[offset as usize..(offset + length) as usize];

// try to load the bundle from embedded zip
if offset > 0 && length > 0 {
info!("Loading bundle from embedded zip...");
let cursor: Box<dyn ReadSeek> = Box::new(Cursor::new(zip_range));
let zip = ZipArchive::new(cursor).map_err(|e| anyhow::Error::new(e))?;
return Ok(BundleInfo { zip: Rc::new(RefCell::new(zip)), zip_from_file: false, zip_range: Some(zip_range), file_path: None });
}

// in debug mode only, allow a nupkg to be passed in as the first argument
if cfg!(debug_assertions) {
if let Some(pkg) = debug_pkg {
info!("Loading bundle from debug nupkg file...");
return load_bundle_from_file(pkg.to_owned());
}
}

bail!("Could not find embedded zip file. Please contact the application author.");
}

#[derive(Clone)]
pub struct BundleInfo<'a> {
zip: Rc<RefCell<ZipArchive<Box<dyn ReadSeek + 'a>>>>,
Expand Down
7 changes: 6 additions & 1 deletion src/Rust/src/shared/dialogs_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ extern "system" fn task_dialog_callback(_: w::HWND, msg: co::TDN, _: usize, _: i
return co::HRESULT::S_OK; // close dialog on button press
}

pub fn generate(title: &str, header: Option<&str>, body: &str, ok_text: Option<&str>, btns: DialogButton, ico: DialogIcon) -> Result<DialogResult> {
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() {
Expand Down Expand Up @@ -165,3 +165,8 @@ pub fn generate(title: &str, header: Option<&str>, body: &str, ok_text: Option<&
let result = w::TaskDialogIndirect(&tdc, None).map(|(dlg_id, _)| dlg_id)?;
Ok(DialogResult::from_win(result))
}

pub fn generate_alert(title: &str, header: Option<&str>, body: &str, ok_text: Option<&str>, btns: DialogButton, ico: DialogIcon) -> Result<()> {
let _ = generate_confirm(title, header, body, ok_text, btns, ico).map(|_| ())?;
Ok(())
}
26 changes: 24 additions & 2 deletions src/Rust/src/shared/util_windows.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use anyhow::{anyhow, bail, Result};
use std::{
collections::HashMap,
path::{Path, PathBuf},
};

use anyhow::{anyhow, Result};
use winsafe::{self as w, co, prelude::*};

use super::bundle::Manifest;

pub fn wait_for_parent_to_exit(ms_to_wait: u32) -> Result<()> {
info!("Reading parent process information.");
let basic_info = windows_sys::Wdk::System::Threading::ProcessBasicInformation;
Expand Down Expand Up @@ -117,6 +118,27 @@ pub fn force_stop_package<P: AsRef<Path>>(root_dir: P) -> Result<()> {
Ok(())
}

pub fn start_package<P: AsRef<Path>>(app: &Manifest, root_dir: P, exe_args: Option<Vec<&str>>) -> Result<()> {
let root_dir = root_dir.as_ref().to_path_buf();
let current = app.get_current_path(&root_dir);
let exe = app.get_main_exe_path(&root_dir);

let exe_to_execute = std::path::Path::new(&exe);
if !exe_to_execute.exists() {
bail!("Unable to find executable to start: '{}'", exe_to_execute.to_string_lossy());
}

crate::windows::assert_can_run_binary_authenticode(&exe_to_execute)?;

if let Some(args) = exe_args {
super::run_process(exe_to_execute, args, current)?;
} else {
crate::shared::run_process(exe_to_execute, vec![], current)?;
};

Ok(())
}

#[test]
fn test_get_running_processes_finds_cargo() {
let profile = w::SHGetKnownFolderPath(&co::KNOWNFOLDERID::Profile, co::KF::DONT_UNEXPAND, None).unwrap();
Expand Down
16 changes: 2 additions & 14 deletions src/Rust/src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fn root_command() -> Command {
.flatten_help(true);

#[cfg(target_os = "windows")]
cmd.subcommand(Command::new("uninstall")
let cmd = cmd.subcommand(Command::new("uninstall")
.about("Remove all app shortcuts, files, and registry entries.")
.long_flag_alias("uninstall")
);
Expand Down Expand Up @@ -120,19 +120,7 @@ fn start(matches: &ArgMatches) -> Result<()> {
warn!("Legacy args format is deprecated and will be removed in a future release. Please update your application to use the new format.");
}

#[cfg(target_os = "windows")]
{
commands::start(wait_for_parent, exe_name, exe_args, legacy_args)
}

#[cfg(target_os = "macos")]
{
if wait_for_parent {
shared::wait_for_parent_to_exit(60_000)?; // 1 minute
}
let (root_path, app) = shared::detect_current_manifest()?;
shared::start_package(&app, &root_path, exe_args)
}
commands::start(wait_for_parent, exe_args, legacy_args)
}

fn apply(matches: &ArgMatches) -> Result<()> {
Expand Down
44 changes: 0 additions & 44 deletions src/Rust/src/windows/bundle_loader.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/Rust/src/windows/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod bundle_loader;
pub mod download;
pub mod prerequisite;
pub mod runtimes;
Expand Down

0 comments on commit d2a6398

Please sign in to comment.