From 59f2953c94b8373f124dc38d4fd0635098f7c5cd Mon Sep 17 00:00:00 2001 From: Minh Nguyen Date: Mon, 26 Oct 2026 16:23:08 +0700 Subject: [PATCH] fix(windows): name the privacy window executable explicitly (#16711) Turning on privacy mode 1 could fail with `os error 193`, "%1 is not a valid Win32 application", naming a broker executable that is perfectly intact. `CreateProcessAsUserW` was given a NULL `lpApplicationName` and the unquoted broker path as `lpCommandLine`. With no application name Windows has to work out the image from the command line, and it does so by trying each whitespace-delimited prefix in turn. The default install path is `C:\Program Files\RustDesk\...`, so the first candidate is `C:\Program`. On a machine where a file by that name happens to exist, Windows loads it, fails to read it as a PE image, and returns ERROR_BAD_EXE_FORMAT. The path in the error message is the command line that was intended, not the file Windows tried. Pass the path as `lpApplicationName`, which removes the guessing entirely, and quote the copy that goes in as `lpCommandLine` so the child still sees a well-formed `argv[0]`. Bind that buffer mutably while here: the API declares it as an in/out `LPWSTR` the Unicode implementation may rewrite, so handing over a const pointer cast to mutable was the wrong interface for the call. Both other `CreateProcess` call sites in the tree already name the executable explicitly, one of them with a comment giving this exact reason, so this brings the third into line rather than introducing a pattern. Refs #16705 --- src/privacy_mode/win_topmost_window.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/privacy_mode/win_topmost_window.rs b/src/privacy_mode/win_topmost_window.rs index b30db5fbe..c8f865e3d 100644 --- a/src/privacy_mode/win_topmost_window.rs +++ b/src/privacy_mode/win_topmost_window.rs @@ -226,7 +226,14 @@ impl PrivacyModeImpl { .to_string(); unsafe { - let cmd_utf16: Vec = cmdline.encode_utf16().chain(Some(0).into_iter()).collect(); + // The path goes in as `lpApplicationName` too: given only a command line, Windows + // treats every whitespace-delimited prefix as a candidate image, and the default + // install path contains a space. + let app_utf16: Vec = cmdline.encode_utf16().chain(Some(0).into_iter()).collect(); + let mut cmd_utf16: Vec = format!("\"{cmdline}\"") + .encode_utf16() + .chain(Some(0).into_iter()) + .collect(); let mut start_info = STARTUPINFOW { cb: 0, @@ -263,8 +270,8 @@ impl PrivacyModeImpl { let create_res = CreateProcessAsUserW( token, - NULL as _, - cmd_utf16.as_ptr() as _, + app_utf16.as_ptr() as _, + cmd_utf16.as_mut_ptr() as _, NULL as _, NULL as _, FALSE,