From 4c05073d1d64b82ad10478324b87816cec16d74c Mon Sep 17 00:00:00 2001 From: Hugo Beauzée-Luyssen Date: Mon, 27 May 2019 17:13:04 +0200 Subject: std: win: Don't use GetFileInformationByHandle on UWP --- src/libstd/sys/windows/c.rs | 51 +++++++++++++++++++++++++++----------------- src/libstd/sys/windows/fs.rs | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 19 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index bfaa2290603..6b4d6d9e23b 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -34,7 +34,6 @@ pub type ULONG = c_ulong; pub type LPBOOL = *mut BOOL; pub type LPBYTE = *mut BYTE; -pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; pub type LPCSTR = *const CHAR; pub type LPCVOID = *const c_void; pub type LPCWSTR = *const WCHAR; @@ -341,20 +340,6 @@ pub struct WIN32_FILE_ATTRIBUTE_DATA { pub nFileSizeLow: DWORD, } -#[repr(C)] -pub struct BY_HANDLE_FILE_INFORMATION { - pub dwFileAttributes: DWORD, - pub ftCreationTime: FILETIME, - pub ftLastAccessTime: FILETIME, - pub ftLastWriteTime: FILETIME, - pub dwVolumeSerialNumber: DWORD, - pub nFileSizeHigh: DWORD, - pub nFileSizeLow: DWORD, - pub nNumberOfLinks: DWORD, - pub nFileIndexHigh: DWORD, - pub nFileIndexLow: DWORD, -} - #[repr(C)] #[allow(dead_code)] // we only use some variants pub enum FILE_INFO_BY_HANDLE_CLASS { @@ -657,6 +642,22 @@ pub struct timeval { // Functions forbidden when targeting UWP cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { + #[repr(C)] + pub struct BY_HANDLE_FILE_INFORMATION { + pub dwFileAttributes: DWORD, + pub ftCreationTime: FILETIME, + pub ftLastAccessTime: FILETIME, + pub ftLastWriteTime: FILETIME, + pub dwVolumeSerialNumber: DWORD, + pub nFileSizeHigh: DWORD, + pub nFileSizeLow: DWORD, + pub nNumberOfLinks: DWORD, + pub nFileIndexHigh: DWORD, + pub nFileIndexLow: DWORD, + } + + pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; + pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; pub const TOKEN_READ: DWORD = 0x20008; @@ -672,6 +673,9 @@ if #[cfg(not(target_vendor = "uwp"))] { pub fn GetUserProfileDirectoryW(hToken: HANDLE, lpProfileDir: LPWSTR, lpcchSize: *mut DWORD) -> BOOL; + pub fn GetFileInformationByHandle(hFile: HANDLE, + lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) + -> BOOL; pub fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL; @@ -688,7 +692,20 @@ cfg_if::cfg_if! { if #[cfg(target_vendor = "uwp")] { pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; + #[repr(C)] + pub struct FILE_STANDARD_INFO { + pub AllocationSize: LARGE_INTEGER, + pub EndOfFile: LARGE_INTEGER, + pub NumberOfLink: DWORD, + pub DeletePending: BOOLEAN, + pub Directory: BOOLEAN, + } + extern "system" { + pub fn GetFileInformationByHandleEx(hFile: HANDLE, + fileInfoClass: FILE_INFO_BY_HANDLE_CLASS, + lpFileInformation: LPVOID, + dwBufferSize: DWORD) -> BOOL; pub fn BCryptGenRandom(hAlgorithm: LPVOID, pBuffer: *mut u8, cbBuffer: ULONG, dwFlags: ULONG) -> LONG; } @@ -752,10 +769,6 @@ extern "system" { pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; - pub fn GetFileInformationByHandle(hFile: HANDLE, - lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) - -> BOOL; - pub fn SetLastError(dwErrCode: DWORD); pub fn GetCommandLineW() -> *mut LPCWSTR; pub fn GetTempPathW(nBufferLength: DWORD, diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index f6f64a008bb..2f158c01406 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -287,6 +287,7 @@ impl File { Ok(()) } + #[cfg(not(target_vendor = "uwp"))] pub fn file_attr(&self) -> io::Result { unsafe { let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed(); @@ -310,6 +311,49 @@ impl File { } } + #[cfg(target_vendor = "uwp")] + pub fn file_attr(&self) -> io::Result { + unsafe { + let mut info: c::FILE_BASIC_INFO = mem::zeroed(); + let size = mem::size_of_val(&info); + cvt(c::GetFileInformationByHandleEx(self.handle.raw(), + c::FileBasicInfo, + &mut info as *mut _ as *mut libc::c_void, + size as c::DWORD))?; + let mut attr = FileAttr { + attributes: info.FileAttributes, + creation_time: c::FILETIME { + dwLowDateTime: info.CreationTime as c::DWORD, + dwHighDateTime: (info.CreationTime >> 32) as c::DWORD, + }, + last_access_time: c::FILETIME { + dwLowDateTime: info.LastAccessTime as c::DWORD, + dwHighDateTime: (info.LastAccessTime >> 32) as c::DWORD, + }, + last_write_time: c::FILETIME { + dwLowDateTime: info.LastWriteTime as c::DWORD, + dwHighDateTime: (info.LastWriteTime >> 32) as c::DWORD, + }, + file_size: 0, + reparse_tag: 0, + }; + let mut info: c::FILE_STANDARD_INFO = mem::zeroed(); + let size = mem::size_of_val(&info); + cvt(c::GetFileInformationByHandleEx(self.handle.raw(), + c::FileStandardInfo, + &mut info as *mut _ as *mut libc::c_void, + size as c::DWORD))?; + attr.file_size = info.AllocationSize as u64; + if attr.is_reparse_point() { + let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + if let Ok((_, buf)) = self.reparse_point(&mut b) { + attr.reparse_tag = buf.ReparseTag; + } + } + Ok(attr) + } + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { self.handle.read(buf) } -- cgit 1.4.1-3-g733a5