Compare commits

...

2 Commits

Author SHA1 Message Date
David Wiesen
7a3fa55d2e Fix Windows sandbox helper launch cwd 2026-05-05 09:58:19 -07:00
David Wiesen
f35fad1f56 fix(windows): launch sandbox refresh from stable cwd 2026-05-05 09:57:34 -07:00

View File

@@ -156,6 +156,22 @@ pub fn run_setup_refresh_with_extra_read_roots(
)
}
fn setup_helper_spawn_cwd(exe: &Path, codex_home: &Path) -> PathBuf {
exe.parent()
.filter(|parent| parent.is_absolute())
.map(Path::to_path_buf)
.unwrap_or_else(|| codex_home.to_path_buf())
}
fn build_setup_helper_command(exe: &Path, payload_b64: &str, cwd: &Path) -> Command {
let mut cmd = Command::new(exe);
cmd.arg(payload_b64)
.current_dir(cwd)
.stdout(Stdio::null())
.stderr(Stdio::null());
cmd
}
fn run_setup_refresh_inner(
request: SandboxSetupRequest<'_>,
overrides: SetupRootOverrides,
@@ -191,9 +207,8 @@ fn run_setup_refresh_inner(
let b64 = BASE64_STANDARD.encode(json);
let exe = find_setup_exe();
// Refresh should never request elevation; ensure verb isn't set and we don't trigger UAC.
let mut cmd = Command::new(&exe);
cmd.arg(&b64).stdout(Stdio::null()).stderr(Stdio::null());
let cwd = std::env::current_dir().unwrap_or_else(|_| request.codex_home.to_path_buf());
let cwd = setup_helper_spawn_cwd(&exe, request.codex_home);
let mut cmd = build_setup_helper_command(&exe, &b64, &cwd);
log_note(
&format!(
"setup refresh: spawning {} (cwd={}, payload_len={})",
@@ -628,18 +643,19 @@ fn run_setup_exe(
}
};
let cwd = setup_helper_spawn_cwd(&exe, codex_home);
if !needs_elevation {
let status = Command::new(&exe)
.arg(&payload_b64)
let status = build_setup_helper_command(&exe, &payload_b64, &cwd)
.creation_flags(0x08000000) // CREATE_NO_WINDOW
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.map_err(|err| {
failure(
SetupErrorCode::OrchestratorHelperLaunchFailed,
format!("failed to launch setup helper (non-elevated): {err}"),
format!(
"failed to launch setup helper (non-elevated, cwd={}): {err}",
cwd.display()
),
)
})?;
if !status.success() {
@@ -670,6 +686,8 @@ fn run_setup_exe(
sei.lpVerb = verb_w.as_ptr();
sei.lpFile = exe_w.as_ptr();
sei.lpParameters = params_w.as_ptr();
let cwd_w = crate::winutil::to_wide(cwd.as_os_str());
sei.lpDirectory = cwd_w.as_ptr();
// Hide the window for the elevated helper.
sei.nShow = 0; // SW_HIDE
let ok = unsafe { ShellExecuteExW(&mut sei) };
@@ -1454,4 +1472,37 @@ mod tests {
.all(|path| roots.contains(&path))
);
}
#[test]
fn setup_helper_command_runs_from_stable_cwd() {
let exe = Path::new(r"C:\codex\codex-windows-sandbox-setup.exe");
let cwd = Path::new(r"C:\Users\tester\.codex");
let cmd = super::build_setup_helper_command(exe, "payload", cwd);
assert_eq!(cmd.get_program(), exe);
assert_eq!(cmd.get_args().collect::<Vec<_>>(), vec!["payload"]);
assert_eq!(cmd.get_current_dir(), Some(cwd));
}
#[test]
fn setup_helper_spawn_cwd_prefers_helper_parent() {
let exe = Path::new(r"C:\Program Files\Codex\codex-windows-sandbox-setup.exe");
let codex_home = Path::new(r"C:\Users\tester\.codex");
assert_eq!(
super::setup_helper_spawn_cwd(exe, codex_home),
PathBuf::from(r"C:\Program Files\Codex")
);
}
#[test]
fn setup_helper_spawn_cwd_falls_back_to_codex_home_for_relative_helper_paths() {
let exe = Path::new("codex-windows-sandbox-setup.exe");
let codex_home = Path::new(r"C:\Users\tester\.codex");
assert_eq!(
super::setup_helper_spawn_cwd(exe, codex_home),
codex_home.to_path_buf()
);
}
}