Skip to content

Commit 8c64bbf

Browse files
committed
Add doc and choose suitable name for Win32 path prefixes
1 parent d831760 commit 8c64bbf

File tree

1 file changed

+9
-10
lines changed

1 file changed

+9
-10
lines changed

src/internals.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ use cast::BytesAsReparseDataBuffer;
1414

1515
/// This prefix indicates to NTFS that the path is to be treated as a non-interpreted
1616
/// path in the virtual file system.
17-
const NON_INTERPRETED_PATH_PREFIX: [u16; 4] = helpers::utf16s(br"\??\");
17+
/// Ref: <https://learn.microsoft.com/windows-hardware/drivers/kernel/object-manager>
18+
const NT_PREFIX: [u16; 4] = helpers::utf16s(br"\??\");
19+
/// Disables normalization and bypasses MAX_PATH.
20+
/// Ref: <https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry>
21+
const VERBATIM_PREFIX: [u16; 4] = helpers::utf16s(br"\\?\");
1822

1923
const WCHAR_SIZE: u16 = size_of::<u16>() as _;
2024

@@ -30,13 +34,12 @@ pub fn create(target: &Path, junction: &Path) -> io::Result<()> {
3034
// canonicalize the path first.
3135
let target = helpers::get_full_path(target)?;
3236
// Strip Win32 verbatim prefix (\\?\) if present - we add NT prefix (\??\) ourselves
33-
const VERBATIM_PREFIX: [u16; 4] = helpers::utf16s(br"\\?\");
3437
let target = target.strip_prefix(VERBATIM_PREFIX.as_slice()).unwrap_or(&target);
3538
fs::create_dir(junction)?;
3639
let file = helpers::open_reparse_point(junction, true)?;
3740
let target_len_in_bytes = {
3841
// "\??\" + target
39-
let len = NON_INTERPRETED_PATH_PREFIX.len().saturating_add(target.len());
42+
let len = NT_PREFIX.len().saturating_add(target.len());
4043
let min_len = cmp::min(len, u16::MAX as usize) as u16;
4144
// Len without `UNICODE_NULL` at the end
4245
let target_len_in_bytes = min_len.saturating_mul(WCHAR_SIZE);
@@ -65,14 +68,10 @@ pub fn create(target: &Path, junction: &Path) -> io::Result<()> {
6568

6669
let mut path_buffer_ptr: *mut u16 = addr_of_mut!((*rdb).ReparseBuffer.PathBuffer).cast();
6770
// Safe because we checked `MAX_AVAILABLE_PATH_BUFFER`
68-
copy_nonoverlapping(
69-
NON_INTERPRETED_PATH_PREFIX.as_ptr(),
70-
path_buffer_ptr,
71-
NON_INTERPRETED_PATH_PREFIX.len(),
72-
);
71+
copy_nonoverlapping(NT_PREFIX.as_ptr(), path_buffer_ptr, NT_PREFIX.len());
7372
// TODO: Do we need to write the NULL-terminator byte?
7473
// It looks like libuv does that.
75-
path_buffer_ptr = path_buffer_ptr.add(NON_INTERPRETED_PATH_PREFIX.len());
74+
path_buffer_ptr = path_buffer_ptr.add(NT_PREFIX.len());
7675
copy_nonoverlapping(target.as_ptr(), path_buffer_ptr, target.len());
7776

7877
// Set the total size of the data buffer
@@ -123,7 +122,7 @@ pub fn get_target(junction: &Path) -> io::Result<PathBuf> {
123122
slice::from_raw_parts(buf, len as usize)
124123
};
125124
// In case of "\??\C:\foo\bar"
126-
let wide = wide.strip_prefix(&NON_INTERPRETED_PATH_PREFIX).unwrap_or(wide);
125+
let wide = wide.strip_prefix(&NT_PREFIX).unwrap_or(wide);
127126
Ok(PathBuf::from(OsString::from_wide(wide)))
128127
} else {
129128
Err(io::Error::new(io::ErrorKind::Other, "not a reparse tag mount point"))

0 commit comments

Comments
 (0)