Skip to content

Commit 6e11c77

Browse files
committed
Replace SHGetFolderPathW with SHGetKnownFolderPath
1 parent 6982b44 commit 6e11c77

File tree

4 files changed

+21
-14
lines changed

4 files changed

+21
-14
lines changed

crates/home/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ repository = "https://github.com/rust-lang/cargo"
1717
description = "Shared definitions of home directories."
1818

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

2222
[lints]
2323
workspace = true

crates/home/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ use std::path::{Path, PathBuf};
4444
///
4545
/// Returns the value of the `USERPROFILE` environment variable if it is set
4646
/// **and** it is not an empty string. Otherwise, it tries to determine the
47-
/// home directory by invoking the [`SHGetFolderPathW`][shgfp] function with
48-
/// [`CSIDL_PROFILE`][csidl].
47+
/// home directory by invoking the [`SHGetKnownFolderPath`][shgkfp] function with
48+
/// [`FOLDERID_Profile`][knownfolderid].
4949
///
50-
/// [shgfp]: https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw
51-
/// [csidl]: https://learn.microsoft.com/en-us/windows/win32/shell/csidl
50+
/// [shgkfp]: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
51+
/// [knownfolderid]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
5252
///
5353
/// # Examples
5454
///

crates/home/src/windows.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ use std::env;
22
use std::ffi::OsString;
33
use std::os::windows::ffi::OsStringExt;
44
use std::path::PathBuf;
5+
use std::ptr;
6+
use std::slice;
57

6-
use windows_sys::Win32::Foundation::{MAX_PATH, S_OK};
7-
use windows_sys::Win32::UI::Shell::{SHGetFolderPathW, CSIDL_PROFILE};
8+
use windows_sys::Win32::Foundation::S_OK;
9+
use windows_sys::Win32::System::Com::CoTaskMemFree;
10+
use windows_sys::Win32::UI::Shell::{FOLDERID_Profile, SHGetKnownFolderPath, KF_FLAG_DONT_VERIFY};
811

912
pub fn home_dir_inner() -> Option<PathBuf> {
1013
env::var_os("USERPROFILE")
@@ -16,15 +19,19 @@ pub fn home_dir_inner() -> Option<PathBuf> {
1619
#[cfg(not(target_vendor = "uwp"))]
1720
fn home_dir_crt() -> Option<PathBuf> {
1821
unsafe {
19-
let mut path: Vec<u16> = Vec::with_capacity(MAX_PATH as usize);
20-
match SHGetFolderPathW(0, CSIDL_PROFILE as i32, 0, 0, path.as_mut_ptr()) {
22+
let mut path = ptr::null_mut();
23+
match SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DONT_VERIFY as u32, 0, &mut path) {
2124
S_OK => {
22-
let len = wcslen(path.as_ptr());
23-
path.set_len(len);
24-
let s = OsString::from_wide(&path);
25+
let path_slice = slice::from_raw_parts(path, wcslen(path));
26+
let s = OsString::from_wide(&path_slice);
27+
CoTaskMemFree(path.cast());
2528
Some(PathBuf::from(s))
2629
}
27-
_ => None,
30+
_ => {
31+
// Free any allocated memory even on failure. A null ptr is a no-op for `CoTaskMemFree`.
32+
CoTaskMemFree(path.cast());
33+
None
34+
}
2835
}
2936
}
3037
}

src/cargo/sources/git/known_hosts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ fn user_known_host_location() -> Option<PathBuf> {
538538
// - OpenSSH (most unix platforms): Uses `pw->pw_dir` from `getpwuid()`.
539539
//
540540
// This doesn't do anything close to that. home_dir's behavior is:
541-
// - Windows: $USERPROFILE, or SHGetFolderPathW()
541+
// - Windows: $USERPROFILE, or SHGetKnownFolderPath()
542542
// - Unix: $HOME, or getpwuid_r()
543543
//
544544
// Since there is a mismatch here, the location returned here might be

0 commit comments

Comments
 (0)