]> git.proxmox.com Git - rustc.git/blame - src/libstd/sys/windows/compat.rs
Imported Upstream version 1.6.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
24use prelude::v1::*;
25
26use ffi::CString;
c1a9b12d 27use sync::atomic::{AtomicUsize, Ordering};
92a42be0 28use sys::c;
c1a9b12d
SL
29
30pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
31 let mut module: Vec<u16> = module.utf16_units().collect();
32 module.push(0);
33 let symbol = CString::new(symbol).unwrap();
34 unsafe {
92a42be0
SL
35 let handle = c::GetModuleHandleW(module.as_ptr());
36 match c::GetProcAddress(handle, symbol.as_ptr()) as usize {
c1a9b12d
SL
37 0 => None,
38 n => Some(n),
39 }
40 }
41}
42
43pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
44 fallback: usize) -> usize {
45 let value = lookup(module, symbol).unwrap_or(fallback);
46 ptr.store(value, Ordering::SeqCst);
47 value
48}
49
50macro_rules! compat_fn {
51 ($module:ident: $(
52 pub fn $symbol:ident($($argname:ident: $argtype:ty),*)
53 -> $rettype:ty {
54 $($body:expr);*
55 }
56 )*) => ($(
57 #[allow(unused_variables)]
58 pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
59 use sync::atomic::{AtomicUsize, Ordering};
60 use mem;
61 type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
62
63 static PTR: AtomicUsize = AtomicUsize::new(0);
64
65 fn load() -> usize {
66 ::sys::compat::store_func(&PTR,
67 stringify!($module),
68 stringify!($symbol),
69 fallback as usize)
70 }
71 unsafe extern "system" fn fallback($($argname: $argtype),*)
72 -> $rettype {
73 $($body);*
74 }
75
76 let addr = match PTR.load(Ordering::SeqCst) {
77 0 => load(),
78 n => n,
79 };
80 mem::transmute::<usize, F>(addr)($($argname),*)
81 }
82 )*)
83}