about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHugo Beauzée-Luyssen <hugo@beauzee.fr>2019-05-27 17:13:04 +0200
committerHugo Beauzée-Luyssen <hugo@beauzee.fr>2019-07-25 21:30:08 +0200
commit4c05073d1d64b82ad10478324b87816cec16d74c (patch)
treefef661163802cc44939fc0cbde2e190ed54790e7
parenta24be59b4693d41634ad22815b4d973440ff0b30 (diff)
downloadrust-4c05073d1d64b82ad10478324b87816cec16d74c.tar.gz
rust-4c05073d1d64b82ad10478324b87816cec16d74c.zip
std: win: Don't use GetFileInformationByHandle on UWP
-rw-r--r--src/libstd/sys/windows/c.rs51
-rw-r--r--src/libstd/sys/windows/fs.rs44
2 files changed, 76 insertions, 19 deletions
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;
@@ -342,20 +341,6 @@ pub struct WIN32_FILE_ATTRIBUTE_DATA {
 }
 
 #[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 {
     FileBasicInfo                   = 0,
@@ -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<FileAttr> {
         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<FileAttr> {
+        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<usize> {
         self.handle.read(buf)
     }