@@ -37,7 +37,7 @@ use crate::sys::c;
37
37
// file an issue for discussion; currently we don't guarantee any functionality
38
38
// before main.
39
39
// See https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-170
40
- #[ cfg( target_vendor = "win7" ) ]
40
+ #[ cfg( any ( target_vendor = "win7" , target_vendor = "rust9x" ) ) ]
41
41
#[ used]
42
42
#[ link_section = ".CRT$XCT" ]
43
43
static INIT_TABLE_ENTRY : unsafe extern "C" fn ( ) = init;
@@ -68,6 +68,21 @@ unsafe extern "C" fn init() {
68
68
load_synch_functions ( ) ;
69
69
}
70
70
71
+ #[ cfg( target_vendor = "rust9x" ) ]
72
+ unsafe extern "C" fn init ( ) {
73
+ // In an exe this code is executed before main() so is single threaded.
74
+ // In a DLL the system's loader lock will be held thereby synchronizing
75
+ // access. So the same best practices apply here as they do to running in DllMain:
76
+ // https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
77
+ //
78
+ // DO NOT do anything interesting or complicated in this function! DO NOT call
79
+ // any Rust functions or CRT functions if those functions touch any global state,
80
+ // because this function runs during global initialization. For example, DO NOT
81
+ // do any dynamic allocation, don't call LoadLibrary, etc.
82
+
83
+ checks:: init_rust9x_checks ( ) ;
84
+ }
85
+
71
86
/// Helper macro for creating CStrs from literals and symbol names.
72
87
macro_rules! ansi_str {
73
88
( sym $ident: ident) => { { crate :: sys:: compat:: const_cstr_from_bytes( concat!( stringify!( $ident) , "\0 " ) . as_bytes( ) ) } } ;
@@ -118,6 +133,15 @@ impl Module {
118
133
}
119
134
}
120
135
136
+ #[ allow( dead_code) ]
137
+ pub unsafe fn load ( name : & CStr ) -> Option < Self > {
138
+ // SAFETY: A CStr is always null terminated.
139
+ unsafe {
140
+ let module = c:: LoadLibraryA ( name. as_ptr ( ) . cast :: < u8 > ( ) ) ;
141
+ NonNull :: new ( module) . map ( Self )
142
+ }
143
+ }
144
+
121
145
// Try to get the address of a function.
122
146
pub fn proc_address ( self , name : & CStr ) -> Option < NonNull < c_void > > {
123
147
unsafe {
@@ -131,43 +155,54 @@ impl Module {
131
155
}
132
156
}
133
157
158
+ pub static UNICOWS : & CStr = c"unicows" ;
159
+
134
160
/// Load a function or use a fallback implementation if that fails.
135
161
macro_rules! compat_fn_with_fallback {
136
- ( pub static $module: ident: & CStr = $name: expr; $(
137
- $( #[ $meta: meta] ) *
138
- $vis: vis fn $symbol: ident( $( $argname: ident: $argtype: ty) ,* ) -> $rettype: ty $fallback_body: block
139
- ) * ) => (
140
- pub static $module: & CStr = $name;
162
+ {
163
+ pub static $module: ident: & CStr = $name: expr => { load: $load: expr, unicows: $unicows: expr } ;
164
+ $(
165
+ $( #[ $meta: meta] ) *
166
+ $vis: vis fn $symbol: ident( $( $argname: ident: $argtype: ty) ,* $( , ) ?) $( -> $rettype: ty) ? $fallback_body: block
167
+ ) *
168
+ } => {
141
169
$(
142
170
$( #[ $meta] ) *
143
171
pub mod $symbol {
144
172
#[ allow( unused_imports) ]
145
173
use super :: * ;
146
174
use crate :: mem;
147
- use crate :: ffi:: CStr ;
175
+ use crate :: ffi:: { CStr , c_void } ;
148
176
use crate :: sync:: atomic:: { AtomicPtr , Ordering } ;
149
- use crate :: sys:: compat:: Module ;
150
177
151
- type F = unsafe extern "system" fn ( $( $argtype) ,* ) -> $rettype;
178
+ type F = unsafe extern "system" fn ( $( $argtype) ,* ) $ ( -> $rettype) ? ;
152
179
153
180
/// `PTR` contains a function pointer to one of three functions.
154
181
/// It starts with the `load` function.
155
182
/// When that is called it attempts to load the requested symbol.
156
183
/// If it succeeds, `PTR` is set to the address of that symbol.
157
184
/// If it fails, then `PTR` is set to `fallback`.
158
- static PTR : AtomicPtr <c_void> = AtomicPtr :: new( load as * mut _) ;
185
+ pub ( in crate :: sys ) static PTR : AtomicPtr <c_void> = AtomicPtr :: new( load as * mut _) ;
159
186
160
- unsafe extern "system" fn load( $( $argname: $argtype) ,* ) -> $rettype {
187
+ unsafe extern "system" fn load( $( $argname: $argtype) ,* ) $ ( -> $rettype) ? {
161
188
unsafe {
162
- let func = load_from_module( Module :: new ( $module ) ) ;
189
+ let func = load_from_module( ) ;
163
190
func( $( $argname) ,* )
164
191
}
165
192
}
166
193
167
- fn load_from_module( module : Option < Module > ) -> F {
194
+ fn load_from_module( ) -> F {
168
195
unsafe {
169
196
static SYMBOL_NAME : & CStr = ansi_str!( sym $symbol) ;
170
- if let Some ( f) = module. and_then( |m| m. proc_address( SYMBOL_NAME ) ) {
197
+
198
+ let f = crate :: sys:: compat:: load_from_module(
199
+ $name,
200
+ SYMBOL_NAME ,
201
+ $load,
202
+ $unicows
203
+ ) ;
204
+
205
+ if let Some ( f) = f {
171
206
PTR . store( f. as_ptr( ) , Ordering :: Relaxed ) ;
172
207
mem:: transmute( f)
173
208
} else {
@@ -177,13 +212,27 @@ macro_rules! compat_fn_with_fallback {
177
212
}
178
213
}
179
214
215
+ #[ allow( dead_code) ]
216
+ pub fn available( ) -> Option <F > {
217
+ let mut ptr = PTR . load( Ordering :: Relaxed ) ;
218
+ if ptr == load as * mut _ {
219
+ ptr = load_from_module( ) as * mut _;
220
+ }
221
+
222
+ if ptr != fallback as * mut _ {
223
+ Some ( unsafe { mem:: transmute( ptr) } )
224
+ } else {
225
+ None
226
+ }
227
+ }
228
+
180
229
#[ allow( unused_variables) ]
181
- unsafe extern "system" fn fallback( $( $argname: $argtype) ,* ) -> $rettype {
230
+ unsafe extern "system" fn fallback( $( $argname: $argtype) ,* ) $ ( -> $rettype) ? {
182
231
$fallback_body
183
232
}
184
233
185
234
#[ inline( always) ]
186
- pub unsafe fn call( $( $argname: $argtype) ,* ) -> $rettype {
235
+ pub unsafe fn call( $( $argname: $argtype) ,* ) $ ( -> $rettype) ? {
187
236
unsafe {
188
237
let func: F = mem:: transmute( PTR . load( Ordering :: Relaxed ) ) ;
189
238
func( $( $argname) ,* )
@@ -193,7 +242,8 @@ macro_rules! compat_fn_with_fallback {
193
242
#[ allow( unused) ]
194
243
$( #[ $meta] ) *
195
244
$vis use $symbol:: call as $symbol;
196
- ) * )
245
+ ) *
246
+ }
197
247
}
198
248
199
249
/// Optionally loaded functions.
@@ -203,7 +253,7 @@ macro_rules! compat_fn_with_fallback {
203
253
macro_rules! compat_fn_optional {
204
254
( $(
205
255
$( #[ $meta: meta] ) *
206
- $vis: vis fn $symbol: ident( $( $argname: ident: $argtype: ty) ,* ) $( -> $rettype: ty) ?;
256
+ $vis: vis fn $symbol: ident( $( $argname: ident: $argtype: ty) ,* $ ( , ) ? ) $( -> $rettype: ty) ?;
207
257
) +) => (
208
258
$(
209
259
pub mod $symbol {
@@ -219,8 +269,19 @@ macro_rules! compat_fn_optional {
219
269
type F = unsafe extern "system" fn ( $( $argtype) ,* ) $( -> $rettype) ?;
220
270
221
271
#[ inline( always) ]
272
+ #[ allow( dead_code) ]
222
273
pub fn option( ) -> Option <F > {
223
- NonNull :: new( PTR . load( Ordering :: Relaxed ) ) . map( |f| unsafe { mem:: transmute( f) } )
274
+ unsafe {
275
+ NonNull :: new( PTR . load( Ordering :: Relaxed ) ) . map( |f| unsafe { mem:: transmute( f) } )
276
+ }
277
+ }
278
+
279
+ #[ inline( always) ]
280
+ #[ allow( dead_code) ]
281
+ pub unsafe fn call( $( $argname: $argtype) ,* ) $( -> $rettype) ? {
282
+ unsafe {
283
+ ( mem:: transmute:: <_, F >( PTR . load( Ordering :: Relaxed ) ) ) ( $( $argname) ,* )
284
+ }
224
285
}
225
286
}
226
287
#[ inline]
@@ -231,6 +292,28 @@ macro_rules! compat_fn_optional {
231
292
)
232
293
}
233
294
295
+ pub ( crate ) fn load_from_module (
296
+ module_name : & CStr ,
297
+ symbol_name : & CStr ,
298
+ load : bool ,
299
+ unicows : bool ,
300
+ ) -> Option < NonNull < c_void > > {
301
+ let in_unicows = if unicows {
302
+ unsafe { Module :: new ( UNICOWS ) . and_then ( |m| m. proc_address ( symbol_name) ) }
303
+ } else {
304
+ None
305
+ } ;
306
+
307
+ in_unicows. or_else ( || {
308
+ if load {
309
+ unsafe { Module :: new ( module_name) }
310
+ } else {
311
+ unsafe { Module :: load ( module_name) }
312
+ }
313
+ . and_then ( |m| m. proc_address ( symbol_name) )
314
+ } )
315
+ }
316
+
234
317
/// Load all needed functions from "api-ms-win-core-synch-l1-2-0".
235
318
#[ cfg( target_vendor = "win7" ) ]
236
319
pub ( super ) fn load_synch_functions ( ) {
@@ -250,6 +333,4 @@ pub(super) fn load_synch_functions() {
250
333
c:: WakeByAddressSingle :: PTR . store ( wake_by_address_single. as_ptr ( ) , Ordering :: Relaxed ) ;
251
334
Some ( ( ) )
252
335
}
253
-
254
- try_load ( ) ;
255
336
}
0 commit comments