1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::os::raw::c_void;
use status::{Status, NvAPI_Status};
use types;
pub type QueryInterfaceFn = extern "C" fn(id: u32) -> *const c_void;
#[cfg(all(windows, target_pointer_width = "32"))]
pub const LIBRARY_NAME: &'static [u8; 10] = b"nvapi.dll\0";
#[cfg(all(windows, target_pointer_width = "64"))]
pub const LIBRARY_NAME: &'static [u8; 12] = b"nvapi64.dll\0";
pub const FN_NAME: &'static [u8; 21] = b"nvapi_QueryInterface\0";
static QUERY_INTERFACE_CACHE: AtomicUsize = ATOMIC_USIZE_INIT;
pub unsafe fn set_query_interface(ptr: QueryInterfaceFn) {
QUERY_INTERFACE_CACHE.store(ptr as usize, Ordering::Relaxed);
}
#[cfg(not(windows))]
pub fn nvapi_QueryInterface(id: u32) -> ::Result<usize> {
Err(Status::LibraryNotFound)
}
#[cfg(windows)]
pub fn nvapi_QueryInterface(id: u32) -> ::Result<usize> {
use winapi::um::libloaderapi::{GetProcAddress, LoadLibraryA};
use std::mem;
use std::os::raw::c_char;
unsafe {
let ptr = match QUERY_INTERFACE_CACHE.load(Ordering::Relaxed) {
0 => {
let lib = LoadLibraryA(LIBRARY_NAME.as_ptr() as *const c_char);
if lib.is_null() {
Err(Status::LibraryNotFound)
} else {
let ptr = GetProcAddress(lib, FN_NAME.as_ptr() as *const c_char);
if ptr.is_null() {
Err(Status::LibraryNotFound)
} else {
QUERY_INTERFACE_CACHE.store(ptr as usize, Ordering::Relaxed);
Ok(ptr as usize)
}
}
},
ptr => Ok(ptr),
}?;
match mem::transmute::<_, QueryInterfaceFn>(ptr)(id) as usize {
0 => Err(Status::NoImplementation),
ptr => Ok(ptr),
}
}
}
pub(crate) fn query_interface(id: u32, cache: &AtomicUsize) -> ::Result<usize> {
match cache.load(Ordering::Relaxed) {
0 => {
let value = nvapi_QueryInterface(id)?;
cache.store(value, Ordering::Relaxed);
Ok(value)
},
value => Ok(value),
}
}
nvapi! {
pub type InitializeFn = extern "C" fn() -> NvAPI_Status;
pub unsafe fn NvAPI_Initialize;
}
nvapi! {
pub type UnloadFn = extern "C" fn() -> NvAPI_Status;
pub unsafe fn NvAPI_Unload;
}
nvapi! {
pub type GetErrorMessageFn = extern "C" fn(nr: NvAPI_Status, szDesc: *mut types::NvAPI_ShortString) -> NvAPI_Status;
pub unsafe fn NvAPI_GetErrorMessage;
}
nvapi! {
pub type GetInterfaceVersionStringFn = extern "C" fn(szDesc: *mut types::NvAPI_ShortString) -> NvAPI_Status;
pub unsafe fn NvAPI_GetInterfaceVersionString;
}