diff --git a/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin.rs b/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin.rs index 509670e36bdb..8b0498d75624 100644 --- a/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin.rs +++ b/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin.rs @@ -10,20 +10,22 @@ use windows_sys::Win32::Security::OBJECT_INHERIT_ACE; use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_EXECUTE; use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_READ; +#[cfg(test)] +#[path = "setup_runtime_bin_tests.rs"] +mod tests; + pub(super) fn ensure_codex_app_runtime_paths_readable( sandbox_group_psid: *mut c_void, refresh_errors: &mut Vec, log: &mut dyn Write, ) -> Result<()> { - let local_app_data = local_app_data_root(); - let Some(local_app_data) = local_app_data else { - return Ok(()); - }; - let read_execute_mask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE; - let codex_root = local_app_data.join("OpenAI").join("Codex"); + let runtime_paths = runtime_paths( + local_app_data_root(), + std::env::var_os("USERPROFILE").map(PathBuf::from), + ); - for runtime_path in [codex_root.join("bin"), codex_root.join("runtimes")] { + for runtime_path in runtime_paths { if !runtime_path.is_dir() { continue; } @@ -86,6 +88,20 @@ pub(super) fn ensure_codex_app_runtime_paths_readable( Ok(()) } +fn runtime_paths(local_app_data: Option, user_profile: Option) -> Vec { + let mut runtime_paths = Vec::new(); + if let Some(local_app_data) = local_app_data { + let codex_root = local_app_data.join("OpenAI").join("Codex"); + runtime_paths.extend([codex_root.join("bin"), codex_root.join("runtimes")]); + } + // The managed primary runtime is installed outside the LocalAppData runtime roots. + if let Some(user_profile) = user_profile { + runtime_paths.push(user_profile.join(".cache").join("codex-runtimes")); + } + + runtime_paths +} + fn local_app_data_root() -> Option { std::env::var_os("LOCALAPPDATA") .map(PathBuf::from) diff --git a/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin_tests.rs b/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin_tests.rs new file mode 100644 index 000000000000..a3fa300d0beb --- /dev/null +++ b/codex-rs/windows-sandbox-rs/src/bin/setup_main/win/setup_runtime_bin_tests.rs @@ -0,0 +1,28 @@ +use super::runtime_paths; +use pretty_assertions::assert_eq; +use std::path::PathBuf; + +#[test] +fn runtime_paths_include_desktop_and_primary_runtime_roots() { + let local_app_data = PathBuf::from(r"C:\Users\user\AppData\Local"); + let user_profile = PathBuf::from(r"C:\Users\user"); + + assert_eq!( + runtime_paths(Some(local_app_data), Some(user_profile)), + vec![ + PathBuf::from(r"C:\Users\user\AppData\Local\OpenAI\Codex\bin"), + PathBuf::from(r"C:\Users\user\AppData\Local\OpenAI\Codex\runtimes"), + PathBuf::from(r"C:\Users\user\.cache\codex-runtimes"), + ] + ); +} + +#[test] +fn primary_runtime_path_does_not_depend_on_local_app_data() { + let user_profile = PathBuf::from(r"C:\Users\user"); + + assert_eq!( + runtime_paths(/*local_app_data*/ None, Some(user_profile)), + vec![PathBuf::from(r"C:\Users\user\.cache\codex-runtimes")] + ); +}