Skip to content

Commit

Permalink
Auto merge of #13173 - ChrisDenton:SHGetKnownFolderPath, r=weihanglo
Browse files Browse the repository at this point in the history
Replace SHGetFolderPathW with SHGetKnownFolderPath

### What does this PR try to resolve?

Resolves #13138 by replacing `SHGetFolderPathW` with `SHGetKnownFolderPath`.

### How should we test and review this PR?

Aside from running the existing tests, this introduces two new functions whose documentation you may want to double check: [`SHGetKnownFolderPath`](https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath) and [`CoTaskMemFree`](https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemfree).
  • Loading branch information
bors committed Dec 15, 2023
2 parents 6982b44 + 6e11c77 commit e9a1b4b
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 14 deletions.
2 changes: 1 addition & 1 deletion crates/home/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repository = "https://github.com/rust-lang/cargo"
description = "Shared definitions of home directories."

[target.'cfg(windows)'.dependencies]
windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_UI_Shell"] }
windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_System_Com"] }

[lints]
workspace = true
8 changes: 4 additions & 4 deletions crates/home/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ use std::path::{Path, PathBuf};
///
/// Returns the value of the `USERPROFILE` environment variable if it is set
/// **and** it is not an empty string. Otherwise, it tries to determine the
/// home directory by invoking the [`SHGetFolderPathW`][shgfp] function with
/// [`CSIDL_PROFILE`][csidl].
/// home directory by invoking the [`SHGetKnownFolderPath`][shgkfp] function with
/// [`FOLDERID_Profile`][knownfolderid].
///
/// [shgfp]: https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw
/// [csidl]: https://learn.microsoft.com/en-us/windows/win32/shell/csidl
/// [shgkfp]: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
/// [knownfolderid]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
///
/// # Examples
///
Expand Down
23 changes: 15 additions & 8 deletions crates/home/src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ use std::env;
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use std::path::PathBuf;
use std::ptr;
use std::slice;

use windows_sys::Win32::Foundation::{MAX_PATH, S_OK};
use windows_sys::Win32::UI::Shell::{SHGetFolderPathW, CSIDL_PROFILE};
use windows_sys::Win32::Foundation::S_OK;
use windows_sys::Win32::System::Com::CoTaskMemFree;
use windows_sys::Win32::UI::Shell::{FOLDERID_Profile, SHGetKnownFolderPath, KF_FLAG_DONT_VERIFY};

pub fn home_dir_inner() -> Option<PathBuf> {
env::var_os("USERPROFILE")
Expand All @@ -16,15 +19,19 @@ pub fn home_dir_inner() -> Option<PathBuf> {
#[cfg(not(target_vendor = "uwp"))]
fn home_dir_crt() -> Option<PathBuf> {
unsafe {
let mut path: Vec<u16> = Vec::with_capacity(MAX_PATH as usize);
match SHGetFolderPathW(0, CSIDL_PROFILE as i32, 0, 0, path.as_mut_ptr()) {
let mut path = ptr::null_mut();
match SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DONT_VERIFY as u32, 0, &mut path) {
S_OK => {
let len = wcslen(path.as_ptr());
path.set_len(len);
let s = OsString::from_wide(&path);
let path_slice = slice::from_raw_parts(path, wcslen(path));
let s = OsString::from_wide(&path_slice);
CoTaskMemFree(path.cast());
Some(PathBuf::from(s))
}
_ => None,
_ => {
// Free any allocated memory even on failure. A null ptr is a no-op for `CoTaskMemFree`.
CoTaskMemFree(path.cast());
None
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/sources/git/known_hosts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ fn user_known_host_location() -> Option<PathBuf> {
// - OpenSSH (most unix platforms): Uses `pw->pw_dir` from `getpwuid()`.
//
// This doesn't do anything close to that. home_dir's behavior is:
// - Windows: $USERPROFILE, or SHGetFolderPathW()
// - Windows: $USERPROFILE, or SHGetKnownFolderPath()
// - Unix: $HOME, or getpwuid_r()
//
// Since there is a mismatch here, the location returned here might be
Expand Down

0 comments on commit e9a1b4b

Please sign in to comment.