Skip to content

Commit

Permalink
Rollup merge of rust-lang#124282 - RalfJung:fill_utf16_buf, r=ChrisDe…
Browse files Browse the repository at this point in the history
…nton

windows fill_utf16_buf: explain the expected return value

The comment just says "return what the syscall returns", but that doesn't work for all syscalls as the Windows API is not consistent in how buffer size is negotiated. For instance, GetUserProfileDirectoryW works a bit differently, and so home_dir_crt has to translate this to the usual protocol itself. So it's worth describing that protocol.

r? `@ChrisDenton`
  • Loading branch information
fmease committed Apr 24, 2024
2 parents b55ec5b + a21c2d8 commit 78b5915
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 5 deletions.
17 changes: 12 additions & 5 deletions library/std/src/sys/pal/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,21 @@ pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
// currently reside in the buffer. This function is an abstraction over these
// functions by making them easier to call.
//
// The first callback, `f1`, is yielded a (pointer, len) pair which can be
// The first callback, `f1`, is passed a (pointer, len) pair which can be
// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case).
// The closure is expected to return what the syscall returns which will be
// interpreted by this function to determine if the syscall needs to be invoked
// again (with more buffer space).
// The closure is expected to:
// - On success, return the actual length of the written data *without* the null terminator.
// This can be 0. In this case the last_error must be left unchanged.
// - On insufficient buffer space,
// - either return the required length *with* the null terminator,
// - or set the last-error to ERROR_INSUFFICIENT_BUFFER and return `len`.
// - On other failure, return 0 and set last_error.
//
// This is how most but not all syscalls indicate the required buffer space.
// Other syscalls may need translation to match this protocol.
//
// Once the syscall has completed (errors bail out early) the second closure is
// yielded the data which has been read from the syscall. The return value
// passed the data which has been read from the syscall. The return value
// from this closure is then the return value of the function.
pub fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
where
Expand Down
2 changes: 2 additions & 0 deletions library/std/src/sys/pal/windows/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ fn home_dir_crt() -> Option<PathBuf> {

super::fill_utf16_buf(
|buf, mut sz| {
// GetUserProfileDirectoryW does not quite use the usual protocol for
// negotiating the buffer size, so we have to translate.
match c::GetUserProfileDirectoryW(
ptr::without_provenance_mut(CURRENT_PROCESS_TOKEN),
buf,
Expand Down

0 comments on commit 78b5915

Please sign in to comment.