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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
use crate::*;
use *;
/// \[[learn.microsoft.com](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagea)\]
/// PostMessageA
///
/// Posts a message in the message queue associated with the thread that created the specified [HWnd], and returns without waiting for the thread to process the message.
///
/// * [HWnd::BROADCAST] will post the message to all top-level windows in the system,
/// including disabled or invisible unowned windows, overlapped windows, and pop-up windows.
/// The message is not posted to child windows.
/// * [HWnd::NULL] will behave like [post_thread_message_a], posting to the current thread.
///
/// ### Safety
/// * `wparam` and `lparam` may need to be valid pointers, and remain valid until the message is processed, depending on what `msg` is and the wndproc of `hwnd`.
/// * `hwnd` should perhaps be a non-unicode window?
///
/// ### Errors
/// * [ERROR::INVALID_WINDOW_HANDLE] If `hwnd` is invalid
/// * [ERROR::ACCESS_DENIED] When a message is blocked by [UIPI](https://en.wikipedia.org/wiki/User_Interface_Privilege_Isolation)
/// * [ERROR::NOT_ENOUGH_QUOTA] If the message queue is full. (A message queue can contain at most 10,000 messages.)
/// * [ERROR::MESSAGE_SYNC_ONLY] If `msg` is a system message to be handled syncronously (common for messages with pointers.)<br>
/// This occurs even if `hwnd` belongs to the current thread.
///
/// ### Example
/// ```rust
/// # use hwnd::*;
/// # use winresult::*;
/// # use std::ptr::*;
/// # let hwnd = unsafe { create_window_a(abistr::cstr!("Message"), (), 0, 0, 0, 0, 0, HWnd::MESSAGE, null_mut(), None, null_mut()).unwrap() };
/// unsafe { post_message_a(hwnd, WM::NULL, 0, 0) }.unwrap();
/// assert_eq!(ERROR::INVALID_WINDOW_HANDLE, unsafe { post_message_a(!42usize as HWND, WM::NULL, 0, 0) }.unwrap_err());
/// assert_eq!(ERROR::MESSAGE_SYNC_ONLY, unsafe { post_message_a(hwnd, WM::SETTEXT, 0, 0) }.unwrap_err());
/// #
/// # let r = std::thread::spawn(||{
/// # let hwnd = unsafe { create_window_a(abistr::cstr!("Message"), (), 0, 0, 0, 0, 0, HWnd::MESSAGE, null_mut(), None, null_mut()).unwrap() };
/// # for _ in 0 .. 11_000 { drop(unsafe { post_message_a(hwnd, WM::NULL, 0, 0) }) }
/// # unsafe { post_message_a(hwnd, WM::NULL, 0, 0) }
/// # }).join().unwrap();
/// # assert_eq!(ERROR::NOT_ENOUGH_QUOTA, r.unwrap_err());
/// ```
pub unsafe
/// \[[learn.microsoft.com](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagew)\]
/// PostMessageW
///
/// Posts a message in the message queue associated with the thread that created the specified [HWnd], and returns without waiting for the thread to process the message.
///
/// * [HWnd::BROADCAST] will post the message to all top-level windows in the system,
/// including disabled or invisible unowned windows, overlapped windows, and pop-up windows.
/// The message is not posted to child windows.
/// * [HWnd::NULL] will behave like [post_thread_message_w], posting to the current thread.
///
/// ### Safety
/// * `wparam` and `lparam` may need to be valid pointers, and remain valid until the message is processed, depending on what `msg` is and the wndproc of `hwnd`.
/// * `hwnd` should perhaps be a unicode window?
///
/// ### Errors
/// * [ERROR::INVALID_WINDOW_HANDLE] If `hwnd` is invalid
/// * [ERROR::ACCESS_DENIED] When a message is blocked by [UIPI](https://en.wikipedia.org/wiki/User_Interface_Privilege_Isolation)
/// * [ERROR::NOT_ENOUGH_QUOTA] If the message queue is full. (A message queue can contain at most 10,000 messages.)
/// * [ERROR::MESSAGE_SYNC_ONLY] If `msg` is a system message that can only be dispatched syncronously (typically wparam/lparam are expected to be pointers)
///
/// ### Example
/// ```rust
/// # use hwnd::*;
/// # use winresult::*;
/// # use std::ptr::*;
/// # let hwnd = unsafe { create_window_w(abistr::cstr16!("Message"), (), 0, 0, 0, 0, 0, HWnd::MESSAGE, null_mut(), None, null_mut()).unwrap() };
/// unsafe { post_message_w(hwnd, WM::NULL, 0, 0) }.unwrap();
/// assert_eq!(ERROR::INVALID_WINDOW_HANDLE, unsafe { post_message_w(!42usize as HWND, WM::NULL, 0, 0) }.unwrap_err());
/// assert_eq!(ERROR::MESSAGE_SYNC_ONLY, unsafe { post_message_w(hwnd, WM::SETTEXT, 0, 0) }.unwrap_err());
/// #
/// # let r = std::thread::spawn(||{
/// # let hwnd = unsafe { create_window_w(abistr::cstr16!("Message"), (), 0, 0, 0, 0, 0, HWnd::MESSAGE, null_mut(), None, null_mut()).unwrap() };
/// # for _ in 0 .. 11_000 { drop(unsafe { post_message_w(hwnd, WM::NULL, 0, 0) }) }
/// # unsafe { post_message_w(hwnd, WM::NULL, 0, 0) }
/// # }).join().unwrap();
/// # assert_eq!(ERROR::NOT_ENOUGH_QUOTA, r.unwrap_err());
/// ```
pub unsafe
/// \[[learn.microsoft.com](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postthreadmessagea)\]
/// PostThreadMessageA
///
/// Posts a message to the message queue of the specified thread. It returns without waiting for the thread to process the message.
///
/// ### Safety
/// * `wparam` and `lparam` may need to be valid pointers, and remain valid until the message is processed, depending on what `msg` is and the wndprocs of `thread`.
///
/// ### Errors
/// * [ERROR::INVALID_THREAD_ID] If `thread` is invalid
/// * [ERROR::ACCESS_DENIED] When a message is blocked by [UIPI](https://en.wikipedia.org/wiki/User_Interface_Privilege_Isolation)
/// * [ERROR::NOT_ENOUGH_QUOTA] If the message queue is full. (A message queue can contain at most 10,000 messages.)
/// * [ERROR::MESSAGE_SYNC_ONLY] If `msg` is a system message to be handled syncronously (common for messages with pointers.)<br>
///
/// ### Example
/// ```rust
/// # use hwnd::*;
/// # use winresult::*;
/// # use std::ptr::*;
/// unsafe { post_thread_message_a(get_current_thread_id(), WM::NULL, 0, 0) }.unwrap();
/// assert_eq!(ERROR::INVALID_THREAD_ID, unsafe { post_thread_message_a(0, WM::NULL, 0, 0) }.unwrap_err());
/// assert_eq!(ERROR::MESSAGE_SYNC_ONLY, unsafe { post_thread_message_a(get_current_thread_id(), WM::SETTEXT, 0, 0) }.unwrap_err());
/// #
/// # let r = std::thread::spawn(||{
/// # let thread = get_current_thread_id();
/// # for _ in 0 .. 11_000 { drop(unsafe { post_thread_message_a(thread, WM::NULL, 0, 0) }) }
/// # unsafe { post_thread_message_a(thread, WM::NULL, 0, 0) }
/// # }).join().unwrap();
/// # assert_eq!(ERROR::NOT_ENOUGH_QUOTA, r.unwrap_err());
/// ```
pub unsafe
/// \[[learn.microsoft.com](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postthreadmessagew)\]
/// PostThreadMessageW
///
/// Posts a message to the message queue of the specified thread. It returns without waiting for the thread to process the message.
///
/// ### Safety
/// * `wparam` and `lparam` may need to be valid pointers, and remain valid until the message is processed, depending on what `msg` is and the wndprocs of `thread`.
///
/// ### Errors
/// * [ERROR::INVALID_THREAD_ID] If `thread` is invalid
/// * [ERROR::ACCESS_DENIED] When a message is blocked by [UIPI](https://en.wikipedia.org/wiki/User_Interface_Privilege_Isolation)
/// * [ERROR::NOT_ENOUGH_QUOTA] If the message queue is full. (A message queue can contain at most 10,000 messages.)
/// * [ERROR::MESSAGE_SYNC_ONLY] If `msg` is a system message to be handled syncronously (common for messages with pointers.)<br>
///
/// ### Example
/// ```rust
/// # use hwnd::*;
/// # use winresult::*;
/// # use std::ptr::*;
/// unsafe { post_thread_message_w(get_current_thread_id(), WM::NULL, 0, 0) }.unwrap();
/// assert_eq!(ERROR::INVALID_THREAD_ID, unsafe { post_thread_message_w(0, WM::NULL, 0, 0) }.unwrap_err());
/// assert_eq!(ERROR::MESSAGE_SYNC_ONLY, unsafe { post_thread_message_w(get_current_thread_id(), WM::SETTEXT, 0, 0) }.unwrap_err());
/// #
/// # let r = std::thread::spawn(||{
/// # let thread = get_current_thread_id();
/// # for _ in 0 .. 11_000 { drop(unsafe { post_thread_message_w(thread, WM::NULL, 0, 0) }) }
/// # unsafe { post_thread_message_w(thread, WM::NULL, 0, 0) }
/// # }).join().unwrap();
/// # assert_eq!(ERROR::NOT_ENOUGH_QUOTA, r.unwrap_err());
/// ```
pub unsafe
// XXX: post_app_message_a appears to be a macro alias for post_thread_message_a? also undocumented as heck, so let's not expose it
// XXX: post_app_message_w appears to be a macro alias for post_thread_message_w? also undocumented as heck, so let's not expose it
/// \[[learn.microsoft.com](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postquitmessage)\]
/// PostQuitMessage
///
/// Posts a [WM::QUIT] message (with `wparam` = `exit_code`) to the thread's message queue and returns immediately;
/// the function simply indicates to the system that the thread is requesting to quit at some time in the future.
///
/// When the thread retrieves the [WM::QUIT] message from its message queue, it should exit its message loop and return control to the system.
/// The exit value returned to the system must be the `wparam` parameter of the [WM::QUIT] message.
///
/// Typically used in response to [WM::DESTROY]ing the last or "main" window.<br>
/// Used by default in response to [WM::DESTROY] by [def_window_proc](def_window_proc_w).
///
/// ### Example
/// ```rust
/// # use hwnd::*;
/// post_quit_message(0);
/// ```