Skip to content

Commit facd127

Browse files
committed
Move Windows compatibility layer to libnative
1 parent 8543e1b commit facd127

File tree

4 files changed

+96
-98
lines changed

4 files changed

+96
-98
lines changed

src/libnative/io/c_win32.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,96 @@ extern "system" {
6262

6363
pub fn CancelIo(hFile: libc::HANDLE) -> libc::BOOL;
6464
}
65+
66+
pub mod compat {
67+
use std::intrinsics::{atomic_store_relaxed, transmute};
68+
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
69+
use std::os::win32::as_utf16_p;
70+
71+
extern "system" {
72+
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
73+
fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
74+
}
75+
76+
// store_func() is idempotent, so using relaxed ordering for the atomics should be enough.
77+
// This way, calling a function in this compatibility layer (after it's loaded) shouldn't
78+
// be any slower than a regular DLL call.
79+
unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
80+
as_utf16_p(module, |module| {
81+
symbol.with_c_str(|symbol| {
82+
let handle = GetModuleHandleW(module);
83+
let func: Option<T> = transmute(GetProcAddress(handle, symbol));
84+
atomic_store_relaxed(ptr, func.unwrap_or(fallback))
85+
})
86+
})
87+
}
88+
89+
/// Macro for creating a compatibility fallback for a Windows function
90+
///
91+
/// # Example
92+
/// ```
93+
/// compat_fn!(adll32::SomeFunctionW(_arg: LPCWSTR) {
94+
/// // Fallback implementation
95+
/// })
96+
/// ```
97+
///
98+
/// Note that arguments unused by the fallback implementation should not be called `_` as
99+
/// they are used to be passed to the real function if available.
100+
macro_rules! compat_fn(
101+
($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
102+
-> $rettype:ty $fallback:block) => (
103+
#[inline(always)]
104+
pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
105+
static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk;
106+
107+
extern "system" fn thunk($($argname: $argtype),*) -> $rettype {
108+
unsafe {
109+
::io::c::compat::store_func(&mut ptr,
110+
stringify!($module),
111+
stringify!($symbol),
112+
fallback);
113+
::std::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
114+
}
115+
}
116+
117+
extern "system" fn fallback($($argname: $argtype),*) -> $rettype $fallback
118+
119+
::std::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
120+
}
121+
);
122+
123+
($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => (
124+
compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback)
125+
)
126+
)
127+
128+
/// Compatibility layer for functions in `kernel32.dll`
129+
///
130+
/// Latest versions of Windows this is needed for:
131+
///
132+
/// * `CreateSymbolicLinkW`: Windows XP, Windows Server 2003
133+
/// * `GetFinalPathNameByHandleW`: Windows XP, Windows Server 2003
134+
pub mod kernel32 {
135+
use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
136+
use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
137+
138+
extern "system" {
139+
fn SetLastError(dwErrCode: DWORD);
140+
}
141+
142+
compat_fn!(kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
143+
_lpTargetFileName: LPCWSTR,
144+
_dwFlags: DWORD) -> BOOLEAN {
145+
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
146+
0
147+
})
148+
149+
compat_fn!(kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
150+
_lpszFilePath: LPCWSTR,
151+
_cchFilePath: DWORD,
152+
_dwFlags: DWORD) -> DWORD {
153+
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
154+
0
155+
})
156+
}
157+
}

src/libnative/io/file_win32.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
408408

