diff options
| author | Ralf Jung <post@ralfj.de> | 2024-04-23 09:34:49 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-04-24 08:48:59 +0200 |
| commit | 342943bc7728198dd92e8adb536dbd608a5dfcec (patch) | |
| tree | 3a52f12bf314e98d622df11701d93dd6a536866f | |
| parent | 26faaa30475a1be4cc26e13882e8d943df91f3d1 (diff) | |
| download | rust-342943bc7728198dd92e8adb536dbd608a5dfcec.tar.gz rust-342943bc7728198dd92e8adb536dbd608a5dfcec.zip | |
windows: basic support for GetUserProfileDirectoryW
| -rw-r--r-- | src/tools/miri/Cargo.lock | 49 | ||||
| -rw-r--r-- | src/tools/miri/Cargo.toml | 1 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/env.rs | 58 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/windows/foreign_items.rs | 6 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/shims/env/home.rs | 2 |
5 files changed, 114 insertions, 2 deletions
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 1e6b5502b04..293b937a5e5 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -300,6 +300,27 @@ dependencies = [ ] [[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] name = "encode_unicode" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -491,6 +512,16 @@ dependencies = [ ] [[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.4.2", + "libc", +] + +[[package]] name = "linux-raw-sys" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -558,6 +589,7 @@ dependencies = [ "chrono", "colored", "ctrlc", + "directories", "getrandom", "jemalloc-sys", "lazy_static", @@ -615,6 +647,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] name = "owo-colors" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -747,6 +785,17 @@ dependencies = [ ] [[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] name = "regex" version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 7748d630b12..b00dae784d2 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -25,6 +25,7 @@ aes = { version = "0.8.3", features = ["hazmat"] } measureme = "11" ctrlc = "3.2.5" chrono = { version = "0.4.38", default-features = false, features = ["clock"] } +directories = "5" # Copied from `compiler/rustc/Cargo.toml`. # But only for some targets, it fails for others. Rustc configures this in its CI, but we can't diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index d97873ce722..22571d0c1c2 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -494,9 +494,65 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> { let this = self.eval_context_mut(); this.assert_target_os("windows", "GetCurrentProcessId"); - this.check_no_isolation("`GetCurrentProcessId`")?; Ok(std::process::id()) } + + #[allow(non_snake_case)] + fn GetUserProfileDirectoryW( + &mut self, + token: &OpTy<'tcx, Provenance>, // HANDLE + buf: &OpTy<'tcx, Provenance>, // LPWSTR + size: &OpTy<'tcx, Provenance>, // LPDWORD + ) -> InterpResult<'tcx, Scalar<Provenance>> // returns BOOL + { + let this = self.eval_context_mut(); + this.assert_target_os("windows", "GetUserProfileDirectoryW"); + this.check_no_isolation("`GetUserProfileDirectoryW`")?; + + let token = this.read_target_isize(token)?; + let buf = this.read_pointer(buf)?; + let size = this.deref_pointer(size)?; + + if token != -4 { + throw_unsup_format!( + "GetUserProfileDirectoryW: only CURRENT_PROCESS_TOKEN is supported" + ); + } + + // See <https://learn.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectoryw> for docs. + Ok(match directories::UserDirs::new() { + Some(dirs) => { + let home = dirs.home_dir(); + let size_avail = if this.ptr_is_null(size.ptr())? { + 0 // if the buf pointer is null, we can't write to it; `size` will be updated to the required length + } else { + this.read_scalar(&size)?.to_u32()? + }; + // Of course we cannot use `windows_check_buffer_size` here since this uses + // a different method for dealing with a too-small buffer than the other functions... + let (success, len) = this.write_path_to_wide_str( + home, + buf, + size_avail.into(), + /*truncate*/ false, + )?; + // The Windows docs just say that this is written on failure. But std + // seems to rely on it always being written. + this.write_scalar(Scalar::from_u32(len.try_into().unwrap()), &size)?; + if success { + Scalar::from_i32(1) // return TRUE + } else { + this.set_last_error(this.eval_windows("c", "ERROR_INSUFFICIENT_BUFFER"))?; + Scalar::from_i32(0) // return FALSE + } + } + None => { + // We have to pick some error code. + this.set_last_error(this.eval_windows("c", "ERROR_BAD_USER_PROFILE"))?; + Scalar::from_i32(0) // return FALSE + } + }) + } } diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index c81d6b2f7fd..cf35ecec7cf 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -135,6 +135,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.SetCurrentDirectoryW(path)?; this.write_scalar(result, dest)?; } + "GetUserProfileDirectoryW" => { + let [token, buf, size] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + let result = this.GetUserProfileDirectoryW(token, buf, size)?; + this.write_scalar(result, dest)?; + } // File related shims "NtWriteFile" => { diff --git a/src/tools/miri/tests/pass/shims/env/home.rs b/src/tools/miri/tests/pass/shims/env/home.rs index 9eb9c3af569..c237f9ed9ff 100644 --- a/src/tools/miri/tests/pass/shims/env/home.rs +++ b/src/tools/miri/tests/pass/shims/env/home.rs @@ -1,9 +1,9 @@ -//@ignore-target-windows: home_dir is not supported on Windows //@compile-flags: -Zmiri-disable-isolation use std::env; fn main() { env::remove_var("HOME"); // make sure we enter the interesting codepath + env::remove_var("USERPROFILE"); // Windows also looks as this env var #[allow(deprecated)] env::home_dir().unwrap(); } |
