@@ -6996,18 +6996,18 @@ mod tests {
69966996
69976997 #[cfg(target_os = "windows")]
69986998 {
6999- use windows_sys::Win32 ::Storage::FileSystem::FILE_RENAME_INFO ;
6999+ use windows_sys::Wdk ::Storage::FileSystem::FILE_RENAME_INFORMATION ;
70007000
70017001 assert!(
7002- std::mem::offset_of!(FILE_RENAME_INFO , FileName)
7003- < std::mem::size_of::<FILE_RENAME_INFO >(),
7002+ std::mem::offset_of!(FILE_RENAME_INFORMATION , FileName)
7003+ < std::mem::size_of::<FILE_RENAME_INFORMATION >(),
70047004 "the full fixed rename record includes padding beyond the name field offset"
70057005 );
70067006 }
70077007 }
70087008
70097009 #[test]
7010- fn windows_retained_rename_buffer_includes_the_full_fixed_record () {
7010+ fn windows_retained_rename_uses_the_native_handle_api () {
70117011 let source = include_str!("sync.rs").replace("\r\n", "\n");
70127012 let windows_rename = source
70137013 .split_once("#[cfg(target_os = \"windows\")]\nfn retained_root_rename")
@@ -7018,11 +7018,12 @@ mod tests {
70187018 .0;
70197019
70207020 assert!(windows_rename.contains(
7021- "let fixed = std::mem::size_of::<FILE_RENAME_INFO>();"
7022- ));
7023- assert!(!windows_rename.contains(
7024- "let fixed = std::mem::offset_of!(FILE_RENAME_INFO, FileName);"
7021+ "let fixed = std::mem::size_of::<FILE_RENAME_INFORMATION>();"
70257022 ));
7023+ assert!(windows_rename.contains("NtSetInformationFile("));
7024+ assert!(windows_rename.contains("FileRenameInformation"));
7025+ assert!(windows_rename.contains("RtlNtStatusToDosError(status)"));
7026+ assert!(!windows_rename.contains("SetFileInformationByHandle("));
70267027 assert!(windows_rename.contains("(*information).FileName.as_mut_ptr()"));
70277028 }
70287029
@@ -14593,17 +14594,19 @@ fn retained_root_rename(
1459314594) -> std::io::Result<()> {
1459414595 use std::os::windows::ffi::OsStrExt as _;
1459514596 use std::os::windows::io::AsRawHandle as _;
14596- use windows_sys::Win32 ::Storage::FileSystem::{
14597- FileRenameInfo, SetFileInformationByHandle, FILE_RENAME_INFO ,
14597+ use windows_sys::Wdk ::Storage::FileSystem::{
14598+ FileRenameInformation, NtSetInformationFile, FILE_RENAME_INFORMATION ,
1459814599 };
14600+ use windows_sys::Win32::Foundation::RtlNtStatusToDosError;
14601+ use windows_sys::Win32::System::IO::IO_STATUS_BLOCK;
1459914602
1460014603 let source = retained_root_open(directory, source, true, false, false)?;
1460114604 let target = destination.encode_wide().collect::<Vec<_>>();
14602- // SetFileInformationByHandle requires the variable-length record to retain
14603- // the complete fixed FILE_RENAME_INFO, including its x64 trailing padding .
14605+ // NtSetInformationFile consumes the native variable-length record while
14606+ // preserving the retained RootDirectory-relative namespace operation .
1460414607 // FileNameLength still describes only the UTF-16 payload copied at the
1460514608 // FileName field below.
14606- let fixed = std::mem::size_of::<FILE_RENAME_INFO >();
14609+ let fixed = std::mem::size_of::<FILE_RENAME_INFORMATION >();
1460714610 let target_bytes = target
1460814611 .len()
1460914612 .checked_mul(std::mem::size_of::<u16>())
@@ -14632,11 +14635,12 @@ fn retained_root_rename(
1463214635 )
1463314636 })?;
1463414637 let words = buffer_bytes.div_ceil(std::mem::size_of::<usize>());
14635- // `FILE_RENAME_INFO ` has pointer alignment; a byte vector does not promise
14636- // enough alignment for the typed header even though system allocators often
14637- // happen to provide it.
14638+ // `FILE_RENAME_INFORMATION ` has pointer alignment; a byte vector does not
14639+ // promise enough alignment for the typed header even though system allocators
14640+ // often happen to provide it.
1463814641 let mut buffer = vec![0_usize; words];
14639- let information = buffer.as_mut_ptr().cast::<FILE_RENAME_INFO>();
14642+ let information = buffer.as_mut_ptr().cast::<FILE_RENAME_INFORMATION>();
14643+ let mut status_block = IO_STATUS_BLOCK::default();
1464014644 before_mutation()?;
1464114645 unsafe {
1464214646 (*information).Anonymous.ReplaceIfExists = replace;
@@ -14647,14 +14651,17 @@ fn retained_root_rename(
1464714651 (*information).FileName.as_mut_ptr(),
1464814652 target.len(),
1464914653 );
14650- if SetFileInformationByHandle (
14654+ let status = NtSetInformationFile (
1465114655 source.as_raw_handle(),
14652- FileRenameInfo ,
14656+ &mut status_block ,
1465314657 information.cast(),
1465414658 information_bytes,
14655- ) == 0
14656- {
14657- return Err(std::io::Error::last_os_error());
14659+ FileRenameInformation,
14660+ );
14661+ if status < 0 {
14662+ return Err(std::io::Error::from_raw_os_error(
14663+ RtlNtStatusToDosError(status) as i32,
14664+ ));
1465814665 }
1465914666 }
1466014667 Ok(())
0 commit comments