Skip to content

Commit

Permalink
std: win: Don't use GetFileInformationByHandle on UWP
Browse files Browse the repository at this point in the history
  • Loading branch information
chouquette committed Jul 25, 2019
1 parent a24be59 commit 4c05073
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 19 deletions.
51 changes: 32 additions & 19 deletions src/libstd/sys/windows/c.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down
44 changes: 44 additions & 0 deletions src/libstd/sys/windows/fs.rs
Expand Up @@ -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();
Expand All @@ -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)
}
Expand Down

0 comments on commit 4c05073

Please sign in to comment.