diff --git a/apps/ai-game-creator-shell/src-tauri/src/config.rs b/apps/ai-game-creator-shell/src-tauri/src/config.rs index e32c70bb5..b66b976af 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/config.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/config.rs @@ -1319,12 +1319,10 @@ pub(crate) fn ensure_game_creator_private_directory_tree( #[cfg(all(windows, test))] initialize_windows_game_creator_directory_owner_for_current_user(&directory)?; #[cfg(windows)] - // This invocation created the directory, so initialize its - // owner/DACL in-process. Marker-based managed-path detection - // must not route a newly-created descendant into UAC. - secure_windows_game_creator_path_for_current_user_with_owner_policy( - &directory, true, true, true, - )?; + // This invocation created the directory: initialize it in + // process first, with a narrowly-scoped managed-path fallback + // only if Windows rejects that local ACL update. + harden_new_game_creator_private_path(&directory, true, label)?; #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; @@ -1363,11 +1361,7 @@ pub(crate) fn ensure_game_creator_private_directory_tree( fs::create_dir(&directory).map_err(|retry_error| { format!("创建 {label} 失败:{}: {retry_error}", directory.display()) })?; - // The retry also created this directory in the current - // process; keep it on the local hardening path. - secure_windows_game_creator_path_for_current_user_with_owner_policy( - &directory, true, true, true, - )?; + harden_new_game_creator_private_path(&directory, true, label)?; } Err(error) => { return Err(format!( @@ -1432,15 +1426,34 @@ pub(crate) fn harden_new_game_creator_private_path( path.display() )); } - // This invocation created the object, so its owner is the current - // user. Tighten the inherited descriptor in-process; UAC repair is - // reserved for existing, externally-owned objects. - secure_windows_game_creator_path_for_current_user_with_owner_policy( - path, - is_directory, - true, - true, - )?; + // This invocation created the object, so local hardening is always + // the first path. Some Windows configurations can nevertheless + // reject the descriptor update (for example when an inherited ACL is + // protected by the parent). Only a managed path may use the existing + // one-shot repair in that exceptional case; ordinary new projects do + // not prompt for UAC. + if let Err(local_error) = + secure_windows_game_creator_path_for_current_user_with_owner_policy( + path, + is_directory, + true, + true, + ) + { + if !game_creator_private_path_allows_auto_elevation(path) + || !windows_acl_error_may_need_elevation(&local_error) + { + return Err(local_error); + } + secure_windows_game_creator_path_for_current_user_with_auto_elevation( + path, + is_directory, + true, + ) + .map_err(|repair_error| { + format!("{local_error};新建对象的受控 ACL 修复未完成:{repair_error}") + })?; + } } #[cfg(unix)] {