1use std::ffi::OsStr;
2use std::path::{self, Path, PathBuf};
3use std::{io, iter, str};
4
5use rustc_abi::{Align, Size};
6use rustc_middle::ty::Ty;
7use rustc_span::Symbol;
8use rustc_target::callconv::FnAbi;
9use rustc_target::spec::Env;
10
11use self::shims::windows::handle::{Handle, PseudoHandle};
12use crate::shims::os_str::bytes_to_os_str;
13use crate::shims::windows::*;
14use crate::*;
15
16pub fn is_dyn_sym(name: &str) -> bool {
17 matches!(
19 name,
20 "SetThreadDescription" | "GetThreadDescription" | "WaitOnAddress" | "WakeByAddressSingle"
21 )
22}
23
24#[cfg(windows)]
25fn win_get_full_path_name<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result<PathBuf>> {
26 interp_ok(path::absolute(path))
28}
29
30#[cfg(unix)]
31#[expect(clippy::get_first, clippy::arithmetic_side_effects)]
32fn win_get_full_path_name<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result<PathBuf>> {
33 use std::sync::LazyLock;
34
35 use rustc_data_structures::fx::FxHashSet;
36
37 let bytes = path.as_os_str().as_encoded_bytes();
45 if bytes.get(0).copied() == Some(b'/')
48 && bytes.get(1).copied() == Some(b'/')
49 && matches!(bytes.get(2), Some(b'.' | b'?'))
50 && bytes.get(3).copied() == Some(b'/')
51 {
52 return interp_ok(Ok(path.into()));
53 };
54 let is_unc = bytes.starts_with(b"//");
55 static MAGIC_FILENAMES: LazyLock<FxHashSet<&'static str>> = LazyLock::new(|| {
57 FxHashSet::from_iter([
58 "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7",
59 "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
60 ])
61 });
62 if str::from_utf8(bytes).is_ok_and(|s| MAGIC_FILENAMES.contains(&*s.to_ascii_uppercase())) {
63 let mut result: Vec<u8> = b"//./".into();
64 result.extend(bytes);
65 return interp_ok(Ok(bytes_to_os_str(&result)?.into()));
66 }
67 let mut result: Vec<&[u8]> = vec![]; let mut bytes = bytes; let mut stop = false;
72 while !stop {
73 let mut component = match bytes.iter().position(|&b| b == b'/') {
75 Some(pos) => {
76 let (component, tail) = bytes.split_at(pos);
77 bytes = &tail[1..]; component
79 }
80 None => {
81 stop = true;
83 let component = bytes;
84 bytes = &[];
85 component
86 }
87 };
88 if !is_unc && component.eq_ignore_ascii_case(b"NUL") {
92 let mut result: Vec<u8> = b"//./".into();
93 result.extend(component);
94 return interp_ok(Ok(bytes_to_os_str(&result)?.into()));
95 }
96 if component == b".." {
98 let is_root = {
100 result.len() == 2 && matches!(result[0], []) && matches!(result[1], [_, b':'])
102 } || {
103 result.len() == 4 && matches!(result[0], []) && matches!(result[1], [])
105 };
106 if !is_root {
107 result.pop();
108 }
109 continue;
110 }
111 let len = component.len();
114 if !is_unc && len >= 2 && component[len - 1] == b'.' && component[len - 2] != b'.' {
115 component = &component[..len - 1];
116 }
117 result.push(component);
119 }
120 if result.len() == 2 && matches!(result[0], []) && matches!(result[1], [_, b':']) {
122 result.push(&[]);
123 }
124 let result = result.join(&b'/');
126 interp_ok(path::absolute(bytes_to_os_str(&result)?))
127}
128
129impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
130pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
131 fn emulate_foreign_item_inner(
132 &mut self,
133 link_name: Symbol,
134 abi: &FnAbi<'tcx, Ty<'tcx>>,
135 args: &[OpTy<'tcx>],
136 dest: &MPlaceTy<'tcx>,
137 ) -> InterpResult<'tcx, EmulateItemResult> {
138 let this = self.eval_context_mut();
139
140 match link_name.as_str() {
149 "GetEnvironmentVariableW" => {
151 let [name, buf, size] = this.check_shim_sig(
153 shim_sig!(extern "system" fn(*const _, *mut _, u32) -> u32),
154 link_name,
155 abi,
156 args,
157 )?;
158 let result = this.GetEnvironmentVariableW(name, buf, size)?;
159 this.write_scalar(result, dest)?;
160 }
161 "SetEnvironmentVariableW" => {
162 let [name, value] = this.check_shim_sig(
164 shim_sig!(extern "system" fn(*const _, *const _) -> winapi::BOOL),
165 link_name,
166 abi,
167 args,
168 )?;
169 let result = this.SetEnvironmentVariableW(name, value)?;
170 this.write_scalar(result, dest)?;
171 }
172 "GetEnvironmentStringsW" => {
173 let [] = this.check_shim_sig(
175 shim_sig!(extern "system" fn() -> *mut _),
176 link_name,
177 abi,
178 args,
179 )?;
180 let result = this.GetEnvironmentStringsW()?;
181 this.write_pointer(result, dest)?;
182 }
183 "FreeEnvironmentStringsW" => {
184 let [env_block] = this.check_shim_sig(
186 shim_sig!(extern "system" fn(*mut _) -> winapi::BOOL),
187 link_name,
188 abi,
189 args,
190 )?;
191 let result = this.FreeEnvironmentStringsW(env_block)?;
192 this.write_scalar(result, dest)?;
193 }
194 "GetCurrentDirectoryW" => {
195 let [size, buf] = this.check_shim_sig(
197 shim_sig!(extern "system" fn(u32, *mut _) -> u32),
198 link_name,
199 abi,
200 args,
201 )?;
202 let result = this.GetCurrentDirectoryW(size, buf)?;
203 this.write_scalar(result, dest)?;
204 }
205 "SetCurrentDirectoryW" => {
206 let [path] = this.check_shim_sig(
208 shim_sig!(extern "system" fn(*const _) -> winapi::BOOL),
209 link_name,
210 abi,
211 args,
212 )?;
213 let result = this.SetCurrentDirectoryW(path)?;
214 this.write_scalar(result, dest)?;
215 }
216 "GetUserProfileDirectoryW" => {
217 let [token, buf, size] = this.check_shim_sig(
219 shim_sig!(extern "system" fn(winapi::HANDLE, *mut _, *mut _) -> winapi::BOOL),
220 link_name,
221 abi,
222 args,
223 )?;
224 let result = this.GetUserProfileDirectoryW(token, buf, size)?;
225 this.write_scalar(result, dest)?;
226 }
227 "GetCurrentProcessId" => {
228 let [] = this.check_shim_sig(
230 shim_sig!(extern "system" fn() -> u32),
231 link_name,
232 abi,
233 args,
234 )?;
235 let result = this.GetCurrentProcessId()?;
236 this.write_scalar(result, dest)?;
237 }
238 "GetTempPathW" => {
239 let [bufferlength, buffer] = this.check_shim_sig(
241 shim_sig!(extern "system" fn(u32, *mut _) -> u32),
242 link_name,
243 abi,
244 args,
245 )?;
246 let result = this.GetTempPathW(bufferlength, buffer)?;
247 this.write_scalar(result, dest)?;
248 }
249
250 "NtWriteFile" => {
252 let [
253 handle,
254 event,
255 apc_routine,
256 apc_context,
257 io_status_block,
258 buf,
259 n,
260 byte_offset,
261 key,
262 ] = this.check_shim_sig(
263 shim_sig!(
264 extern "system" fn(
265 winapi::HANDLE,
266 winapi::HANDLE,
267 *mut _,
268 *mut _,
269 *mut _,
270 *mut _,
271 u32,
272 *mut _,
273 *mut _,
274 ) -> i32
275 ),
276 link_name,
277 abi,
278 args,
279 )?;
280 this.NtWriteFile(
281 handle,
282 event,
283 apc_routine,
284 apc_context,
285 io_status_block,
286 buf,
287 n,
288 byte_offset,
289 key,
290 dest,
291 )?;
292 }
293 "NtReadFile" => {
294 let [
295 handle,
296 event,
297 apc_routine,
298 apc_context,
299 io_status_block,
300 buf,
301 n,
302 byte_offset,
303 key,
304 ] = this.check_shim_sig(
305 shim_sig!(
306 extern "system" fn(
307 winapi::HANDLE,
308 winapi::HANDLE,
309 *mut _,
310 *mut _,
311 *mut _,
312 *mut _,
313 u32,
314 *mut _,
315 *mut _,
316 ) -> i32
317 ),
318 link_name,
319 abi,
320 args,
321 )?;
322 this.NtReadFile(
323 handle,
324 event,
325 apc_routine,
326 apc_context,
327 io_status_block,
328 buf,
329 n,
330 byte_offset,
331 key,
332 dest,
333 )?;
334 }
335 "GetFullPathNameW" => {
336 let [filename, size, buffer, filepart] = this.check_shim_sig(
338 shim_sig!(extern "system" fn(*const _, u32, *mut _, *mut _) -> u32),
339 link_name,
340 abi,
341 args,
342 )?;
343 this.check_no_isolation("`GetFullPathNameW`")?;
344
345 let filename = this.read_pointer(filename)?;
346 let size = this.read_scalar(size)?.to_u32()?;
347 let buffer = this.read_pointer(buffer)?;
348 let filepart = this.read_pointer(filepart)?;
349
350 if !this.ptr_is_null(filepart)? {
351 throw_unsup_format!("GetFullPathNameW: non-null `lpFilePart` is not supported");
352 }
353
354 let filename = this.read_path_from_wide_str(filename)?;
355 let result = match win_get_full_path_name(&filename)? {
356 Err(err) => {
357 this.set_last_error(err)?;
358 Scalar::from_u32(0) }
360 Ok(abs_filename) => {
361 Scalar::from_u32(helpers::windows_check_buffer_size(
362 this.write_path_to_wide_str(&abs_filename, buffer, size.into())?,
363 ))
364 }
367 };
368 this.write_scalar(result, dest)?;
369 }
370 "CreateFileW" => {
371 let [
372 file_name,
373 desired_access,
374 share_mode,
375 security_attributes,
376 creation_disposition,
377 flags_and_attributes,
378 template_file,
379 ] = this.check_shim_sig(
380 shim_sig!(
381 extern "system" fn(
382 *const _,
383 u32,
384 u32,
385 *mut _,
386 u32,
387 u32,
388 winapi::HANDLE,
389 ) -> winapi::HANDLE
390 ),
391 link_name,
392 abi,
393 args,
394 )?;
395 let handle = this.CreateFileW(
396 file_name,
397 desired_access,
398 share_mode,
399 security_attributes,
400 creation_disposition,
401 flags_and_attributes,
402 template_file,
403 )?;
404 this.write_scalar(handle.to_scalar(this), dest)?;
405 }
406 "GetFileInformationByHandle" => {
407 let [handle, info] = this.check_shim_sig(
408 shim_sig!(extern "system" fn(winapi::HANDLE, *mut _) -> winapi::BOOL),
409 link_name,
410 abi,
411 args,
412 )?;
413 let res = this.GetFileInformationByHandle(handle, info)?;
414 this.write_scalar(res, dest)?;
415 }
416 "SetFileInformationByHandle" => {
417 let [handle, class, info, size] = this.check_shim_sig(
418 shim_sig!(
419 extern "system" fn(
420 winapi::HANDLE,
421 winapi::FILE_INFO_BY_HANDLE_CLASS,
422 *mut _,
423 u32,
424 ) -> winapi::BOOL
425 ),
426 link_name,
427 abi,
428 args,
429 )?;
430 let res = this.SetFileInformationByHandle(handle, class, info, size)?;
431 this.write_scalar(res, dest)?;
432 }
433 "FlushFileBuffers" => {
434 let [handle] = this.check_shim_sig(
435 shim_sig!(extern "system" fn(winapi::HANDLE) -> winapi::BOOL),
436 link_name,
437 abi,
438 args,
439 )?;
440 let res = this.FlushFileBuffers(handle)?;
441 this.write_scalar(res, dest)?;
442 }
443 "DeleteFileW" => {
444 let [file_name] = this.check_shim_sig(
445 shim_sig!(extern "system" fn(*const _) -> winapi::BOOL),
446 link_name,
447 abi,
448 args,
449 )?;
450 let res = this.DeleteFileW(file_name)?;
451 this.write_scalar(res, dest)?;
452 }
453 "SetFilePointerEx" => {
454 let [file, distance_to_move, new_file_pointer, move_method] = this.check_shim_sig(
455 shim_sig!(extern "system" fn(winapi::HANDLE, i64, *mut _, u32) -> winapi::BOOL),
457 link_name,
458 abi,
459 args,
460 )?;
461 let res =
462 this.SetFilePointerEx(file, distance_to_move, new_file_pointer, move_method)?;
463 this.write_scalar(res, dest)?;
464 }
465 "MoveFileExW" => {
466 let [existing_name, new_name, flags] = this.check_shim_sig(
467 shim_sig!(extern "system" fn(*const _, *const _, u32) -> winapi::BOOL),
468 link_name,
469 abi,
470 args,
471 )?;
472 let res = this.MoveFileExW(existing_name, new_name, flags)?;
473 this.write_scalar(res, dest)?;
474 }
475
476 "HeapAlloc" => {
478 let [handle, flags, size] = this.check_shim_sig(
480 shim_sig!(extern "system" fn(winapi::HANDLE, u32, usize) -> *mut _),
481 link_name,
482 abi,
483 args,
484 )?;
485 this.read_target_isize(handle)?;
486 let flags = this.read_scalar(flags)?.to_u32()?;
487 let size = this.read_target_usize(size)?;
488 const HEAP_ZERO_MEMORY: u32 = 0x00000008;
489 let init = if (flags & HEAP_ZERO_MEMORY) == HEAP_ZERO_MEMORY {
490 AllocInit::Zero
491 } else {
492 AllocInit::Uninit
493 };
494 let align = this.tcx.pointer_size().bytes().strict_mul(2);
497 let ptr = this.allocate_ptr(
498 Size::from_bytes(size),
499 Align::from_bytes(align).unwrap(),
500 MiriMemoryKind::WinHeap.into(),
501 init,
502 )?;
503 this.write_pointer(ptr, dest)?;
504 }
505 "HeapFree" => {
506 let [handle, flags, ptr] = this.check_shim_sig(
508 shim_sig!(extern "system" fn(winapi::HANDLE, u32, *mut _) -> winapi::BOOL),
509 link_name,
510 abi,
511 args,
512 )?;
513 this.read_target_isize(handle)?;
514 this.read_scalar(flags)?.to_u32()?;
515 let ptr = this.read_pointer(ptr)?;
516 if !this.ptr_is_null(ptr)? {
519 this.deallocate_ptr(ptr, None, MiriMemoryKind::WinHeap.into())?;
520 }
521 this.write_scalar(Scalar::from_i32(1), dest)?;
522 }
523 "HeapReAlloc" => {
524 let [handle, flags, old_ptr, size] = this.check_shim_sig(
526 shim_sig!(extern "system" fn(winapi::HANDLE, u32, *mut _, usize) -> *mut _),
527 link_name,
528 abi,
529 args,
530 )?;
531 this.read_target_isize(handle)?;
532 this.read_scalar(flags)?.to_u32()?;
533 let old_ptr = this.read_pointer(old_ptr)?;
534 let size = this.read_target_usize(size)?;
535 let align = this.tcx.pointer_size().bytes().strict_mul(2); let new_ptr = this.reallocate_ptr(
540 old_ptr,
541 None,
542 Size::from_bytes(size),
543 Align::from_bytes(align).unwrap(),
544 MiriMemoryKind::WinHeap.into(),
545 AllocInit::Uninit,
546 )?;
547 this.write_pointer(new_ptr, dest)?;
548 }
549 "LocalFree" => {
550 let [ptr] = this.check_shim_sig(
552 shim_sig!(extern "system" fn(winapi::HLOCAL) -> winapi::HLOCAL),
553 link_name,
554 abi,
555 args,
556 )?;
557 let ptr = this.read_pointer(ptr)?;
558 if !this.ptr_is_null(ptr)? {
561 this.deallocate_ptr(ptr, None, MiriMemoryKind::WinLocal.into())?;
562 }
563 this.write_null(dest)?;
564 }
565
566 "SetLastError" => {
568 let [error] = this.check_shim_sig(
569 shim_sig!(extern "system" fn(u32) -> ()),
570 link_name,
571 abi,
572 args,
573 )?;
574 let error = this.read_scalar(error)?;
575 this.set_last_error(error)?;
576 }
577 "GetLastError" => {
578 let [] = this.check_shim_sig(
579 shim_sig!(extern "system" fn() -> u32),
580 link_name,
581 abi,
582 args,
583 )?;
584 let last_error = this.get_last_error()?;
585 this.write_scalar(last_error, dest)?;
586 }
587 "RtlNtStatusToDosError" => {
588 let [status] = this.check_shim_sig(
589 shim_sig!(extern "system" fn(i32) -> u32),
590 link_name,
591 abi,
592 args,
593 )?;
594 let status = this.read_scalar(status)?.to_u32()?;
595 let err = match status {
596 0xC00000A2 => 19,
598 0xC0000098 => 1006,
600 0xC000007F => 112,
602 0xC0000185 => 1117,
604 0xC0000022 => 5,
606 _ => 317,
608 };
609 this.write_scalar(Scalar::from_i32(err), dest)?;
610 }
611
612 "GetSystemInfo" => {
614 let [system_info] = this.check_shim_sig(
617 shim_sig!(extern "system" fn(*mut _) -> ()),
618 link_name,
619 abi,
620 args,
621 )?;
622 let system_info =
623 this.deref_pointer_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?;
624 this.write_bytes_ptr(
626 system_info.ptr(),
627 iter::repeat_n(0u8, system_info.layout.size.bytes_usize()),
628 )?;
629 this.write_int_fields_named(
631 &[
632 ("dwPageSize", this.machine.page_size.into()),
633 ("dwNumberOfProcessors", this.machine.num_cpus.into()),
634 ],
635 &system_info,
636 )?;
637 }
638
639 "TlsAlloc" => {
641 let [] = this.check_shim_sig(
645 shim_sig!(extern "system" fn() -> u32),
646 link_name,
647 abi,
648 args,
649 )?;
650 let key = this.machine.tls.create_tls_key(None, dest.layout.size)?;
651 this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
652 }
653 "TlsGetValue" => {
654 let [key] = this.check_shim_sig(
655 shim_sig!(extern "system" fn(u32) -> *mut _),
656 link_name,
657 abi,
658 args,
659 )?;
660 let key = u128::from(this.read_scalar(key)?.to_u32()?);
661 let active_thread = this.active_thread();
662 let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
663 this.write_scalar(ptr, dest)?;
664 }
665 "TlsSetValue" => {
666 let [key, new_ptr] = this.check_shim_sig(
667 shim_sig!(extern "system" fn(u32, *mut _) -> winapi::BOOL),
668 link_name,
669 abi,
670 args,
671 )?;
672 let key = u128::from(this.read_scalar(key)?.to_u32()?);
673 let active_thread = this.active_thread();
674 let new_data = this.read_scalar(new_ptr)?;
675 this.machine.tls.store_tls(key, active_thread, new_data, &*this.tcx)?;
676
677 this.write_int(1, dest)?;
679 }
680 "TlsFree" => {
681 let [key] = this.check_shim_sig(
682 shim_sig!(extern "system" fn(u32) -> winapi::BOOL),
683 link_name,
684 abi,
685 args,
686 )?;
687 let key = u128::from(this.read_scalar(key)?.to_u32()?);
688 this.machine.tls.delete_tls_key(key)?;
689
690 this.write_int(1, dest)?;
692 }
693
694 "FlsAlloc" => {
696 let [dtor] = this.check_shim_sig(
698 shim_sig!(extern "system" fn(winapi::PFLS_CALLBACK_FUNCTION) -> u32),
699 link_name,
700 abi,
701 args,
702 )?;
703 let dtor = this.read_pointer(dtor)?;
704
705 let dtor = if !this.ptr_is_null(dtor)? {
707 Some((
708 this.get_ptr_fn(dtor)?.as_instance()?,
709 this.machine.current_user_relevant_span(),
710 ))
711 } else {
712 None
713 };
714
715 let key = this.machine.tls.create_tls_key(dtor, dest.layout.size)?;
716 this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
717 }
718 "FlsGetValue" => {
719 let [key] = this.check_shim_sig(
720 shim_sig!(extern "system" fn(u32) -> *mut _),
721 link_name,
722 abi,
723 args,
724 )?;
725 let key = u128::from(this.read_scalar(key)?.to_u32()?);
726 let active_thread = this.active_thread();
727 let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
728 this.write_scalar(ptr, dest)?;
729 }
730 "FlsSetValue" => {
731 let [key, new_ptr] = this.check_shim_sig(
732 shim_sig!(extern "system" fn(u32, *mut _) -> winapi::BOOL),
733 link_name,
734 abi,
735 args,
736 )?;
737 let key = u128::from(this.read_scalar(key)?.to_u32()?);
738 let active_thread = this.active_thread();
739 let new_data = this.read_scalar(new_ptr)?;
740 this.machine.tls.store_tls(key, active_thread, new_data, &*this.tcx)?;
741
742 this.write_int(1, dest)?;
744 }
745 "FlsFree" => {
746 let [key] = this.check_shim_sig(
747 shim_sig!(extern "system" fn(u32) -> winapi::BOOL),
748 link_name,
749 abi,
750 args,
751 )?;
752 let key = u128::from(this.read_scalar(key)?.to_u32()?);
753 let tls_entry = this.machine.tls.delete_tls_key(key)?;
754
755 if !tls_entry.data.is_empty() && tls_entry.dtor.is_some() {
757 throw_unsup_format!(
758 "calling `FlsFree` on a key with an associated dtor is not supported"
759 );
760 }
761
762 this.write_int(1, dest)?;
764 }
765 "IsThreadAFiber" => {
766 let [] = this.check_shim_sig(
767 shim_sig!(extern "system" fn() -> winapi::BOOL),
768 link_name,
769 abi,
770 args,
771 )?;
772
773 this.write_int(0, dest)?;
775 }
776
777 "GetCommandLineW" => {
779 let [] = this.check_shim_sig(
781 shim_sig!(extern "system" fn() -> *mut _),
782 link_name,
783 abi,
784 args,
785 )?;
786 this.write_pointer(
787 this.machine.cmd_line.expect("machine must be initialized"),
788 dest,
789 )?;
790 }
791
792 "GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => {
794 let [filetime] = this.check_shim_sig(
796 shim_sig!(extern "system" fn(*mut _) -> ()),
797 link_name,
798 abi,
799 args,
800 )?;
801 this.GetSystemTimeAsFileTime(link_name.as_str(), filetime)?;
802 }
803 "QueryPerformanceCounter" => {
804 let [performance_count] = this.check_shim_sig(
806 shim_sig!(extern "system" fn(*mut _) -> winapi::BOOL),
807 link_name,
808 abi,
809 args,
810 )?;
811 let result = this.QueryPerformanceCounter(performance_count)?;
812 this.write_scalar(result, dest)?;
813 }
814 "QueryPerformanceFrequency" => {
815 let [frequency] = this.check_shim_sig(
817 shim_sig!(extern "system" fn(*mut _) -> winapi::BOOL),
818 link_name,
819 abi,
820 args,
821 )?;
822 let result = this.QueryPerformanceFrequency(frequency)?;
823 this.write_scalar(result, dest)?;
824 }
825 "Sleep" => {
826 let [timeout] = this.check_shim_sig(
828 shim_sig!(extern "system" fn(u32) -> ()),
829 link_name,
830 abi,
831 args,
832 )?;
833
834 this.Sleep(timeout)?;
835 }
836 "CreateWaitableTimerExW" => {
837 let [attributes, name, flags, access] = this.check_shim_sig(
839 shim_sig!(extern "system" fn(*mut _, *const _, u32, u32) -> winapi::HANDLE),
840 link_name,
841 abi,
842 args,
843 )?;
844 this.read_pointer(attributes)?;
845 this.read_pointer(name)?;
846 this.read_scalar(flags)?.to_u32()?;
847 this.read_scalar(access)?.to_u32()?;
848 let not_supported = this.eval_windows("c", "ERROR_NOT_SUPPORTED");
850 this.set_last_error(not_supported)?;
851 this.write_null(dest)?;
852 }
853
854 "InitOnceBeginInitialize" => {
856 let [ptr, flags, pending, context] = this.check_shim_sig(
857 shim_sig!(extern "system" fn(*mut _, u32, *mut _, *mut _) -> winapi::BOOL),
858 link_name,
859 abi,
860 args,
861 )?;
862 this.InitOnceBeginInitialize(ptr, flags, pending, context, dest)?;
863 }
864 "InitOnceComplete" => {
865 let [ptr, flags, context] = this.check_shim_sig(
866 shim_sig!(extern "system" fn(*mut _, u32, *mut _) -> winapi::BOOL),
867 link_name,
868 abi,
869 args,
870 )?;
871 let result = this.InitOnceComplete(ptr, flags, context)?;
872 this.write_scalar(result, dest)?;
873 }
874 "WaitOnAddress" => {
875 let [ptr_op, compare_op, size_op, timeout_op] = this.check_shim_sig(
877 shim_sig!(extern "system" fn(*mut _, *mut _, usize, u32) -> winapi::BOOL),
879 link_name,
880 abi,
881 args,
882 )?;
883
884 this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?;
885 }
886 "WakeByAddressSingle" => {
887 let [ptr_op] = this.check_shim_sig(
889 shim_sig!(extern "system" fn(*mut _) -> ()),
890 link_name,
891 abi,
892 args,
893 )?;
894
895 this.WakeByAddressSingle(ptr_op)?;
896 }
897 "WakeByAddressAll" => {
898 let [ptr_op] = this.check_shim_sig(
900 shim_sig!(extern "system" fn(*mut _) -> ()),
901 link_name,
902 abi,
903 args,
904 )?;
905
906 this.WakeByAddressAll(ptr_op)?;
907 }
908
909 "GetProcAddress" => {
911 let [module, proc_name] = this.check_shim_sig(
913 shim_sig!(extern "system" fn(winapi::HMODULE, *const _) -> winapi::FARPROC),
914 link_name,
915 abi,
916 args,
917 )?;
918 this.read_target_isize(module)?;
919 let name = this.read_c_str(this.read_pointer(proc_name)?)?;
920 if let Ok(name) = str::from_utf8(name)
921 && is_dyn_sym(name)
922 {
923 let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name)));
924 this.write_pointer(ptr, dest)?;
925 } else {
926 this.write_null(dest)?;
927 }
928 }
929
930 "CreateThread" => {
932 let [security, stacksize, start, arg, flags, thread] = this.check_shim_sig(
933 shim_sig!(
934 extern "system" fn(
935 *mut _,
936 usize,
937 *mut _,
938 *mut _,
939 u32,
940 *mut _,
941 ) -> winapi::HANDLE
942 ),
943 link_name,
944 abi,
945 args,
946 )?;
947
948 let thread_id =
949 this.CreateThread(security, stacksize, start, arg, flags, thread)?;
950
951 this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?;
952 }
953 "WaitForSingleObject" => {
954 let [handle, timeout] = this.check_shim_sig(
955 shim_sig!(extern "system" fn(winapi::HANDLE, u32) -> u32),
956 link_name,
957 abi,
958 args,
959 )?;
960
961 this.WaitForSingleObject(handle, timeout, dest)?;
962 }
963 "GetCurrentProcess" => {
964 let [] = this.check_shim_sig(
965 shim_sig!(extern "system" fn() -> winapi::HANDLE),
966 link_name,
967 abi,
968 args,
969 )?;
970
971 this.write_scalar(
972 Handle::Pseudo(PseudoHandle::CurrentProcess).to_scalar(this),
973 dest,
974 )?;
975 }
976 "GetCurrentThread" => {
977 let [] = this.check_shim_sig(
978 shim_sig!(extern "system" fn() -> winapi::HANDLE),
979 link_name,
980 abi,
981 args,
982 )?;
983
984 this.write_scalar(
985 Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this),
986 dest,
987 )?;
988 }
989 "SetThreadDescription" => {
990 let [handle, name] = this.check_shim_sig(
991 shim_sig!(extern "system" fn(winapi::HANDLE, *const _) -> i32),
992 link_name,
993 abi,
994 args,
995 )?;
996
997 let handle = this.read_handle(handle, "SetThreadDescription")?;
998 let name = this.read_wide_str(this.read_pointer(name)?)?;
999
1000 let thread = match handle {
1001 Handle::Thread(thread) => thread,
1002 Handle::Pseudo(PseudoHandle::CurrentThread) => this.active_thread(),
1003 _ => this.invalid_handle("SetThreadDescription")?,
1004 };
1005 this.set_thread_name(thread, String::from_utf16_lossy(&name).into_bytes());
1007 this.write_scalar(Scalar::from_u32(0), dest)?;
1008 }
1009 "GetThreadDescription" => {
1010 let [handle, name_ptr] = this.check_shim_sig(
1011 shim_sig!(extern "system" fn(winapi::HANDLE, *mut _) -> i32),
1012 link_name,
1013 abi,
1014 args,
1015 )?;
1016
1017 let handle = this.read_handle(handle, "GetThreadDescription")?;
1018 let name_ptr = this.deref_pointer_as(name_ptr, this.machine.layouts.mut_raw_ptr)?; let thread = match handle {
1021 Handle::Thread(thread) => thread,
1022 Handle::Pseudo(PseudoHandle::CurrentThread) => this.active_thread(),
1023 _ => this.invalid_handle("GetThreadDescription")?,
1024 };
1025 let name = this.get_thread_name(thread).unwrap_or(b"").to_owned();
1027 let name = this.alloc_os_str_as_wide_str(
1028 bytes_to_os_str(&name)?,
1029 MiriMemoryKind::WinLocal.into(),
1030 )?;
1031 let name = Scalar::from_maybe_pointer(name, this);
1032 let res = Scalar::from_u32(0);
1033
1034 this.write_scalar(name, &name_ptr)?;
1035 this.write_scalar(res, dest)?;
1036 }
1037 "GetThreadId" => {
1038 let [handle] = this.check_shim_sig(
1039 shim_sig!(extern "system" fn(winapi::HANDLE) -> u32),
1040 link_name,
1041 abi,
1042 args,
1043 )?;
1044 let handle = this.read_handle(handle, "GetThreadId")?;
1045 let thread = match handle {
1046 Handle::Thread(thread) => thread,
1047 Handle::Pseudo(PseudoHandle::CurrentThread) => this.active_thread(),
1048 _ => this.invalid_handle("GetThreadDescription")?,
1049 };
1050 this.write_scalar(Scalar::from_u32(thread.to_u32()), dest)?;
1051 }
1052 "GetCurrentThreadId" => {
1053 let [] = this.check_shim_sig(
1054 shim_sig!(extern "system" fn() -> u32),
1055 link_name,
1056 abi,
1057 args,
1058 )?;
1059 this.write_scalar(Scalar::from_u32(this.active_thread().to_u32()), dest)?;
1060 }
1061
1062 "ExitProcess" => {
1064 let [code] = this.check_shim_sig(
1066 shim_sig!(extern "system" fn(u32) -> ()),
1067 link_name,
1068 abi,
1069 args,
1070 )?;
1071 let code = this.read_scalar(code)?.to_i32()?;
1073 throw_machine_stop!(TerminationInfo::Exit { code, leak_check: false });
1074 }
1075 "SystemFunction036" => {
1076 let [ptr, len] = this.check_shim_sig(
1079 shim_sig!(extern "system" fn(*mut _, u32) -> u8),
1081 link_name,
1082 abi,
1083 args,
1084 )?;
1085 let ptr = this.read_pointer(ptr)?;
1086 let len = this.read_scalar(len)?.to_u32()?;
1087 this.gen_random(ptr, len.into())?;
1088 this.write_scalar(Scalar::from_bool(true), dest)?;
1089 }
1090 "ProcessPrng" => {
1091 let [ptr, len] = this.check_shim_sig(
1094 shim_sig!(extern "system" fn(*mut _, usize) -> winapi::BOOL),
1095 link_name,
1096 abi,
1097 args,
1098 )?;
1099 let ptr = this.read_pointer(ptr)?;
1100 let len = this.read_target_usize(len)?;
1101 this.gen_random(ptr, len)?;
1102 this.write_int(1, dest)?;
1103 }
1104 "BCryptGenRandom" => {
1105 let [algorithm, ptr, len, flags] = this.check_shim_sig(
1107 shim_sig!(extern "system" fn(*mut _, *mut _, u32, u32) -> i32),
1108 link_name,
1109 abi,
1110 args,
1111 )?;
1112 let algorithm = this.read_scalar(algorithm)?;
1113 let algorithm = algorithm.to_target_usize(this)?;
1114 let ptr = this.read_pointer(ptr)?;
1115 let len = this.read_scalar(len)?.to_u32()?;
1116 let flags = this.read_scalar(flags)?.to_u32()?;
1117 match flags {
1118 0 => {
1119 if algorithm != 0x81 {
1120 throw_unsup_format!(
1122 "BCryptGenRandom algorithm must be BCRYPT_RNG_ALG_HANDLE when the flag is 0"
1123 );
1124 }
1125 }
1126 2 => {
1127 if algorithm != 0 {
1129 throw_unsup_format!(
1130 "BCryptGenRandom algorithm must be NULL when the flag is BCRYPT_USE_SYSTEM_PREFERRED_RNG"
1131 );
1132 }
1133 }
1134 _ => {
1135 throw_unsup_format!(
1136 "BCryptGenRandom is only supported with BCRYPT_USE_SYSTEM_PREFERRED_RNG or BCRYPT_RNG_ALG_HANDLE"
1137 );
1138 }
1139 }
1140 this.gen_random(ptr, len.into())?;
1141 this.write_null(dest)?; }
1143 "GetConsoleScreenBufferInfo" => {
1144 let [console, buffer_info] = this.check_shim_sig(
1147 shim_sig!(extern "system" fn(winapi::HANDLE, *mut _) -> winapi::BOOL),
1148 link_name,
1149 abi,
1150 args,
1151 )?;
1152 this.read_target_isize(console)?;
1153 this.deref_pointer(buffer_info)?;
1155 this.write_null(dest)?;
1158 }
1159 "GetStdHandle" => {
1160 let [which] = this.check_shim_sig(
1162 shim_sig!(extern "system" fn(u32) -> winapi::HANDLE),
1163 link_name,
1164 abi,
1165 args,
1166 )?;
1167 let res = this.GetStdHandle(which)?;
1168 this.write_scalar(res, dest)?;
1169 }
1170 "DuplicateHandle" => {
1171 let [src_proc, src_handle, target_proc, target_handle, access, inherit, options] =
1172 this.check_shim_sig(
1173 shim_sig!(
1174 extern "system" fn(
1175 winapi::HANDLE,
1176 winapi::HANDLE,
1177 winapi::HANDLE,
1178 *mut _,
1179 u32,
1180 winapi::BOOL,
1181 u32,
1182 ) -> winapi::BOOL
1183 ),
1184 link_name,
1185 abi,
1186 args,
1187 )?;
1188 let res = this.DuplicateHandle(
1189 src_proc,
1190 src_handle,
1191 target_proc,
1192 target_handle,
1193 access,
1194 inherit,
1195 options,
1196 )?;
1197 this.write_scalar(res, dest)?;
1198 }
1199 "CloseHandle" => {
1200 let [handle] = this.check_shim_sig(
1201 shim_sig!(extern "system" fn(winapi::HANDLE) -> winapi::BOOL),
1202 link_name,
1203 abi,
1204 args,
1205 )?;
1206
1207 let ret = this.CloseHandle(handle)?;
1208
1209 this.write_scalar(ret, dest)?;
1210 }
1211 "GetModuleFileNameW" => {
1212 let [handle, filename, size] = this.check_shim_sig(
1214 shim_sig!(extern "system" fn(winapi::HMODULE, *mut _, u32) -> u32),
1215 link_name,
1216 abi,
1217 args,
1218 )?;
1219 this.check_no_isolation("`GetModuleFileNameW`")?;
1220
1221 let handle = this.read_handle(handle, "GetModuleFileNameW")?;
1222 let filename = this.read_pointer(filename)?;
1223 let size = this.read_scalar(size)?.to_u32()?;
1224
1225 if handle != Handle::Null {
1226 throw_unsup_format!("`GetModuleFileNameW` only supports the NULL handle");
1227 }
1228
1229 let path = std::env::current_exe().unwrap();
1232 let (all_written, size_needed) =
1233 this.write_path_to_wide_str_truncated(&path, filename, size.into())?;
1234
1235 if all_written {
1236 this.write_int(size_needed.strict_sub(1), dest)?;
1240 } else {
1241 this.write_int(size, dest)?;
1246 let insufficient_buffer = this.eval_windows("c", "ERROR_INSUFFICIENT_BUFFER");
1247 this.set_last_error(insufficient_buffer)?;
1248 }
1249 }
1250 "FormatMessageW" => {
1251 let [flags, module, message_id, language_id, buffer, size, arguments] = this
1253 .check_shim_sig(
1254 shim_sig!(
1255 extern "system" fn(u32, *const _, u32, u32, *mut _, u32, *mut _) -> u32
1256 ),
1257 link_name,
1258 abi,
1259 args,
1260 )?;
1261
1262 let flags = this.read_scalar(flags)?.to_u32()?;
1263 let _module = this.read_pointer(module)?; let message_id = this.read_scalar(message_id)?;
1265 let _language_id = this.read_scalar(language_id)?.to_u32()?;
1266 let buffer = this.read_pointer(buffer)?;
1267 let size = this.read_scalar(size)?.to_u32()?;
1268 let _arguments = this.read_pointer(arguments)?;
1269
1270 if flags != 4096u32 | 512u32 {
1273 throw_unsup_format!("FormatMessageW: unsupported flags {flags:#x}");
1274 }
1275
1276 let error = this.try_errnum_to_io_error(message_id)?;
1277 let formatted = match error {
1278 Some(err) => format!("{err}"),
1279 None => format!("<unknown error in FormatMessageW: {message_id}>"),
1280 };
1281 let (complete, length) =
1282 this.write_os_str_to_wide_str(OsStr::new(&formatted), buffer, size.into())?;
1283 if !complete {
1284 throw_unsup_format!("FormatMessageW: buffer not big enough");
1287 }
1288 this.write_int(length.strict_sub(1), dest)?;
1290 }
1291
1292 "_Unwind_RaiseException" => {
1293 if this.tcx.sess.target.env != Env::Gnu {
1299 throw_unsup_format!(
1300 "`_Unwind_RaiseException` is not supported on non-MinGW Windows",
1301 );
1302 }
1303 let [payload] = this.check_shim_sig(
1305 shim_sig!(extern "C" fn(*mut _) -> unwind::libunwind::_Unwind_Reason_Code),
1306 link_name,
1307 abi,
1308 args,
1309 )?;
1310 this.handle_miri_start_unwind(payload)?;
1311 return interp_ok(EmulateItemResult::NeedsUnwind);
1312 }
1313
1314 "GetProcessHeap" if this.frame_in_std() => {
1317 let [] = this.check_shim_sig(
1318 shim_sig!(extern "system" fn() -> winapi::HANDLE),
1319 link_name,
1320 abi,
1321 args,
1322 )?;
1323 this.write_int(1, dest)?;
1326 }
1327 "GetModuleHandleA" if this.frame_in_std() => {
1328 let [_module_name] = this.check_shim_sig(
1329 shim_sig!(extern "system" fn(*const _) -> winapi::HMODULE),
1330 link_name,
1331 abi,
1332 args,
1333 )?;
1334 this.write_int(1, dest)?;
1336 }
1337 "SetConsoleTextAttribute" if this.frame_in_std() => {
1338 let [_console_output, _attribute] = this.check_shim_sig(
1339 shim_sig!(extern "system" fn(winapi::HANDLE, u16) -> winapi::BOOL),
1340 link_name,
1341 abi,
1342 args,
1343 )?;
1344 this.write_null(dest)?;
1346 }
1347 "GetConsoleMode" if this.frame_in_std() => {
1348 let [console, mode] = this.check_shim_sig(
1349 shim_sig!(extern "system" fn(winapi::HANDLE, *mut _) -> winapi::BOOL),
1350 link_name,
1351 abi,
1352 args,
1353 )?;
1354 this.read_target_isize(console)?;
1355 this.deref_pointer_as(mode, this.machine.layouts.u32)?;
1356 this.write_null(dest)?;
1358 }
1359 "GetFileType" if this.frame_in_std() => {
1360 let [_file] = this.check_shim_sig(
1361 shim_sig!(extern "system" fn(winapi::HANDLE) -> u32),
1362 link_name,
1363 abi,
1364 args,
1365 )?;
1366 this.write_null(dest)?;
1368 }
1369 "AddVectoredExceptionHandler" if this.frame_in_std() => {
1370 let [_first, _handler] = this.check_shim_sig(
1371 shim_sig!(extern "system" fn(u32, *mut _) -> *mut _),
1372 link_name,
1373 abi,
1374 args,
1375 )?;
1376 this.write_int(1, dest)?;
1378 }
1379 "SetThreadStackGuarantee" if this.frame_in_std() => {
1380 let [_stack_size_in_bytes] = this.check_shim_sig(
1381 shim_sig!(extern "system" fn(*mut _) -> winapi::BOOL),
1382 link_name,
1383 abi,
1384 args,
1385 )?;
1386 this.write_int(1, dest)?;
1388 }
1389 "SwitchToThread" if this.frame_in_std() => {
1391 let [] = this.check_shim_sig(
1392 shim_sig!(extern "system" fn() -> winapi::BOOL),
1393 link_name,
1394 abi,
1395 args,
1396 )?;
1397
1398 this.yield_active_thread();
1399
1400 this.write_null(dest)?;
1402 }
1403
1404 _ => return interp_ok(EmulateItemResult::NotSupported),
1405 }
1406
1407 interp_ok(EmulateItemResult::NeedsReturn)
1408 }
1409}