Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for UWP targets #60260

Merged
merged 13 commits into from
Jul 26, 2019
Merged
Prev Previous commit
Next Next commit
std: win: Don't use GetFileInformationByHandle on UWP
  • Loading branch information
chouquette committed Jul 25, 2019
commit 4c05073d1d64b82ad10478324b87816cec16d74c
51 changes: 32 additions & 19 deletions src/libstd/sys/windows/c.rs
Original file line number Diff line number Diff line change
@@ -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,
44 changes: 44 additions & 0 deletions src/libstd/sys/windows/fs.rs
Original file line number Diff line number Diff line change
@@ -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)
}