diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 4aa76f201f5ef..a00db6f84b49a 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -282,7 +282,7 @@ pub unsafe fn NtReadFile( byteoffset: Option<&LARGE_INTEGER>, key: Option<&ULONG>, ) -> NTSTATUS { - windows_sys::NtReadFile( + ntdll::NtReadFile( filehandle.as_raw_handle(), event, apcroutine, @@ -305,7 +305,7 @@ pub unsafe fn NtWriteFile( byteoffset: Option<&LARGE_INTEGER>, key: Option<&ULONG>, ) -> NTSTATUS { - windows_sys::NtWriteFile( + ntdll::NtWriteFile( filehandle.as_raw_handle(), event, apcroutine, @@ -565,6 +565,53 @@ pub const RtlGenRandom: unsafe fn( randombufferlength: u32, ) -> BOOLEAN = SystemFunction036; +compat_fn_lazy! { + pub static NTDLL: &CStr = c"ntdll" => { load: true, unicows: false }; + + pub fn NtCreateFile( + filehandle: *mut HANDLE, + desiredaccess: FILE_ACCESS_RIGHTS, + objectattributes: *const OBJECT_ATTRIBUTES, + iostatusblock: *mut IO_STATUS_BLOCK, + allocationsize: *const i64, + fileattributes: FILE_FLAGS_AND_ATTRIBUTES, + shareaccess: FILE_SHARE_MODE, + createdisposition: NTCREATEFILE_CREATE_DISPOSITION, + createoptions: NTCREATEFILE_CREATE_OPTIONS, + eabuffer: *const ::core::ffi::c_void, + ealength: u32, + ) -> NTSTATUS; +} + +pub mod ntdll { + use super::*; + compat_fn_lazy! { + pub static NTDLL: &CStr = c"ntdll" => { load: true, unicows: false }; + + pub fn NtReadFile( + filehandle: HANDLE, + event: HANDLE, + apcroutine: PIO_APC_ROUTINE, + apccontext: *const ::core::ffi::c_void, + iostatusblock: *mut IO_STATUS_BLOCK, + buffer: *mut ::core::ffi::c_void, + length: u32, + byteoffset: *const i64, + key: *const u32, + ) -> NTSTATUS; + pub fn NtWriteFile( + filehandle: HANDLE, + event: HANDLE, + apcroutine: PIO_APC_ROUTINE, + apccontext: *const ::core::ffi::c_void, + iostatusblock: *mut IO_STATUS_BLOCK, + buffer: *const ::core::ffi::c_void, + length: u32, + byteoffset: *const i64, + key: *const u32, + ) -> NTSTATUS; + } +} compat_fn_with_fallback! { pub static NTDLL: &CStr = c"ntdll" => { load: true, unicows: false }; @@ -592,53 +639,6 @@ compat_fn_with_fallback! { ) -> NTSTATUS { panic!("keyed events not available") } - - // These functions are available on UWP when lazily loaded. They will fail WACK if loaded statically. - #[cfg(target_vendor = "uwp")] - pub fn NtCreateFile( - filehandle: *mut HANDLE, - desiredaccess: FILE_ACCESS_RIGHTS, - objectattributes: *const OBJECT_ATTRIBUTES, - iostatusblock: *mut IO_STATUS_BLOCK, - allocationsize: *const i64, - fileattributes: FILE_FLAGS_AND_ATTRIBUTES, - shareaccess: FILE_SHARE_MODE, - createdisposition: NTCREATEFILE_CREATE_DISPOSITION, - createoptions: NTCREATEFILE_CREATE_OPTIONS, - eabuffer: *const ::core::ffi::c_void, - ealength: u32 - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - #[cfg(target_vendor = "uwp")] - pub fn NtReadFile( - filehandle: BorrowedHandle<'_>, - event: HANDLE, - apcroutine: PIO_APC_ROUTINE, - apccontext: *mut c_void, - iostatusblock: &mut IO_STATUS_BLOCK, - buffer: *mut crate::mem::MaybeUninit, - length: ULONG, - byteoffset: Option<&LARGE_INTEGER>, - key: Option<&ULONG> - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - #[cfg(target_vendor = "uwp")] - pub fn NtWriteFile( - filehandle: BorrowedHandle<'_>, - event: HANDLE, - apcroutine: PIO_APC_ROUTINE, - apccontext: *mut c_void, - iostatusblock: &mut IO_STATUS_BLOCK, - buffer: *const u8, - length: ULONG, - byteoffset: Option<&LARGE_INTEGER>, - key: Option<&ULONG> - ) -> NTSTATUS { - STATUS_NOT_IMPLEMENTED - } - #[cfg(target_vendor = "uwp")] pub fn RtlNtStatusToDosError(Status: NTSTATUS) -> u32 { Status as u32 } diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index fd32e522b8bd1..acc958485d92b 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1133,6 +1133,22 @@ fn open_link(path: &Path, access_mode: u32) -> io::Result { } pub fn remove_dir_all(path: &Path) -> io::Result<()> { + // if the modern file/directory APIs are not available, we'll fall back to the old (unsafe, see + // https://github.com/rust-lang/rust/pull/93112) directory removal implementation + if c::NtCreateFile::option().is_none() + || c::GetFileInformationByHandleEx::option().is_none() + || c::SetFileInformationByHandle::option().is_none() + { + let filetype = lstat(path)?.file_type(); + if filetype.is_symlink() { + // On Windows symlinks to files and directories are removed differently. + // rmdir only deletes dir symlinks and junctions, not file symlinks. + return rmdir(path); + } else { + return remove_dir_all_recursive_old(path); + } + } + let file = open_link(path, c::DELETE | c::FILE_LIST_DIRECTORY)?; // Test if the file is not a directory or a symlink to a directory. @@ -1232,6 +1248,21 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io Ok(()) } +fn remove_dir_all_recursive_old(path: &Path) -> io::Result<()> { + for child in readdir(path)? { + let child = child?; + let child_type = child.file_type()?; + if child_type.is_dir() { + remove_dir_all_recursive_old(&child.path())?; + } else if child_type.is_symlink_dir() { + rmdir(&child.path())?; + } else { + unlink(&child.path())?; + } + } + rmdir(path) +} + pub fn readlink(path: &Path) -> io::Result { // Open the link with no access mode, instead of generic read. // By default FILE_LIST_DIRECTORY is denied for the junction "C:\Documents and Settings", so