1use std::ffi::c_void;
16use std::sync::atomic::{AtomicPtr, AtomicU32, Ordering};
17
18use windows::Win32::Devices::Display::HDEV;
19use windows::Win32::Graphics::Gdi::HMONITOR;
20use windows::Win32::UI::Input::KeyboardAndMouse::HKL;
21use windows::Win32::UI::WindowsAndMessaging::MESSAGEBOX_STYLE;
22use windows::{
23 core::{w, PCSTR},
24 Win32::{
25 Foundation::{
26 BOOL, HANDLE, HWND, LPARAM, LRESULT, NTSTATUS, POINT, UNICODE_STRING, WPARAM,
27 },
28 Graphics::Gdi::{HDC, HRGN},
29 System::{
30 LibraryLoader::{GetModuleHandleW, GetProcAddress},
31 StationsAndDesktops::HDESK,
32 },
33 UI::WindowsAndMessaging::{GET_CLASS_LONG_INDEX, HDWP, HICON, HMENU, SYSTEM_METRICS_INDEX},
34 },
35};
36
37use crate::{
38 error::UserCallError,
39 indices::get_index,
40 version::{get_os_version, has_dedicated_syscalls, OsVersion},
41};
42trait IntoCallParam {
43 fn into_call_param(self) -> usize;
44}
45
46macro_rules! into_call_param_self_as {
47 ($($type:ty),+) => {
48 $(
49 impl IntoCallParam for $type {
50 fn into_call_param(self) -> usize {
51 self as _
52 }
53 }
54 )+
55 };
56}
57
58macro_rules! into_call_param_self_0_as {
59 ($($type:ty),+) => {
60 $(
61 impl IntoCallParam for $type {
62 fn into_call_param(self) -> usize {
63 self.0 as _
64 }
65 }
66 )+
67 };
68}
69
70macro_rules! into_call_param_transmute {
71 ($($type:ty),+) => {
72 $(
73 impl IntoCallParam for $type {
74 fn into_call_param(self) -> usize {
75 unsafe {
77 std::mem::transmute(self)
78 }
79 }
80 }
81 )+
82 };
83}
84
85impl<T> IntoCallParam for *const T {
86 fn into_call_param(self) -> usize {
87 self as _
88 }
89}
90
91impl<T> IntoCallParam for *mut T {
92 fn into_call_param(self) -> usize {
93 self as _
94 }
95}
96
97into_call_param_self_as!(i16, i32, u32, usize);
98into_call_param_self_0_as!(
99 BOOL,
100 GET_CLASS_LONG_INDEX,
101 LRESULT,
102 LPARAM,
103 MESSAGEBOX_STYLE,
104 SYSTEM_METRICS_INDEX,
105 WPARAM
106);
107into_call_param_transmute!(HANDLE, HDC, HDESK, HDEV, HRGN, HWND);
108
109trait FromCallReturn {
110 fn from_call_return(value: usize) -> Self;
111}
112
113macro_rules! from_call_return_as {
114 ($($type:ty),+) => {
115 $(
116 impl FromCallReturn for $type {
117 fn from_call_return(value: usize) -> Self {
118 value as _
119 }
120 }
121 )+
122 };
123}
124
125macro_rules! from_call_return_self {
126 ($($type:ty),+) => {
127 $(
128 impl FromCallReturn for $type {
129 fn from_call_return(value: usize) -> Self {
130 Self(value as _)
131 }
132 }
133 )+
134 };
135}
136
137impl FromCallReturn for () {
138 fn from_call_return(_value: usize) -> Self {}
139}
140
141impl<T> FromCallReturn for *const T {
142 fn from_call_return(value: usize) -> Self {
143 value as _
144 }
145}
146
147impl<T> FromCallReturn for *mut T {
148 fn from_call_return(value: usize) -> Self {
149 value as _
150 }
151}
152
153from_call_return_as!(i32, u32, usize);
154from_call_return_self!(
155 BOOL, HANDLE, HDESK, HDWP, HICON, HKL, HMENU, HMONITOR, HWND, LPARAM, LRESULT, NTSTATUS
156);
157
158macro_rules! nt_user_call_fn_body {
159 ( $syscall:ident $call:ident ) => {{
160 user_call::$syscall($call)
161 }};
162
163 ( $syscall:ident $call:ident $($paramname:ident)* ) => {{
164 user_call::$syscall($(IntoCallParam::into_call_param($paramname)),*, $call)
165 }};
166}
167
168macro_rules! nt_user_call_fn {
169 (
170 #[doc = $doc:literal] $syscall:ident $call:ident $vis:vis fn $name:ident ($($paramname:ident: $paramtype:ty),*) -> $rettype:ty
171 ) => {
172 paste::paste! {
173 #[doc = $doc]
174 #[allow(clippy::empty_docs, clippy::missing_safety_doc)]
175 #[expect(non_snake_case)]
176 $vis unsafe fn [< NtUser $name >] ($($paramname: $paramtype),*) -> Result<$rettype, UserCallError> {
177 if has_dedicated_syscalls() {
178 crate::macros::load_runtime_fn_body!(["win32u"] $name($($paramname: $paramtype),*) -> $rettype)
180 } else {
181 static CALL_ATOMIC: AtomicU32 = AtomicU32::new(u16::MAX as u32 + 1);
182
183 let call_index = match CALL_ATOMIC.load(Ordering::Relaxed) {
184 index@..=0xFFFFu32 => index,
185 u32::MAX => return Err(UserCallError::CallNotFound),
186 _ => match get_index(NtUserCall::$name) {
187 Some(index) => {
188 CALL_ATOMIC.store(index as _, Ordering::SeqCst);
189 index as _
190 },
191 None => {
192 CALL_ATOMIC.store(u32::MAX, Ordering::SeqCst);
193 return Err(UserCallError::CallNotFound);
194 }
195 }
196 };
197
198 let $call = call_index;
199
200 nt_user_call_fn_body!($syscall $call $($paramname)*).map(FromCallReturn::from_call_return)
201 }
202 }
203 }
204 };
205}
206
207macro_rules! nt_user_call {
208 ( #![doc = $enumdoc:literal] $(#[doc = $doc:literal] $syscall:ident $vis:vis fn $name:ident ($($funcdef:tt)*) -> $rettype:ty;)+ ) => {
209 #[doc = $enumdoc]
210 #[allow(non_camel_case_types)]
211 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
212 pub enum NtUserCall {
213 $($name),+
214 }
215
216 $(nt_user_call_fn! { #[doc = $doc] $syscall CALL $vis fn $name ($($funcdef)*) -> $rettype })+
217 };
218}
219
220nt_user_call! {
221 #![doc = r#"
222 The sum of all functions accessible via the `NtUserCall*` family of system calls in all supported operating systems.
223 The variants will be mapped to the respective function indices in [`crate::indices`] at runtime.
224 "#]
225
226 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createmenu>"]
228 NtUserCallNoParam pub fn CreateMenu() -> HMENU;
229
230 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createpopupmenu>"]
231 NtUserCallNoParam pub fn CreatePopupMenu() -> HMENU;
232
233 #[doc = ""]
234 NtUserCallNoParam pub fn AllowForegroundActivation() -> ();
235
236 #[doc = ""]
237 NtUserCallNoParam pub fn CancelQueueEventCompletionPacket() -> ();
238
239 #[doc = ""]
240 NtUserCallNoParam pub fn ClearWakeMask() -> ();
241
242 #[doc = ""]
243 NtUserCallNoParam pub fn CreateSystemThreads() -> ();
244
245 #[doc = ""]
246 NtUserCallNoParam pub fn DesktopHasWatermarkText() -> BOOL;
247
248 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroycaret>"]
249 NtUserCallNoParam pub fn DestroyCaret() -> BOOL;
250
251 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-disableprocesswindowsghosting>"]
252 NtUserCallNoParam pub fn DisableProcessWindowsGhosting() -> ();
253
254 #[doc = ""]
255 NtUserCallNoParam pub fn DrainThreadCoreMessagingCompletions() -> BOOL;
256
257 #[doc = ""]
258 NtUserCallNoParam pub fn GetDeviceChangeInfo() -> u32;
259
260 #[doc = ""]
261 NtUserCallNoParam pub fn GetIMEShowStatus() -> BOOL;
262
263 #[doc = ""]
264 NtUserCallNoParam pub fn GetInputDesktop() -> HDESK;
265
266 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessagepos>"]
267 NtUserCallNoParam pub fn GetMessagePos() -> u32;
268
269 #[doc = ""]
270 NtUserCallNoParam pub fn GetQueueIocp() -> HANDLE;
271
272 #[doc = ""]
273 NtUserCallNoParam pub fn GetUnpredictedMessagePos() -> u32;
274
275 #[doc = ""]
276 NtUserCallNoParam pub fn HandleSystemThreadCreationFailure() -> BOOL;
277
278 #[doc = ""]
279 NtUserCallNoParam pub fn HideCursorNoCapture() -> ();
280
281 #[doc = ""]
282 NtUserCallNoParam pub fn IsQueueAttached() -> BOOL;
283
284 #[doc = ""]
285 NtUserCallNoParam pub fn LoadCursorsAndIcons() -> BOOL;
286
287 #[doc = ""]
288 NtUserCallNoParam pub fn LoadUserApiHook() -> ();
289
290 #[doc = ""]
291 NtUserCallNoParam pub fn PrepareForLogoff() -> BOOL;
292
293 #[doc = ""]
294 NtUserCallNoParam pub fn ReassociateQueueEventCompletionPacket() -> BOOL;
295
296 #[doc = ""]
297 NtUserCallNoParam pub fn ReleaseCapture() -> BOOL;
298
299 #[doc = ""]
300 NtUserCallNoParam pub fn RemoveQueueCompletion() -> BOOL;
301
302 #[doc = ""]
303 NtUserCallNoParam pub fn ResetDblClk() -> BOOL;
304
305 #[doc = ""]
306 NtUserCallNoParam pub fn ZapActiveAndFocus() -> BOOL;
307
308 #[doc = ""]
309 NtUserCallNoParam pub fn RemoteConsoleShadowStop() -> ();
310
311 #[doc = ""]
312 NtUserCallNoParam pub fn RemoteDisconnect() -> ();
313
314 #[doc = ""]
315 NtUserCallNoParam pub fn RemoteLogoff() -> NTSTATUS;
316
317 #[doc = "Always returns STATUS_NOT_SUPPORTED."]
318 NtUserCallNoParam pub fn RemoteNtSecurity() -> NTSTATUS;
319
320 #[doc = "Always returns STATUS_NOT_SUPPORTED."]
321 NtUserCallNoParam pub fn EditionPostKeyboardInputMessage() -> NTSTATUS;
322
323 #[doc = "May only be called by CSRSS, returns STATUS_ACCESS_DENIED otherwise."]
324 NtUserCallNoParam pub fn RemoteShadowSetup() -> NTSTATUS;
325
326 #[doc = "May only be called by CSRSS, returns STATUS_ACCESS_DENIED otherwise."]
327 NtUserCallNoParam pub fn RemoteShadowStop() -> NTSTATUS;
328
329 #[doc = "May only be called by CSRSS, returns STATUS_ACCESS_DENIED otherwise."]
330 NtUserCallNoParam pub fn RemotePassthruEnable() -> NTSTATUS;
331
332 #[doc = "May only be called by CSRSS, returns STATUS_ACCESS_DENIED otherwise."]
333 NtUserCallNoParam pub fn RemotePassthruDisable() -> NTSTATUS;
334
335 #[doc = ""]
336 NtUserCallNoParam pub fn RemoteConnectState() -> usize;
337
338 #[doc = ""]
339 NtUserCallNoParam pub fn TraceLoggingSendMixedModeTelemetry() -> BOOL;
340
341 #[doc = ""]
342 NtUserCallNoParam pub fn UpdatePerUserImmEnabling() -> BOOL;
343
344 #[doc = ""]
345 NtUserCallNoParam pub fn UserPowerCalloutWorker() -> BOOL;
346
347 #[doc = "May only be called by CSRSS, returns STATUS_UNSUPPORTED otherwise."]
348 NtUserCallNoParam pub fn WakeRITForShutdown() -> NTSTATUS;
349
350 #[doc = ""]
351 NtUserCallNoParam pub fn DoInitMessagePumpHook() -> BOOL;
352
353 #[doc = ""]
354 NtUserCallNoParam pub fn DoUninitMessagePumpHook() -> BOOL;
355
356 #[doc = ""]
357 NtUserCallNoParam pub fn EnableMiPShellThread() -> BOOL;
358
359 #[doc = ""]
360 NtUserCallNoParam pub fn IsMiPShellThreadEnabled() -> BOOL;
361
362 #[doc = ""]
363 NtUserCallNoParam pub fn EnableMouseInPointerForThread() -> BOOL;
364
365 #[doc = ""]
366 NtUserCallNoParam pub fn DeferredDesktopRotation() -> i32;
367
368 #[doc = ""]
369 NtUserCallNoParam pub fn EnablePerMonitorMenuScaling() -> BOOL;
370
371 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-begindeferwindowpos>"]
372 NtUserCallOneParam pub fn BeginDeferWindowPos(nNumWindows: i32) -> HDWP;
373
374 #[doc = ""]
375 NtUserCallOneParam pub fn GetSendMessageReceiver(dwThreadId: u32) -> HWND;
376
377 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-windowfromdc>"]
378 NtUserCallOneParam pub fn WindowFromDC(hdc: HDC) -> HWND;
379
380 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-allowsetforegroundwindow>"]
381 NtUserCallOneParam pub fn AllowSetForegroundWindow(dwProcessId: u32) -> u32;
382
383 #[doc = ""]
384 NtUserCallOneParam pub fn CreateEmptyCursorObject(param: BOOL) -> u32;
385
386 #[doc = ""]
387 NtUserCallOneParam pub fn CsDdeUninitialize(dde_object: usize) -> BOOL;
388
389 #[doc = "NOP"]
390 NtUserCallOneParam pub fn DirectedYield(param: usize) -> usize;
391
392 #[doc = ""]
393 NtUserCallOneParam pub fn KbdNlsFuncTypeDummy(param: usize) -> u32;
394
395 #[doc = ""]
396 NtUserCallOneParam pub fn EditionGetExecutionEvironment(param: usize) -> BOOL;
397
398 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumclipboardformats>"]
399 NtUserCallOneParam pub fn EnumClipboardFormats(format: u32) -> u32;
400
401 #[doc = ""]
402 NtUserCallOneParam pub fn GetInputEvent(wake_mask_and_flags: u32) -> HANDLE;
403
404 #[doc = ""]
405 NtUserCallOneParam pub fn GetKeyboardLayout(dwThread: u32) -> HKL;
406
407 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getkeyboardtype>"]
408 NtUserCallOneParam pub fn GetKeyboardType(nTypeFlag: i32) -> i32;
409
410 #[doc = ""]
411 NtUserCallOneParam pub fn GetProcessDefaultLayout(pdwDefaultLayout: *mut u32) -> BOOL;
412
413 #[doc = ""]
414 NtUserCallOneParam pub fn GetQueueStatus(flags: u32) -> u32;
415
416 #[doc = ""]
417 NtUserCallOneParam pub fn GetWinStationInfo(ptr: *mut c_void) -> BOOL;
418
419 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-locksetforegroundwindow>"]
420 NtUserCallOneParam pub fn LockSetForegroundWindow(uLockCode: u32) -> BOOL;
421
422 #[doc = ""]
423 NtUserCallOneParam pub fn LW_LoadFonts(unknown: i32) -> BOOL;
424
425 #[doc = ""]
426 NtUserCallOneParam pub fn MapDesktopObject(handle: *mut c_void) -> *mut c_void;
427
428 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebeep>"]
429 NtUserCallOneParam pub fn MessageBeep(uType: MESSAGEBOX_STYLE) -> BOOL;
430
431 #[doc = ""]
432 NtUserCallOneParam pub fn PlayEventSound(unknown: u32) -> BOOL;
433
434 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postquitmessage>"]
435 NtUserCallOneParam pub fn PostQuitMessage(nExitCode: i32) -> ();
436
437 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-realizepalette>"]
438 NtUserCallOneParam pub fn RealizePalette(hdc: HDC) -> u32;
439
440 #[doc = ""]
441 NtUserCallOneParam pub fn RegisterLPK(unknown: u32) -> BOOL;
442
443 #[doc = ""]
444 NtUserCallOneParam pub fn RegisterSystemThread(unknown_flags: u32) -> BOOL;
445
446 #[doc = ""]
447 NtUserCallOneParam pub fn RemoteReconnect(unknown: *mut c_void) -> NTSTATUS;
448
449 #[doc = "May only be called by CSRSS, returns STATUS_ACCESS_DENIED otherwise."]
450 NtUserCallOneParam pub fn RemoteThinwireStats(stats: *mut c_void) -> NTSTATUS;
451
452 #[doc = ""]
453 NtUserCallOneParam pub fn ReleaseDC(hdc: HDC) -> BOOL;
454
455 #[doc = "May only be called by CSRSS, returns STATUS_ACCESS_DENIED otherwise."]
456 NtUserCallOneParam pub fn RemoteNotify(unknown: *const u32) -> NTSTATUS;
457
458 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-replymessage>"]
459 NtUserCallOneParam pub fn ReplyMessage(lResult: LRESULT) -> BOOL;
460
461 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setcaretblinktime>"]
462 NtUserCallOneParam pub fn SetCaretBlinkTime(uMSeconds: u32) -> BOOL;
463
464 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setdoubleclicktime>"]
465 NtUserCallOneParam pub fn SetDoubleClickTime(unnamedParam1: u32) -> BOOL;
466
467 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setmessageextrainfo>"]
468 NtUserCallOneParam pub fn SetMessageExtraInfo(lParam: LPARAM) -> LPARAM;
469
470 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdefaultlayout>"]
471 NtUserCallOneParam pub fn SetProcessDefaultLayout(dwDefaultLayout: u32) -> BOOL;
472
473 #[doc = "May only be called by winlogon, returns FALSE otherwise."]
474 NtUserCallOneParam pub fn SetWatermarkStrings(param: *const UNICODE_STRING) -> BOOL;
475
476 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showcursor>"]
477 NtUserCallOneParam pub fn ShowCursor(bShow: BOOL) -> i32;
478
479 #[doc = ""]
480 NtUserCallOneParam pub fn ShowStartGlass(param: u32) -> BOOL;
481
482 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-swapmousebutton>"]
483 NtUserCallOneParam pub fn SwapMouseButton(fSwap: BOOL) -> BOOL;
484
485 #[doc = ""]
486 NtUserCallOneParam pub fn WOWModuleUnload(param: i16) -> BOOL;
487
488 #[doc = "May only be called by winlogon."]
489 NtUserCallOneParam pub fn DwmLockScreenUpdates(lock: BOOL) -> i32;
490
491 #[doc = "May only be called by dwm, returns FALSE otherwise."]
492 NtUserCallOneParam pub fn EnableSessionForMMCSS(enable: BOOL) -> BOOL;
493
494 #[doc = ""]
495 NtUserCallOneParam pub fn SetWaitForQueueAttach(wait: BOOL) -> BOOL;
496
497 #[doc = ""]
498 NtUserCallOneParam pub fn ThreadMessageQueueAttached(thread_id: u32) -> BOOL;
499
500 #[doc = "May only be called by the immersive broker, otherwise returns 0 with GetLastError() == ERROR_ACCESS_DENIED."]
501 NtUserCallOneParam pub fn PostUIActions(wparam: WPARAM) -> LRESULT;
502
503 #[doc = ""]
504 NtUserCallOneParam pub fn EnsureDpiDepSysMetCacheForPlateau(dpi: u32) -> BOOL;
505
506 #[doc = ""]
507 NtUserCallOneParam pub fn ForceEnableNumpadTranslation(param: u32) -> u32;
508
509 #[doc = ""]
510 NtUserCallOneParam pub fn SetTSFEventState(state: u32) -> BOOL;
511
512 #[doc = ""]
513 NtUserCallOneParam pub fn SetShellChangeNotifyHWND(hwnd: HWND) -> BOOL;
514
515 #[doc = ""]
516 NtUserCallHwnd pub fn DeregisterShellHookWindow(hwnd: HWND) -> BOOL;
517
518 #[doc = ""]
519 NtUserCallHwnd pub fn DWP_GetEnabledPopup(hwnd: HWND) -> usize;
520
521 #[doc = ""]
522 NtUserCallHwnd pub fn DWP_GetEnabledPopupOffset(hwnd: HWND) -> usize;
523
524 #[doc = ""]
525 NtUserCallHwnd pub fn GetModernAppWindow(hwnd: HWND) -> HWND;
526
527 #[doc = ""]
528 NtUserCallHwnd pub fn GetWindowContextHelpId(hwnd: HWND) -> ();
529
530 #[doc = ""]
531 NtUserCallHwnd pub fn RegisterShellHookWindow(hwnd: HWND) -> ();
532
533 #[doc = ""]
534 NtUserCallHwnd pub fn SetMsgBox(hwnd: HWND) -> BOOL;
535
536 #[doc = ""]
537 NtUserCallHwndSafe pub fn InitThreadCoreMessagingIocp(hwnd: HWND) -> HANDLE;
538
539 #[doc = ""]
540 NtUserCallHwndSafe pub fn ScheduleDispatchNotification(hwnd: HWND) -> i32;
541
542 #[doc = ""]
543 NtUserCallHwndSafe pub fn SetProgmanWindow(hwnd: HWND) -> BOOL;
544
545 #[doc = ""]
546 NtUserCallHwndOpt pub fn SetTaskmanWindow(hwnd: HWND) -> BOOL;
547
548 #[doc = "See <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclasslongptrw>. `index` may be GCLP_HCURSOR or GCLP_HICON."]
549 NtUserCallHwndParam pub fn GetClassIcoCur(hwnd: HWND, index: GET_CLASS_LONG_INDEX) -> HICON;
550
551 #[doc = ""]
552 NtUserCallHwndParam pub fn ClearWindowState(hwnd: HWND, state: u32) -> BOOL;
553
554 #[doc = ""]
555 NtUserCallHwndParam pub fn KillSystemTimer(hwnd: HWND, timer_id: usize) -> BOOL;
556
557 #[doc = ""]
558 NtUserCallHwndParam pub fn NotifyOverlayWindow(hwnd: HWND, param: BOOL) -> BOOL;
559
560 #[doc = "May only be called by the immersive broker, otherwise returns FALSE with GetLastError() == ERROR_ACCESS_DENIED."]
561 NtUserCallHwndParam pub fn RegisterKeyboardCorrectionCallout(hwnd: HWND, param: u32) -> BOOL;
562
563 #[doc = ""]
564 NtUserCallHwndParam pub fn SetDialogPointer(hwnd: HWND, param: u32) -> BOOL;
565
566 #[doc = ""]
567 NtUserCallHwndParam pub fn SetVisible(hwnd: HWND, param: u32) -> BOOL;
568
569 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowcontexthelpid>"]
570 NtUserCallHwndParam pub fn SetWindowContextHelpId(hwnd: HWND, help_context_identifier: u32) -> BOOL;
571
572 #[doc = ""]
573 NtUserCallHwndParam pub fn SetWindowState(hwnd: HWND, state: u32) -> BOOL;
574
575 #[doc = ""]
576 NtUserCallHwndParam pub fn RegisterWindowArrangementCallout(hwnd: HWND, param: u32) -> BOOL;
577
578 #[doc = "May only be called by the immersive broker, otherwise returns 0 with GetLastError() == ERROR_ACCESS_DENIED."]
579 NtUserCallHwndParam pub fn EnableModernAppWindowKeyboardIntercept(hwnd: HWND, param: u32) -> BOOL;
580
581 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-arrangeiconicwindows>"]
582 NtUserCallHwndLock pub fn ArrangeIconicWindows(hwnd: HWND) -> u32;
583
584 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawmenubar>"]
585 NtUserCallHwndLock pub fn DrawMenuBar(hwnd: HWND) -> BOOL;
586
587 #[doc = ""]
588 NtUserCallHwndLock pub fn CheckImeShowStatusInThread(hwnd: HWND) -> BOOL;
589
590 #[doc = ""]
591 NtUserCallHwndLock pub fn GetSysMenuHandle(hwnd: HWND) -> HMENU;
592
593 #[doc = ""]
594 NtUserCallHwndLock pub fn GetSysMenuOffset(hwnd: HWND) -> usize;
595
596 #[doc = "Equivalent to `SetWindowPos(hwnd, HWND::default(), 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)`"]
597 NtUserCallHwndLock pub fn RedrawFrame(hwnd: HWND) -> BOOL;
598
599 #[doc = "Redraws and calls WH_SYSMSGFILTER hooks if a tray window"]
600 NtUserCallHwndLock pub fn RedrawFrameAndHook(hwnd: HWND) -> BOOL;
601
602 #[doc = ""]
603 NtUserCallHwndLock pub fn SetDialogSystemMenu(hwnd: HWND) -> BOOL;
604
605 #[doc = ""]
606 NtUserCallHwndLock pub fn StubSetForegroundWindow(hwnd: HWND) -> BOOL;
607
608 #[doc = ""]
609 NtUserCallHwndLock pub fn SetSysMenu(hwnd: HWND) -> BOOL;
610
611 #[doc = ""]
612 NtUserCallHwndLock pub fn UpdateClientRect(hwnd: HWND) -> BOOL;
613
614 #[doc = ""]
615 NtUserCallHwndLock pub fn UpdateWindow(hwnd: HWND) -> BOOL;
616
617 #[doc = "Needs IAM access."]
618 NtUserCallHwndLock pub fn SetActiveImmersiveWindow(hwnd: HWND) -> BOOL;
619
620 #[doc = ""]
621 NtUserCallHwndLock pub fn SetCancelRotationDelayHintWindow(hwnd: HWND) -> BOOL;
622
623 #[doc = "Needs IAM access."]
624 NtUserCallHwndLock pub fn GetWindowTrackInfoAsync(hwnd: HWND) -> BOOL;
625
626 #[doc = ""]
627 NtUserCallHwndParamLock pub fn BroadcastImeShowStatusChange(hwnd: HWND, status: BOOL) -> BOOL;
628
629 #[doc = ""]
630 NtUserCallHwndParamLock pub fn SetModernAppWindow(hwnd: HWND, modern: HWND) -> BOOL;
631
632 #[doc = ""]
633 NtUserCallHwndParamLock pub fn RedrawTitle(hwnd: HWND, param: u32) -> BOOL;
634
635 #[doc = ""]
636 NtUserCallHwndParamLock pub fn ShowOwnedPopups(hwnd: HWND, show: BOOL) -> BOOL;
637
638 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-switchtothiswindow>"]
639 NtUserCallHwndParamLock pub fn SwitchToThisWindow(hwnd: HWND, unknown: BOOL) -> ();
640
641 #[doc = ""]
642 NtUserCallHwndParamLock pub fn UpdateWindows(first_hwnd: HWND, region: HRGN) -> BOOL;
643
644 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-validatergn>"]
645 NtUserCallHwndParamLock pub fn ValidateRgn(hwnd: HWND, hrgn: HRGN) -> BOOL;
646
647 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow>"]
648 NtUserCallHwndParamLock pub fn MonitorFromWindow(hwnd: HWND, dwFlags: u32) -> HMONITOR;
649
650 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablewindow>"]
651 NtUserCallHwndParamLockSafe pub fn EnableWindow(hwnd: HWND, fEnable: BOOL) -> BOOL;
652
653 #[doc = ""]
654 NtUserCallTwoParam pub fn ChangeWindowMessageFilter(message: u32, dwFlag: u32) -> BOOL;
655
656 #[doc = "1 = regular, 2 = logical pos from dpi awareness context"]
657 NtUserCallTwoParam pub fn GetCursorPos(point: *mut POINT, which: u32) -> BOOL;
658
659 #[doc = ""]
660 NtUserCallTwoParam pub fn GetHDevName(hdev: HDEV, buffer: *mut [u8; 64]) -> BOOL;
661
662 #[doc = ""]
663 NtUserCallTwoParam pub fn InitAnsiOem(param1: *mut c_void, param2: *mut c_void) -> BOOL;
664
665 #[doc = ""]
666 NtUserCallTwoParam pub fn NlsKbdSendIMENotification(param1: u32, param2: u32) -> ();
667
668 #[doc = "May only be called by DWM, returns FALSE with GetLastError() == ERROR_ACCESS_DENIED otherwise."]
669 NtUserCallTwoParam pub fn RegisterGhostWindow(hwnd: HWND, ghost: HWND) -> BOOL;
670
671 #[doc = ""]
672 NtUserCallTwoParam pub fn RegisterLogonProcess(process_id: u32, param2: usize) -> BOOL;
673
674 #[doc = ""]
675 NtUserCallTwoParam pub fn RegisterSiblingFrostWindow(hwnd: HWND, frost: HWND) -> BOOL;
676
677 #[doc = ""]
678 NtUserCallTwoParam pub fn RegisterUserHungAppHandlers(unknown: usize, event: HANDLE) -> BOOL;
679
680 #[doc = "May only be called by CSRSS, returns STATUS_ACCESS_DENIED otherwise."]
681 NtUserCallTwoParam pub fn RemoteShadowCleanup(buffer: *const c_void, size: usize) -> NTSTATUS;
682
683 #[doc = "May only be called by CSRSS, returns STATUS_ACCESS_DENIED otherwise."]
684 NtUserCallTwoParam pub fn RemoteShadowStart(buffer: *const c_void, size: usize) -> NTSTATUS;
685
686 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setcaretpos>"]
687 NtUserCallTwoParam pub fn SetCaretPos(x: i32, y: i32) -> BOOL;
688
689 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setcursorpos>"]
690 NtUserCallTwoParam pub fn SetCursorPos(x: i32, y: i32) -> BOOL;
691
692 #[doc = "<https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setphysicalcursorpos>"]
693 NtUserCallTwoParam pub fn SetPhysicalCursorPos(x: i32, y: i32) -> BOOL;
694
695 #[doc = ""]
696 NtUserCallTwoParam pub fn SetThreadQueueMergeSetting(thread_id: u32, setting: BOOL) -> BOOL;
697
698 #[doc = ""]
699 NtUserCallTwoParam pub fn UnhookWindowsHook(hook: i32, param: i32) -> BOOL;
700
701 #[doc = ""]
702 NtUserCallTwoParam pub fn WOWCleanup(param1: usize, param2: u32) -> BOOL;
703
704 #[doc = ""]
705 NtUserCallTwoParam pub fn EnableShellWindowManagementBehavior(mask: u32, behavior: u32) -> BOOL;
706
707 #[doc = ""]
708 NtUserCallTwoParam pub fn CitSetInfo(which: u32, info: *mut c_void) -> NTSTATUS;
709
710 #[doc = ""]
711 NtUserCallTwoParam pub fn ScaleSystemMetricForDPIWithoutCache(metric: SYSTEM_METRICS_INDEX, dpi: u32) -> i32;
712}
713
714macro_rules! nt_user_call_syscall_fn {
715 (($paramname:ident: $paramtype:ty) -> $rettype:ty) => {
716 unsafe extern "system" fn syscall<const SYSCALL_NR: usize>(
717 $paramname: $paramtype
718 ) -> $rettype {
719 use std::arch::asm;
720 let result;
721
722 asm!(
723 "mov eax, {syscall_nr}",
724 "syscall",
725 in("r10") $paramname,
726 lateout("rax") result,
727 syscall_nr = const(SYSCALL_NR),
728 options(nostack),
729 );
730
731 result
732 }
733 };
734
735 (($paramname:ident: $paramtype:ty, $param2name:ident: $param2type:ty) -> $rettype:ty) => {
736 unsafe extern "system" fn syscall<const SYSCALL_NR: usize>(
737 $paramname: $paramtype,
738 $param2name: $param2type,
739 ) -> $rettype {
740 use std::arch::asm;
741 let result;
742
743 asm!(
744 "mov eax, {syscall_nr}",
745 "syscall",
746 in("r10") $paramname,
747 in("rdx") $param2name,
748 lateout("rax") result,
749 syscall_nr = const(SYSCALL_NR),
750 options(nostack),
751 );
752
753 result
754 }
755 };
756
757 (($paramname:ident: $paramtype:ty, $param2name:ident: $param2type:ty, $param3name:ident: $param3type:ty) -> $rettype:ty) => {
758 unsafe extern "system" fn syscall<const SYSCALL_NR: usize>(
759 $paramname: $paramtype,
760 $param2name: $param2type,
761 $param3name: $param3type,
762 ) -> $rettype {
763 use std::arch::asm;
764 let result;
765
766 asm!(
767 "mov eax, {syscall_nr}",
768 "syscall",
769 in("r10") $paramname,
770 in("rdx") $param2name,
771 in("r8") $param3name,
772 lateout("rax") result,
773 syscall_nr = const(SYSCALL_NR),
774 options(nostack),
775 );
776
777 result
778 }
779 };
780 }
781
782macro_rules! nt_user_call_alternate {
783 ($name:ident => => $rettype:ty => $($paramname:ident: $paramtype:ty),*) => {{
784 _ = FUNCTION.compare_exchange(
785 std::ptr::null_mut(),
786 UserCallError::CallNotFound as _,
787 Ordering::SeqCst,
788 Ordering::Relaxed,
789 );
790 return Err(UserCallError::CallNotFound);
791 }};
792
793 ($name:ident => $($(#[$cfg:meta])? $os:ident = $syscall_nr:literal),+ => $rettype:ty => $($paramname:ident: $paramtype:ty),*) => {{
794 println!(concat!("Function ", stringify!($name), " direct syscall"));
795
796 nt_user_call_syscall_fn!(($($paramname: $paramtype),+) -> $rettype);
797
798 let syscall: unsafe extern "system" fn($($paramtype),*) -> $rettype = match get_os_version() {
799 $(
800 $(#[$cfg])?
801 Ok(OsVersion::$os) => syscall::<$syscall_nr>,
802 )+
803 Ok(_) => {
804 _ = FUNCTION.compare_exchange(
805 std::ptr::null_mut(),
806 UserCallError::OsNotSupported as usize as _,
807 Ordering::SeqCst,
808 Ordering::Relaxed,
809 );
810
811 return Err(UserCallError::OsNotSupported);
812 },
813 Err(err) => {
814 _ = FUNCTION.compare_exchange(
815 std::ptr::null_mut(),
816 err as usize as _,
817 Ordering::SeqCst,
818 Ordering::Relaxed,
819 );
820
821 return Err(err);
822 },
823 };
824
825 syscall as _
826 }};
827 }
828
829macro_rules! nt_user_call_syscall {
830 (
831 $vis:vis fn $name:ident ($($paramname:ident: $paramtype:ty),*) -> $rettype:ty $(=> $($(#[$cfg:meta])? $os:ident = $syscall_nr:literal),+)?
832 ) => {
833 #[expect(non_snake_case, clippy::missing_safety_doc)]
834 $vis unsafe fn $name($($paramname: $paramtype),*) -> Result<$rettype, UserCallError> {
835 type Function = unsafe extern "system" fn($($paramtype),*) -> $rettype;
836
837 static FUNCTION: AtomicPtr<c_void> = AtomicPtr::new(std::ptr::null_mut());
838
839 let mut ptr = FUNCTION.load(Ordering::Relaxed);
840
841 if ptr.is_null() {
842 let library = match unsafe { GetModuleHandleW(w!("win32u")).or_else(|_| GetModuleHandleW(w!("user32"))) } {
844 Ok(library) => library,
845 Err(_) => {
846 _ = FUNCTION.compare_exchange(std::ptr::null_mut(), 0x1 as _, Ordering::AcqRel, Ordering::Acquire);
847 return Err(UserCallError::LibraryNotFound);
848 }
849 };
850
851 ptr = match unsafe { GetProcAddress(library, PCSTR(concat!(stringify!($name), "\u{0}").as_ptr())) } {
853 Some(f) => f as _,
855 None => {
856 nt_user_call_alternate!($name => $($($(#[$cfg])? $os = $syscall_nr),+)? => $rettype => $($paramname: $paramtype),*)
857 }
858 };
859
860 ptr = FUNCTION.compare_exchange(std::ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire).map_or_else(|p| p, |_| ptr);
861 }
862
863 if (ptr as usize) < u16::MAX as usize {
864 println!("{:?}", ptr as usize);
865 return Err(UserCallError::try_from(ptr as usize).unwrap());
866 }
867
868 let function: Function = unsafe {
870 std::mem::transmute(ptr)
871 };
872
873 Ok(unsafe { function($($paramname),*) })
875 }
876 };
877 }
878
879pub mod user_call {
883 use super::{
884 c_void, get_os_version, w, AtomicPtr, GetModuleHandleW, GetProcAddress, Ordering,
885 OsVersion, UserCallError, PCSTR,
886 };
887
888 nt_user_call_syscall!(pub fn NtUserCallNoParam(call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4101, Win8 = 4102, Win81 = 4103);
889 nt_user_call_syscall!(pub fn NtUserCallOneParam(param: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4098, Win8 = 4099, Win81 = 4100);
890 nt_user_call_syscall!(pub fn NtUserCallHwnd(hwnd: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4364, Win8 = 4364, Win81 = 4365);
891 nt_user_call_syscall!(pub fn NtUserCallHwndSafe(hwnd: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4364, Win8 = 4364, Win81 = 4365);
892 nt_user_call_syscall!(pub fn NtUserCallHwndOpt(hwnd: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4743, Win8 = 4836, Win81 = 4869);
893 nt_user_call_syscall!(pub fn NtUserCallHwndParam(hwnd: usize, param: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4254, Win8 = 4254, Win81 = 4255);
894 nt_user_call_syscall!(pub fn NtUserCallHwndLock(hwnd: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4129, Win8 = 4130, Win81 = 4131);
895 nt_user_call_syscall!(pub fn NtUserCallHwndParamLock(hwnd: usize, param: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4135, Win8 = 4136, Win81 = 4137);
896 nt_user_call_syscall!(pub fn NtUserCallHwndParamLockSafe(hwnd: usize, param: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4135, Win8 = 4136, Win81 = 4137);
897 nt_user_call_syscall!(pub fn NtUserCallTwoParam(param1: usize, param2: usize, call: u32) -> usize => #[cfg(any(target_vendor = "win7", feature = "all_os_versions"))] Win7 = 4138, Win8 = 4138, Win81 = 4139);
898}