std: win: Don't use GetFileInformationByHandle on UWP

This commit is contained in:
Hugo Beauzée-Luyssen 2019-05-27 17:13:04 +02:00
parent a24be59b46
commit 4c05073d1d
2 changed files with 76 additions and 19 deletions

View file

@ -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,

View file

@ -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)
}