Skip to content

Commit 342943b

Browse files
committed
windows: basic support for GetUserProfileDirectoryW
1 parent 26faaa3 commit 342943b

File tree

5 files changed

+114
-2
lines changed

5 files changed

+114
-2
lines changed

src/tools/miri/Cargo.lock

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,27 @@ dependencies = [
299299
"windows-sys 0.52.0",
300300
]
301301

302+
[[package]]
303+
name = "directories"
304+
version = "5.0.1"
305+
source = "registry+https://github.com/rust-lang/crates.io-index"
306+
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
307+
dependencies = [
308+
"dirs-sys",
309+
]
310+
311+
[[package]]
312+
name = "dirs-sys"
313+
version = "0.4.1"
314+
source = "registry+https://github.com/rust-lang/crates.io-index"
315+
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
316+
dependencies = [
317+
"libc",
318+
"option-ext",
319+
"redox_users",
320+
"windows-sys 0.48.0",
321+
]
322+
302323
[[package]]
303324
name = "encode_unicode"
304325
version = "0.3.6"
@@ -490,6 +511,16 @@ dependencies = [
490511
"windows-sys 0.48.0",
491512
]
492513

514+
[[package]]
515+
name = "libredox"
516+
version = "0.1.3"
517+
source = "registry+https://github.com/rust-lang/crates.io-index"
518+
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
519+
dependencies = [
520+
"bitflags 2.4.2",
521+
"libc",
522+
]
523+
493524
[[package]]
494525
name = "linux-raw-sys"
495526
version = "0.4.13"
@@ -558,6 +589,7 @@ dependencies = [
558589
"chrono",
559590
"colored",
560591
"ctrlc",
592+
"directories",
561593
"getrandom",
562594
"jemalloc-sys",
563595
"lazy_static",
@@ -614,6 +646,12 @@ version = "1.19.0"
614646
source = "registry+https://github.com/rust-lang/crates.io-index"
615647
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
616648

649+
[[package]]
650+
name = "option-ext"
651+
version = "0.2.0"
652+
source = "registry+https://github.com/rust-lang/crates.io-index"
653+
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
654+
617655
[[package]]
618656
name = "owo-colors"
619657
version = "3.5.0"
@@ -746,6 +784,17 @@ dependencies = [
746784
"bitflags 1.3.2",
747785
]
748786

787+
[[package]]
788+
name = "redox_users"
789+
version = "0.4.5"
790+
source = "registry+https://github.com/rust-lang/crates.io-index"
791+
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
792+
dependencies = [
793+
"getrandom",
794+
"libredox",
795+
"thiserror",
796+
]
797+
749798
[[package]]
750799
name = "regex"
751800
version = "1.10.3"

src/tools/miri/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ aes = { version = "0.8.3", features = ["hazmat"] }
2525
measureme = "11"
2626
ctrlc = "3.2.5"
2727
chrono = { version = "0.4.38", default-features = false, features = ["clock"] }
28+
directories = "5"
2829

2930
# Copied from `compiler/rustc/Cargo.toml`.
3031
# But only for some targets, it fails for others. Rustc configures this in its CI, but we can't

src/tools/miri/src/shims/env.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,65 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
494494
fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> {
495495
let this = self.eval_context_mut();
496496
this.assert_target_os("windows", "GetCurrentProcessId");
497-
498497
this.check_no_isolation("`GetCurrentProcessId`")?;
499498

500499
Ok(std::process::id())
501500
}
501+
502+
#[allow(non_snake_case)]
503+
fn GetUserProfileDirectoryW(
504+
&mut self,
505+
token: &OpTy<'tcx, Provenance>, // HANDLE
506+
buf: &OpTy<'tcx, Provenance>, // LPWSTR
507+
size: &OpTy<'tcx, Provenance>, // LPDWORD
508+
) -> InterpResult<'tcx, Scalar<Provenance>> // returns BOOL
509+
{
510+
let this = self.eval_context_mut();
511+
this.assert_target_os("windows", "GetUserProfileDirectoryW");
512+
this.check_no_isolation("`GetUserProfileDirectoryW`")?;
513+
514+
let token = this.read_target_isize(token)?;
515+
let buf = this.read_pointer(buf)?;
516+
let size = this.deref_pointer(size)?;
517+
518+
if token != -4 {
519+
throw_unsup_format!(
520+
"GetUserProfileDirectoryW: only CURRENT_PROCESS_TOKEN is supported"
521+
);
522+
}
523+
524+
// See <https://learn.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectoryw> for docs.
525+
Ok(match directories::UserDirs::new() {
526+
Some(dirs) => {
527+
let home = dirs.home_dir();
528+
let size_avail = if this.ptr_is_null(size.ptr())? {
529+
0 // if the buf pointer is null, we can't write to it; `size` will be updated to the required length
530+
} else {
531+
this.read_scalar(&size)?.to_u32()?
532+
};
533+
// Of course we cannot use `windows_check_buffer_size` here since this uses
534+
// a different method for dealing with a too-small buffer than the other functions...
535+
let (success, len) = this.write_path_to_wide_str(
536+
home,
537+
buf,
538+
size_avail.into(),
539+
/*truncate*/ false,
540+
)?;
541+
// The Windows docs just say that this is written on failure. But std
542+
// seems to rely on it always being written.
543+
this.write_scalar(Scalar::from_u32(len.try_into().unwrap()), &size)?;
544+
if success {
545+
Scalar::from_i32(1) // return TRUE
546+
} else {
547+
this.set_last_error(this.eval_windows("c", "ERROR_INSUFFICIENT_BUFFER"))?;
548+
Scalar::from_i32(0) // return FALSE
549+
}
550+
}
551+
None => {
552+
// We have to pick some error code.
553+
this.set_last_error(this.eval_windows("c", "ERROR_BAD_USER_PROFILE"))?;
554+
Scalar::from_i32(0) // return FALSE
555+
}
556+
})
557+
}
502558
}

src/tools/miri/src/shims/windows/foreign_items.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
135135
let result = this.SetCurrentDirectoryW(path)?;
136136
this.write_scalar(result, dest)?;
137137
}
138+
"GetUserProfileDirectoryW" => {
139+
let [token, buf, size] =
140+
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
141+
let result = this.GetUserProfileDirectoryW(token, buf, size)?;
142+
this.write_scalar(result, dest)?;
143+
}
138144

139145
// File related shims
140146
"NtWriteFile" => {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
//@ignore-target-windows: home_dir is not supported on Windows
21
//@compile-flags: -Zmiri-disable-isolation
32
use std::env;
43

54
fn main() {
65
env::remove_var("HOME"); // make sure we enter the interesting codepath
6+
env::remove_var("USERPROFILE"); // Windows also looks as this env var
77
#[allow(deprecated)]
88
env::home_dir().unwrap();
99
}

0 commit comments

Comments
 (0)