409409
pub fn readlink(p: &CString) -> IoResult<Path> {
410410
// FIXME: I have a feeling that this reads intermediate symlinks as well.
411-
use std::os::win32::compat::kernel32::GetFinalPathNameByHandleW;
411+
use io::c::compat::kernel32::GetFinalPathNameByHandleW;
412412
let handle = unsafe {
413413
as_utf16_p(p.as_str().unwrap(), |p| {
414414
libc::CreateFileW(p,
@@ -441,7 +441,7 @@ pub fn readlink(p: &CString) -> IoResult<Path> {
441441
}
442442

443443
pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
444-
use std::os::win32::compat::kernel32::CreateSymbolicLinkW;
444+
use io::c::compat::kernel32::CreateSymbolicLinkW;
445445
super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
446446
as_utf16_p(dst.as_str().unwrap(), |dst| {
447447
unsafe { CreateSymbolicLinkW(dst, src, 0) }

src/libnative/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
html_root_url = "http://static.rust-lang.org/doc/master")]
5151
#![deny(unused_result, unused_must_use)]
5252
#![allow(non_camel_case_types)]
53+
#![feature(macro_rules)]
5354

5455
// NB this crate explicitly does *not* allow glob imports, please seriously
5556
// consider whether they're needed before adding that feature here (the

src/libstd/os.rs

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -145,102 +145,6 @@ pub mod win32 {
145145
t.push(0u16);
146146
f(t.as_ptr())
147147
}
148-
149-
pub mod compat {
150-
use kinds::Copy;
151-
use option::Option;
152-
use c_str::ToCStr;
153-
use intrinsics::{atomic_store_relaxed, transmute};
154-
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
155-
use os::win32::as_utf16_p;
156-
157-
extern "system" {
158-
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
159-
fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
160-
}
161-
162-
// store_func() is idempotent, so using relaxed ordering for the atomics should be enough.
163-
// This way, calling a function in this compatibility layer (after it's loaded) shouldn't
164-
// be any slower than a regular DLL call.
165-
unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
166-
as_utf16_p(module, |module| {
167-
symbol.with_c_str(|symbol| {
168-
let handle = GetModuleHandleW(module);
169-
let func: Option<T> = transmute(GetProcAddress(handle, symbol));
170-
atomic_store_relaxed(ptr, func.unwrap_or(fallback))
171-
})
172-
})
173-
}
174-
175-
/// Macro for creating a compatibility fallback for a Windows function
176-
///
177-
/// # Example
178-
/// ```
179-
/// compat_fn!(adll32::SomeFunctionW(_arg: LPCWSTR) {
180-
/// // Fallback implementation
181-
/// })
182-
/// ```
183-
///
184-
/// Note that arguments unused by the fallback implementation should not be called `_` as
185-
/// they are used to be passed to the real function if available.
186-
macro_rules! compat_fn(
187-
($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
188-
-> $rettype:ty $fallback:block) => (
189-
#[inline(always)]
190-
pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
191-
static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk;
192-
193-
extern "system" fn thunk($($argname: $argtype),*) -> $rettype {
194-
unsafe {
195-
::os::win32::compat::store_func(&mut ptr,
196-
stringify!($module),
197-
stringify!($symbol),
198-
fallback);
199-
::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
200-
}
201-
}
202-
203-
extern "system" fn fallback($($argname: $argtype),*) -> $rettype $fallback
204-
205-
::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
206-
}
207-
);
208-
209-
($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => (
210-
compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback)
211-
)
212-
)
213-
214-
/// Compatibility layer for functions in `kernel32.dll`
215-
///
216-
/// Latest versions of Windows this is needed for:
217-
///
218-
/// * `CreateSymbolicLinkW`: Windows XP, Windows Server 2003
219-
/// * `GetFinalPathNameByHandleW`: Windows XP, Windows Server 2003
220-
pub mod kernel32 {
221-
use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
222-
use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
223-
224-
extern "system" {
225-
fn SetLastError(dwErrCode: DWORD);
226-
}
227-
228-
compat_fn!(kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
229-
_lpTargetFileName: LPCWSTR,
230-
_dwFlags: DWORD) -> BOOLEAN {
231-
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
232-
0
233-
})
234-
235-
compat_fn!(kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
236-
_lpszFilePath: LPCWSTR,
237-
_cchFilePath: DWORD,
238-
_dwFlags: DWORD) -> DWORD {
239-
unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
240-
0
241-
})
242-
}
243-
}
244148
}
245149

246150
/*

0 commit comments

Comments
 (0)