1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE:     Test for NtUserGetThreadState
5  * COPYRIGHT:   Copyright 2021-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6  */
7 
8 #include "../win32nt.h"
9 #include <pseh/pseh2.h>
10 
11 #define MAX_COUNT 8
12 #define IGNORED 0xDEADFACE
13 #define RAISED 0xBADBEEF
14 #define DO_CHECK(i, value) CheckThreadState(__LINE__, (i), (DWORD_PTR)(value))
15 
16 #undef DO_PRINT
17 
18 #ifdef DO_PRINT
19 static VOID PrintThreadState(INT lineno, HWND hWnd)
20 {
21     INT i;
22     HIMC hIMC = ImmGetContext(hWnd);
23     HWND hImeWnd = ImmGetDefaultIMEWnd(hWnd);
24 
25     trace("---\n");
26     trace("__LINE__: %d\n", lineno);
27     trace("hWnd: %p\n", (LPVOID)hWnd);
28     trace("GetFocus(): %p\n", (LPVOID)GetFocus());
29     trace("GetCapture(): %p\n", (LPVOID)GetCapture());
30     trace("GetActiveWindow(): %p\n", (LPVOID)GetActiveWindow());
31     trace("ImmGetContext(): %p\n", (LPVOID)hIMC);
32     trace("ImmGetDefaultIMEWnd(): %p\n", (LPVOID)hImeWnd);
33 
34     for (i = 0; i < MAX_COUNT; ++i)
35     {
36         _SEH2_TRY
37         {
38             trace("ThreadState[%d]: %p\n", i, (LPVOID)NtUserGetThreadState(i));
39         }
40         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
41         {
42             trace("ThreadState[%d]: exception\n", i);
43         }
44         _SEH2_END;
45     }
46 
47     ImmReleaseContext(hWnd, hIMC);
48 }
49 #endif
50 
51 static VOID CheckThreadState(INT lineno, INT i, DWORD_PTR dwState)
52 {
53     DWORD_PTR dwValue;
54 
55     _SEH2_TRY
56     {
57         dwValue = (DWORD_PTR)NtUserGetThreadState(i);
58     }
59     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
60     {
61         dwValue = RAISED;
62     }
63     _SEH2_END;
64 
65     if (dwState != IGNORED)
66     {
67         ok(dwValue == dwState, "Line %d: Mismatch 0x%lX vs. 0x%lX\n",
68            lineno, (DWORD)dwValue, (DWORD)dwState);
69     }
70 }
71 
72 static VOID DoTest_EDIT(VOID)
73 {
74     HWND hWnd, hImeWnd;
75     HIMC hIMC;
76     HCURSOR hCursor;
77     LPARAM ExtraInfo;
78     LONG MsgTime;
79 
80     hWnd = CreateWindowA("EDIT", "Test", ES_LEFT | ES_MULTILINE | WS_VISIBLE,
81                          0, 0, 50, 30,
82                          NULL, NULL, GetModuleHandleW(NULL), NULL);
83     hImeWnd = ImmGetDefaultIMEWnd(hWnd);
84     ok_int(hImeWnd != NULL, TRUE);
85 
86     hIMC = ImmGetContext(hWnd);
87     ok_int(hIMC != NULL, TRUE);
88     ok_int(hIMC == (HIMC)NtUserGetThreadState(4), TRUE);
89     hCursor = GetCursor();
90     ExtraInfo = GetMessageExtraInfo();
91     MsgTime = GetMessageTime();
92 
93 #ifdef DO_PRINT
94     PrintThreadState(__LINE__, hWnd);
95 #endif
96     DO_CHECK(0, hWnd);
97     DO_CHECK(1, hWnd);
98     DO_CHECK(2, 0);
99     DO_CHECK(3, hImeWnd);
100     DO_CHECK(4, hIMC);
101     DO_CHECK(6, hCursor);
102     DO_CHECK(8, ExtraInfo);
103     DO_CHECK(10, MsgTime);
104 
105     SetCapture(hWnd);
106     hCursor = GetCursor();
107     ExtraInfo = GetMessageExtraInfo();
108     MsgTime = GetMessageTime();
109 
110 #ifdef DO_PRINT
111     PrintThreadState(__LINE__, hWnd);
112 #endif
113     DO_CHECK(0, hWnd);
114     DO_CHECK(1, hWnd);
115     DO_CHECK(2, hWnd);
116     DO_CHECK(3, hImeWnd);
117     DO_CHECK(4, hIMC);
118     DO_CHECK(6, hCursor);
119     DO_CHECK(8, ExtraInfo);
120     DO_CHECK(10, MsgTime);
121 
122     ReleaseCapture();
123     hCursor = GetCursor();
124     ExtraInfo = GetMessageExtraInfo();
125     MsgTime = GetMessageTime();
126 
127 #ifdef DO_PRINT
128     PrintThreadState(__LINE__, hWnd);
129 #endif
130     DO_CHECK(0, hWnd);
131     DO_CHECK(1, hWnd);
132     DO_CHECK(2, 0);
133     DO_CHECK(3, hImeWnd);
134     DO_CHECK(4, hIMC);
135     DO_CHECK(6, hCursor);
136     DO_CHECK(8, ExtraInfo);
137     DO_CHECK(10, MsgTime);
138 
139     SetFocus(hWnd);
140     hCursor = GetCursor();
141     ExtraInfo = GetMessageExtraInfo();
142     MsgTime = GetMessageTime();
143 
144 #ifdef DO_PRINT
145     PrintThreadState(__LINE__, hWnd);
146 #endif
147     DO_CHECK(0, hWnd);
148     DO_CHECK(1, hWnd);
149     DO_CHECK(2, 0);
150     DO_CHECK(3, hImeWnd);
151     DO_CHECK(4, hIMC);
152     DO_CHECK(6, hCursor);
153     DO_CHECK(8, ExtraInfo);
154     DO_CHECK(10, MsgTime);
155 
156     SetActiveWindow(hWnd);
157     hCursor = GetCursor();
158     ExtraInfo = GetMessageExtraInfo();
159     MsgTime = GetMessageTime();
160 
161 #ifdef DO_PRINT
162     PrintThreadState(__LINE__, hWnd);
163 #endif
164     DO_CHECK(0, hWnd);
165     DO_CHECK(1, hWnd);
166     DO_CHECK(2, 0);
167     DO_CHECK(3, hImeWnd);
168     DO_CHECK(4, hIMC);
169     DO_CHECK(6, hCursor);
170     DO_CHECK(8, ExtraInfo);
171     DO_CHECK(10, MsgTime);
172 
173     SetActiveWindow(NULL);
174     hCursor = GetCursor();
175     ExtraInfo = GetMessageExtraInfo();
176     MsgTime = GetMessageTime();
177 
178 #ifdef DO_PRINT
179     PrintThreadState(__LINE__, hWnd);
180 #endif
181     DO_CHECK(0, IGNORED);
182     DO_CHECK(1, IGNORED);
183     DO_CHECK(2, 0);
184     DO_CHECK(3, hImeWnd);
185     DO_CHECK(4, hIMC);
186     DO_CHECK(6, hCursor);
187     DO_CHECK(8, ExtraInfo);
188     DO_CHECK(10, MsgTime);
189 
190     ImmReleaseContext(hWnd, hIMC);
191     DestroyWindow(hWnd);
192 }
193 
194 static VOID DoTest_BUTTON(VOID)
195 {
196     HWND hWnd, hImeWnd;
197     HIMC hIMC;
198     HCURSOR hCursor;
199     LPARAM ExtraInfo;
200     LONG MsgTime;
201 
202     hWnd = CreateWindowA("BUTTON", "Test", BS_PUSHBUTTON | WS_VISIBLE,
203                          0, 0, 50, 30,
204                          NULL, NULL, GetModuleHandleW(NULL), NULL);
205     hImeWnd = ImmGetDefaultIMEWnd(hWnd);
206     ok_int(hImeWnd != NULL, TRUE);
207 
208     hIMC = ImmGetContext(hWnd);
209     ok_int(hIMC != NULL, FALSE);
210 
211     hIMC = (HIMC)NtUserGetThreadState(4);
212     ok_int(hIMC != NULL, TRUE);
213     hCursor = GetCursor();
214     ExtraInfo = GetMessageExtraInfo();
215     MsgTime = GetMessageTime();
216 
217 #ifdef DO_PRINT
218     PrintThreadState(__LINE__, hWnd);
219 #endif
220     DO_CHECK(0, hWnd);
221     DO_CHECK(1, hWnd);
222     DO_CHECK(2, 0);
223     DO_CHECK(3, hImeWnd);
224     DO_CHECK(4, hIMC);
225     DO_CHECK(6, hCursor);
226     DO_CHECK(8, ExtraInfo);
227     DO_CHECK(10, MsgTime);
228 
229     SetCapture(hWnd);
230     hCursor = GetCursor();
231     ExtraInfo = GetMessageExtraInfo();
232     MsgTime = GetMessageTime();
233 
234 #ifdef DO_PRINT
235     PrintThreadState(__LINE__, hWnd);
236 #endif
237     DO_CHECK(0, hWnd);
238     DO_CHECK(1, hWnd);
239     DO_CHECK(2, hWnd);
240     DO_CHECK(3, hImeWnd);
241     DO_CHECK(4, hIMC);
242     DO_CHECK(6, hCursor);
243     DO_CHECK(8, ExtraInfo);
244     DO_CHECK(10, MsgTime);
245 
246     ReleaseCapture();
247     hCursor = GetCursor();
248     ExtraInfo = GetMessageExtraInfo();
249     MsgTime = GetMessageTime();
250 
251 #ifdef DO_PRINT
252     PrintThreadState(__LINE__, hWnd);
253 #endif
254     DO_CHECK(0, hWnd);
255     DO_CHECK(1, hWnd);
256     DO_CHECK(2, 0);
257     DO_CHECK(3, hImeWnd);
258     DO_CHECK(4, hIMC);
259     DO_CHECK(6, hCursor);
260     DO_CHECK(8, ExtraInfo);
261     DO_CHECK(10, MsgTime);
262 
263     SetFocus(hWnd);
264     hCursor = GetCursor();
265     ExtraInfo = GetMessageExtraInfo();
266     MsgTime = GetMessageTime();
267 
268 #ifdef DO_PRINT
269     PrintThreadState(__LINE__, hWnd);
270 #endif
271     DO_CHECK(0, hWnd);
272     DO_CHECK(1, hWnd);
273     DO_CHECK(2, 0);
274     DO_CHECK(3, hImeWnd);
275     DO_CHECK(4, hIMC);
276     DO_CHECK(6, hCursor);
277     DO_CHECK(8, ExtraInfo);
278     DO_CHECK(10, MsgTime);
279 
280     SetActiveWindow(hWnd);
281     hCursor = GetCursor();
282     ExtraInfo = GetMessageExtraInfo();
283     MsgTime = GetMessageTime();
284 
285 #ifdef DO_PRINT
286     PrintThreadState(__LINE__, hWnd);
287 #endif
288     DO_CHECK(0, hWnd);
289     DO_CHECK(1, hWnd);
290     DO_CHECK(2, 0);
291     DO_CHECK(3, hImeWnd);
292     DO_CHECK(4, hIMC);
293     DO_CHECK(6, hCursor);
294     DO_CHECK(8, ExtraInfo);
295     DO_CHECK(10, MsgTime);
296 
297     SetActiveWindow(NULL);
298     hCursor = GetCursor();
299     ExtraInfo = GetMessageExtraInfo();
300     MsgTime = GetMessageTime();
301 
302 #ifdef DO_PRINT
303     PrintThreadState(__LINE__, hWnd);
304 #endif
305     DO_CHECK(0, IGNORED);
306     DO_CHECK(1, IGNORED);
307     DO_CHECK(2, 0);
308     DO_CHECK(3, hImeWnd);
309     DO_CHECK(4, hIMC);
310     DO_CHECK(6, hCursor);
311     DO_CHECK(8, ExtraInfo);
312     DO_CHECK(10, MsgTime);
313 
314     DestroyWindow(hWnd);
315 }
316 
317 START_TEST(NtUserGetThreadState)
318 {
319     DoTest_EDIT();
320     DoTest_BUTTON();
321 }
322