Skip to content

Commit

Permalink
windows: basic support for GetUserProfileDirectoryW
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Apr 23, 2024
1 parent bafa392 commit 2545a84
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 2 deletions.
49 changes: 49 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
58 changes: 57 additions & 1 deletion src/shims/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,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"
);
}

Ok(match directories::UserDirs::new() {
Some(dirs) => {
let home = dirs.home_dir();
let size_avail = if this.ptr_is_null(size.ptr())? {
0
} 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 {
const ERROR_INSUFFICIENT_BUFFER: u32 = 122u32;
this.set_last_error(Scalar::from_u32(ERROR_INSUFFICIENT_BUFFER))?;
Scalar::from_i32(0) // return FALSE
}
}
None => {
const ERROR_BAD_USER_PROFILE: u32 = 1253u32;
this.set_last_error(Scalar::from_u32(ERROR_BAD_USER_PROFILE))?;
Scalar::from_i32(0) // return FALSE
}
})
}
}
6 changes: 6 additions & 0 deletions src/shims/windows/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" => {
Expand Down
1 change: 0 additions & 1 deletion tests/pass/shims/env/home.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//@ignore-target-windows: home_dir is not supported on Windows
//@compile-flags: -Zmiri-disable-isolation
use std::env;

Expand Down

0 comments on commit 2545a84

Please sign in to comment.