]> git.proxmox.com Git - rustc.git/blame - src/libstd/sys/windows/compat.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / libstd / sys / windows / compat.rs
CommitLineData
c1a9b12d
SL
1// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! A "compatibility layer" for spanning XP and Windows 7
12//!
13//! The standard library currently binds many functions that are not available
14//! on Windows XP, but we would also like to support building executables that
15//! run on XP. To do this we specify all non-XP APIs as having a fallback
16//! implementation to do something reasonable.
17//!
18//! This dynamic runtime detection of whether a function is available is
19//! implemented with `GetModuleHandle` and `GetProcAddress` paired with a
20//! static-per-function which caches the result of the first check. In this
21//! manner we pay a semi-large one-time cost up front for detecting whether a
22//! function is available but afterwards it's just a load and a jump.
23
c1a9b12d 24use ffi::CString;
c1a9b12d 25use sync::atomic::{AtomicUsize, Ordering};
92a42be0 26use sys::c;
c1a9b12d
SL
27
28pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
7453a54e 29 let mut module: Vec<u16> = module.encode_utf16().collect();
c1a9b12d
SL
30 module.push(0);
31 let symbol = CString::new(symbol).unwrap();
32 unsafe {
92a42be0
SL
33 let handle = c::GetModuleHandleW(module.as_ptr());
34 match c::GetProcAddress(handle, symbol.as_ptr()) as usize {
c1a9b12d
SL
35 0 => None,
36 n => Some(n),
37 }
38 }
39}
40
41pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
42 fallback: usize) -> usize {
43 let value = lookup(module, symbol).unwrap_or(fallback);
44 ptr.store(value, Ordering::SeqCst);
45 value
46}
47
48macro_rules! compat_fn {
49 ($module:ident: $(
50 pub fn $symbol:ident($($argname:ident: $argtype:ty),*)
51 -> $rettype:ty {
52 $($body:expr);*
53 }
54 )*) => ($(
55 #[allow(unused_variables)]
56 pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
57 use sync::atomic::{AtomicUsize, Ordering};
58 use mem;
59 type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
60
61 static PTR: AtomicUsize = AtomicUsize::new(0);
62
63 fn load() -> usize {
64 ::sys::compat::store_func(&PTR,
65 stringify!($module),
66 stringify!($symbol),
67 fallback as usize)
68 }
69 unsafe extern "system" fn fallback($($argname: $argtype),*)
70 -> $rettype {
71 $($body);*
72 }
73
74 let addr = match PTR.load(Ordering::SeqCst) {
75 0 => load(),
76 n => n,
77 };
78 mem::transmute::<usize, F>(addr)($($argname),*)
79 }
80 )*)
81}