Implement fallbacks for functions unavailable in older versions of Windows
This commit is contained in:
parent
1f25c8b78d
commit
073d7ffc27
3 changed files with 89 additions and 16 deletions
|
|
@ -250,7 +250,6 @@ pub use funcs::bsd43::{shutdown};
|
|||
#[cfg(windows)] pub use funcs::extra::kernel32::{FlushFileBuffers, SetEndOfFile, CreateFileW};
|
||||
#[cfg(windows)] pub use funcs::extra::kernel32::{CreateDirectoryW, FindFirstFileW};
|
||||
#[cfg(windows)] pub use funcs::extra::kernel32::{FindNextFileW, FindClose, DeleteFileW};
|
||||
#[cfg(windows)] pub use funcs::extra::kernel32::{GetFinalPathNameByHandleW, CreateSymbolicLinkW};
|
||||
#[cfg(windows)] pub use funcs::extra::kernel32::{CreateHardLinkW, CreateEventW};
|
||||
#[cfg(windows)] pub use funcs::extra::kernel32::{FlushFileBuffers, CreateNamedPipeW};
|
||||
#[cfg(windows)] pub use funcs::extra::kernel32::{SetNamedPipeHandleState, WaitNamedPipeW};
|
||||
|
|
@ -1733,6 +1732,7 @@ pub mod consts {
|
|||
pub static ERROR_INVALID_HANDLE : c_int = 6;
|
||||
pub static ERROR_BROKEN_PIPE: c_int = 109;
|
||||
pub static ERROR_DISK_FULL : c_int = 112;
|
||||
pub static ERROR_CALL_NOT_IMPLEMENTED : c_int = 120;
|
||||
pub static ERROR_INSUFFICIENT_BUFFER : c_int = 122;
|
||||
pub static ERROR_INVALID_NAME : c_int = 123;
|
||||
pub static ERROR_ALREADY_EXISTS : c_int = 183;
|
||||
|
|
@ -4185,9 +4185,9 @@ pub mod funcs {
|
|||
LPSTARTUPINFO,
|
||||
LPPROCESS_INFORMATION,
|
||||
LPMEMORY_BASIC_INFORMATION,
|
||||
LPSYSTEM_INFO, BOOLEAN,
|
||||
HANDLE, LPHANDLE, LARGE_INTEGER,
|
||||
PLARGE_INTEGER, LPFILETIME};
|
||||
LPSYSTEM_INFO, HANDLE, LPHANDLE,
|
||||
LARGE_INTEGER, PLARGE_INTEGER,
|
||||
LPFILETIME};
|
||||
|
||||
extern "system" {
|
||||
pub fn GetEnvironmentVariableW(n: LPCWSTR,
|
||||
|
|
@ -4297,9 +4297,6 @@ pub mod funcs {
|
|||
pub fn MoveFileExW(lpExistingFileName: LPCWSTR,
|
||||
lpNewFileName: LPCWSTR,
|
||||
dwFlags: DWORD) -> BOOL;
|
||||
pub fn CreateSymbolicLinkW(lpSymlinkFileName: LPCWSTR,
|
||||
lpTargetFileName: LPCWSTR,
|
||||
dwFlags: DWORD) -> BOOLEAN;
|
||||
pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR,
|
||||
lpTargetFileName: LPCWSTR,
|
||||
lpSecurityAttributes: LPSECURITY_ATTRIBUTES)
|
||||
|
|
@ -4312,10 +4309,6 @@ pub mod funcs {
|
|||
dwCreationDisposition: DWORD,
|
||||
dwFlagsAndAttributes: DWORD,
|
||||
hTemplateFile: HANDLE) -> HANDLE;
|
||||
pub fn GetFinalPathNameByHandleW(hFile: HANDLE,
|
||||
lpszFilePath: LPCWSTR,
|
||||
cchFilePath: DWORD,
|
||||
dwFlags: DWORD) -> DWORD;
|
||||
pub fn ReadFile(hFile: HANDLE,
|
||||
lpBuffer: LPVOID,
|
||||
nNumberOfBytesToRead: DWORD,
|
||||
|
|
|
|||
|
|
@ -408,6 +408,7 @@ pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
|
|||
|
||||
pub fn readlink(p: &CString) -> IoResult<Path> {
|
||||
// FIXME: I have a feeling that this reads intermediate symlinks as well.
|
||||
use std::os::win32::compat::kernel32::GetFinalPathNameByHandleW;
|
||||
let handle = unsafe {
|
||||
as_utf16_p(p.as_str().unwrap(), |p| {
|
||||
libc::CreateFileW(p,
|
||||
|
|
@ -425,10 +426,10 @@ pub fn readlink(p: &CString) -> IoResult<Path> {
|
|||
// Specify (sz - 1) because the documentation states that it's the size
|
||||
// without the null pointer
|
||||
let ret = fill_utf16_buf_and_decode(|buf, sz| unsafe {
|
||||
libc::GetFinalPathNameByHandleW(handle,
|
||||
buf as *u16,
|
||||
sz - 1,
|
||||
libc::VOLUME_NAME_DOS)
|
||||
GetFinalPathNameByHandleW(handle,
|
||||
buf as *u16,
|
||||
sz - 1,
|
||||
libc::VOLUME_NAME_DOS)
|
||||
});
|
||||
let ret = match ret {
|
||||
Some(ref s) if s.starts_with(r"\\?\") => Ok(Path::new(s.slice_from(4))),
|
||||
|
|
@ -440,9 +441,10 @@ pub fn readlink(p: &CString) -> IoResult<Path> {
|
|||
}
|
||||
|
||||
pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
|
||||
use std::os::win32::compat::kernel32::CreateSymbolicLinkW;
|
||||
super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
|
||||
as_utf16_p(dst.as_str().unwrap(), |dst| {
|
||||
unsafe { libc::CreateSymbolicLinkW(dst, src, 0) }
|
||||
unsafe { CreateSymbolicLinkW(dst, src, 0) }
|
||||
}) as libc::BOOL
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,6 +145,84 @@ pub mod win32 {
|
|||
t.push(0u16);
|
||||
f(t.as_ptr())
|
||||
}
|
||||
|
||||
pub mod compat {
|
||||
use kinds::Copy;
|
||||
use option::Option;
|
||||
use c_str::ToCStr;
|
||||
use intrinsics::{atomic_store_relaxed, transmute};
|
||||
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
|
||||
use os::win32::as_utf16_p;
|
||||
|
||||
#[link_name="kernel32"]
|
||||
extern "system" {
|
||||
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
|
||||
fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
|
||||
}
|
||||
|
||||
unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
|
||||
as_utf16_p(module, |module| {
|
||||
symbol.with_c_str(|symbol| {
|
||||
let handle = GetModuleHandleW(module);
|
||||
let func: Option<T> = transmute(GetProcAddress(handle, symbol));
|
||||
atomic_store_relaxed(ptr, func.unwrap_or(fallback))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! compat_fn(
|
||||
($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
|
||||
-> $rettype:ty $fallback:block) => (
|
||||
#[inline(always)]
|
||||
pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
|
||||
static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk;
|
||||
|
||||
extern "system" fn thunk($($argname: $argtype),*) -> $rettype {
|
||||
unsafe {
|
||||
::os::win32::compat::store_func(&mut ptr,
|
||||
stringify!($module),
|
||||
stringify!($symbol),
|
||||
fallback);
|
||||
::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
|
||||
}
|
||||
}
|
||||
|
||||
extern "system" fn fallback($($argname: $argtype),*) -> $rettype $fallback
|
||||
|
||||
::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
|
||||
}
|
||||
);
|
||||
|
||||
($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => (
|
||||
compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback)
|
||||
)
|
||||
)
|
||||
|
||||
pub mod kernel32 {
|
||||
use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
|
||||
use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
|
||||
|
||||
#[link_name="kernel32"]
|
||||
extern "system" {
|
||||
fn SetLastError(dwErrCode: DWORD);
|
||||
}
|
||||
|
||||
compat_fn!(kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
|
||||
_lpTargetFileName: LPCWSTR,
|
||||
_dwFlags: DWORD) -> BOOLEAN {
|
||||
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
|
||||
0
|
||||
})
|
||||
|
||||
compat_fn!(kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
|
||||
_lpszFilePath: LPCWSTR,
|
||||
_cchFilePath: DWORD,
|
||||
_dwFlags: DWORD) -> DWORD {
|
||||
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
|
||||
0
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue