[KERNEL32_APITEST]: SetConsoleWindowInfo test:
[reactos.git] / rostests / apitests / kernel32 / SetConsoleWindowInfo.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for SetConsoleWindowInfo
5 * PROGRAMMER: Hermes Belusca-Maito
6 */
7
8 #include <apitest.h>
9 #include <wincon.h>
10
11 static VOID
12 ResizeTextConsole(
13 IN HANDLE hConOut,
14 IN OUT PCONSOLE_SCREEN_BUFFER_INFO pcsbi,
15 IN COORD Resolution,
16 IN PSMALL_RECT WindowSize OPTIONAL)
17 {
18 BOOL Success;
19 SMALL_RECT ConRect;
20
21 if (Resolution.X != pcsbi->dwSize.X || Resolution.Y != pcsbi->dwSize.Y)
22 {
23 SHORT oldWidth, oldHeight;
24
25 oldWidth = pcsbi->srWindow.Right - pcsbi->srWindow.Left + 1;
26 oldHeight = pcsbi->srWindow.Bottom - pcsbi->srWindow.Top + 1;
27
28 /*
29 * If the current console window is too large for
30 * the new screen buffer, resize it first.
31 */
32 if (oldWidth > Resolution.X || oldHeight > Resolution.Y)
33 {
34 ConRect.Left = ConRect.Top = 0;
35 ConRect.Right = ConRect.Left + min(oldWidth , Resolution.X) - 1;
36 ConRect.Bottom = ConRect.Top + min(oldHeight, Resolution.Y) - 1;
37 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
38 ok(Success, "Setting console wnd info failed with last error error %lu\n", GetLastError());
39 }
40
41 /* Now resize the screen buffer */
42 Success = SetConsoleScreenBufferSize(hConOut, Resolution);
43 ok(Success, "Setting console SB size failed with last error error %lu\n", GetLastError());
44
45 /*
46 * Setting a new screen buffer size can change other information,
47 * so update the saved console information.
48 */
49 Success = GetConsoleScreenBufferInfo(hConOut, pcsbi);
50 ok(Success, "Getting SB info\n");
51 }
52
53 if (!WindowSize)
54 {
55 /* Always resize the console window within the permitted maximum size */
56 ConRect.Left = 0;
57 ConRect.Right = ConRect.Left + min(Resolution.X, pcsbi->dwMaximumWindowSize.X) - 1;
58 ConRect.Bottom = min(pcsbi->dwCursorPosition.Y, Resolution.Y - 1);
59 ConRect.Top = ConRect.Bottom - min(Resolution.Y, pcsbi->dwMaximumWindowSize.Y) + 1;
60 }
61 else
62 {
63 /* Resize the console window according to user's wishes */
64 ConRect.Left = ConRect.Top = 0;
65 ConRect.Right = ConRect.Left + WindowSize->Right - WindowSize->Left;
66 ConRect.Bottom = ConRect.Top + WindowSize->Bottom - WindowSize->Top ;
67 }
68
69 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
70 ok(Success, "Setting console wnd info failed with last error error %lu\n", GetLastError());
71
72 /* Update console screen buffer info */
73 Success = GetConsoleScreenBufferInfo(hConOut, pcsbi);
74 ok(Success, "Getting SB info\n");
75 }
76
77 START_TEST(SetConsoleWindowInfo)
78 {
79 /*
80 * The aim of this test is to show that what MSDN says about the validity
81 * checks performed on the window size rect given to SetConsoleWindowInfo
82 * is partially wrong.
83 *
84 * Indeed, while it is claimed that:
85 * "The function fails if the specified window rectangle extends beyond
86 * the boundaries of the console screen buffer. This means that the Top
87 * and Left members of the lpConsoleWindow rectangle (or the calculated
88 * top and left coordinates, if bAbsolute is FALSE) cannot be less than
89 * zero. Similarly, the Bottom and Right members (or the calculated
90 * bottom and right coordinates) cannot be greater than (screen buffer
91 * height – 1) and (screen buffer width – 1), respectively. The function
92 * also fails if the Right member (or calculated right coordinate) is
93 * less than or equal to the Left member (or calculated left coordinate)
94 * or if the Bottom member (or calculated bottom coordinate) is less than
95 * or equal to the Top member (or calculated top coordinate)."
96 *
97 * the really performed tests are fewer, and it appears that the console
98 * subsystem knows how to take proper actions when the window size rect
99 * has e.g. negative left/top coordinates...
100 *
101 * NOTE that we all perform those tests in "absolute mode" (second parameter
102 * of SetConsoleWindowInfo being TRUE), so that the specified window size rect
103 * is in absolute coordinates (i.e. relative to the console screen buffer),
104 * and not in coordinates relative to the current window-corner coordinates.
105 */
106
107 BOOL Success;
108 DWORD dwLastError;
109 HANDLE hConOut;
110 COORD Resolution;
111 CONSOLE_SCREEN_BUFFER_INFO org_csbi, csbi, csbi2;
112 SMALL_RECT ConRect;
113
114 /* First, retrieve a handle to the real console output, even if we are redirected */
115 hConOut = CreateFileW(L"CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
116 ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
117 if (hConOut == INVALID_HANDLE_VALUE)
118 return; // We cannot run this test if we failed...
119
120 /*
121 * Retrieve the original console screen buffer info and save it
122 * for restoration at the end of the test. Use a copy after then.
123 */
124 Success = GetConsoleScreenBufferInfo(hConOut, &org_csbi);
125 ok(Success, "Getting SB info\n");
126 if (!Success)
127 goto Cleanup; // We cannot as well run this test if we failed...
128 csbi = org_csbi;
129
130 /*
131 * Set the console screen buffer to a correct size that should not
132 * completely fill the computer screen. 'csbi' is correctly updated.
133 */
134 Resolution.X = 80;
135 Resolution.Y = 25;
136 ResizeTextConsole(hConOut, &csbi, Resolution, NULL);
137
138 /* Test 1: Resize the console window to its possible maximum size (succeeds) */
139 ConRect.Left = ConRect.Top = 0;
140 ConRect.Right = ConRect.Left + min(csbi.dwSize.X, csbi.dwMaximumWindowSize.X) - 1;
141 ConRect.Bottom = ConRect.Top + min(csbi.dwSize.Y, csbi.dwMaximumWindowSize.Y) - 1;
142 SetLastError(0xdeadbeef);
143 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
144 dwLastError = GetLastError();
145 ok(Success, "Setting console wnd info\n");
146 ok(dwLastError != ERROR_INVALID_PARAMETER, "GetLastError: %lu\n", dwLastError);
147
148 /* Test 2: Set negative Left/Top members, but correct Right/Bottom ones.
149 * The Left/Top members are shifted to zero while the Right/Bottom ones
150 * are shifted too in accordance.
151 * Situation where the Right/Bottom members will be ok after the shift
152 * (succeeds, disagrees with MSDN) */
153 ConRect.Left = ConRect.Top = -5;
154 ConRect.Right = csbi.dwSize.X - 7;
155 ConRect.Bottom = csbi.dwSize.Y - 7;
156 // Expected result: ConRect.Left == ConRect.Top == 0 and
157 // ConRect.Right == csbi.dwSize.X - 2, ConRect.Bottom == csbi.dwSize.Y - 2;
158 SetLastError(0xdeadbeef);
159 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
160 dwLastError = GetLastError();
161 ok(Success, "Setting console wnd info should have succeeded!\n");
162 ok(dwLastError != ERROR_INVALID_PARAMETER, "GetLastError: %lu\n", dwLastError);
163
164 /* Check the new reported window size rect */
165 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
166 ok(Success, "Getting SB info\n");
167 if (Success)
168 {
169 ConRect.Right -= ConRect.Left;
170 ConRect.Left = 0;
171 ConRect.Bottom -= ConRect.Top;
172 ConRect.Top = 0;
173
174 ok(csbi2.srWindow.Left == ConRect.Left, "srWindow.Left = %d, expected %d\n",
175 csbi2.srWindow.Left, ConRect.Left);
176 ok(csbi2.srWindow.Top == ConRect.Top, "srWindow.Top = %d, expected %d\n",
177 csbi2.srWindow.Top, ConRect.Top);
178 ok(csbi2.srWindow.Right == ConRect.Right, "srWindow.Right = %d, expected %d\n",
179 csbi2.srWindow.Right, ConRect.Right);
180 ok(csbi2.srWindow.Bottom == ConRect.Bottom, "srWindow.Bottom = %d, expected %d\n",
181 csbi2.srWindow.Bottom, ConRect.Bottom);
182 }
183
184 /* Test 3: Similar to Test 2, but set the Right/Bottom members too large
185 * with respect to the screen buffer size, so that after their shift, they
186 * are still too large (fails, agrees with MSDN) */
187 ConRect.Left = ConRect.Top = -5;
188 ConRect.Right = csbi.dwSize.X + 2; // Bigger than SB size
189 ConRect.Bottom = csbi.dwSize.Y + 2; // Bigger than SB size
190 SetLastError(0xdeadbeef);
191 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
192 dwLastError = GetLastError();
193 ok(!Success, "Setting console wnd info should have failed!\n");
194 ok(dwLastError == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
195 ERROR_INVALID_PARAMETER, dwLastError);
196
197 /* Check the new reported window size rect */
198 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
199 ok(Success, "Getting SB info\n");
200 if (Success)
201 {
202 /* NOTE that here we compare against the old csbi data! */
203 ok(csbi2.srWindow.Left == 0, "srWindow.Left = %d, expected %d\n",
204 csbi2.srWindow.Left, 0);
205 ok(csbi2.srWindow.Top == 0, "srWindow.Top = %d, expected %d\n",
206 csbi2.srWindow.Top, 0);
207 ok(csbi2.srWindow.Right == csbi.dwSize.X - 2, "srWindow.Right = %d, expected %d\n",
208 csbi2.srWindow.Right, csbi.dwSize.X - 2);
209 ok(csbi2.srWindow.Bottom == csbi.dwSize.Y - 2, "srWindow.Bottom = %d, expected %d\n",
210 csbi2.srWindow.Bottom, csbi.dwSize.Y - 2);
211 }
212
213 /* Test 4: Similar to Tests 2 and 3, but we here just check what happens for
214 * the Right/Bottom members when they are too large, without caring about the
215 * Left/Top members (the latter being set to valid values this time)
216 * (fails, agrees with MSDN) */
217 ConRect.Left = ConRect.Top = 2; // OK
218 ConRect.Right = csbi.dwSize.X + 7; // Bigger than SB size
219 ConRect.Bottom = csbi.dwSize.Y + 7; // Bigger than SB size
220 SetLastError(0xdeadbeef);
221 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
222 dwLastError = GetLastError();
223 ok(!Success, "Setting console wnd info should have failed!\n");
224 ok(dwLastError == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
225 ERROR_INVALID_PARAMETER, dwLastError);
226
227 /* Check the new reported window size rect */
228 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
229 ok(Success, "Getting SB info\n");
230 if (Success)
231 {
232 ok(csbi2.srWindow.Left == 0, "srWindow.Left = %d, expected %d\n",
233 csbi2.srWindow.Left, 0);
234 ok(csbi2.srWindow.Top == 0, "srWindow.Top = %d, expected %d\n",
235 csbi2.srWindow.Top, 0);
236
237 /* NOTE that here we compare against the old csbi data! */
238 ok(csbi2.srWindow.Right == csbi.dwSize.X - 2, "srWindow.Right = %d, expected %d\n",
239 csbi2.srWindow.Right, csbi.dwSize.X - 2);
240 ok(csbi2.srWindow.Bottom == csbi.dwSize.Y - 2, "srWindow.Bottom = %d, expected %d\n",
241 csbi2.srWindow.Bottom, csbi.dwSize.Y - 2);
242 }
243
244 /* Test 5: Set Right/Bottom members strictly smaller than Left/Top members
245 * (fails, agrees with MSDN) */
246 ConRect.Left = csbi.dwSize.X - 5;
247 ConRect.Right = 0;
248 ConRect.Top = csbi.dwSize.Y - 5;
249 ConRect.Bottom = 0;
250 SetLastError(0xdeadbeef);
251 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
252 dwLastError = GetLastError();
253 ok(!Success, "Setting console wnd info should have failed!\n");
254 ok(dwLastError == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
255 ERROR_INVALID_PARAMETER, dwLastError);
256
257 /* Test 6: Set Left/Top members equal to the Right/Bottom members respectively
258 * (succeeds, disagrees with MSDN) */
259 ConRect.Left = ConRect.Right = 2;
260 ConRect.Top = ConRect.Bottom = 5;
261 SetLastError(0xdeadbeef);
262 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
263 dwLastError = GetLastError();
264 ok(Success, "Setting console wnd info should have succeeded!\n");
265 ok(dwLastError != ERROR_INVALID_PARAMETER, "GetLastError: %lu\n", dwLastError);
266
267 /* Check the new reported window size rect */
268 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
269 ok(Success, "Getting SB info\n");
270 if (Success)
271 {
272 ok(csbi2.srWindow.Left == ConRect.Left, "srWindow.Left = %d, expected %d\n",
273 csbi2.srWindow.Left, ConRect.Left);
274 ok(csbi2.srWindow.Top == ConRect.Top, "srWindow.Top = %d, expected %d\n",
275 csbi2.srWindow.Top, ConRect.Top);
276 ok(csbi2.srWindow.Right == ConRect.Right, "srWindow.Right = %d, expected %d\n",
277 csbi2.srWindow.Right, ConRect.Right);
278 ok(csbi2.srWindow.Bottom == ConRect.Bottom, "srWindow.Bottom = %d, expected %d\n",
279 csbi2.srWindow.Bottom, ConRect.Bottom);
280 }
281
282 /*
283 * Test 7: Test how large can the console window be, for a given
284 * screen buffer size. For that we set the console screen buffer
285 * to a really large size, hoping that its corresponding window size
286 * is larger than the computer screen. The permitted maximum window
287 * size specified in csbi.dwMaximumWindowSize should be a boundary.
288 */
289 Resolution.X = 500;
290 Resolution.Y = 500;
291 ResizeTextConsole(hConOut, &csbi, Resolution, NULL);
292 /* Be sure that csbi.dwMaximumWindowSize is strictly smaller
293 * than the console screen buffer size, for our matters... */
294 ok((csbi.dwMaximumWindowSize.X < Resolution.X) && (csbi.dwMaximumWindowSize.Y < Resolution.Y),
295 "dwMaximumWindowSize = {%d, %d} was expected to be smaller than Resolution = {%d, %d}\n",
296 csbi.dwMaximumWindowSize.X, csbi.dwMaximumWindowSize.Y, Resolution.X, Resolution.Y);
297
298 /* Now try to set first the console window to a size smaller than the maximum size */
299 ConRect.Left = ConRect.Top = 0;
300 ConRect.Right = csbi.dwMaximumWindowSize.X - 1;
301 ConRect.Bottom = csbi.dwMaximumWindowSize.Y - 1;
302 SetLastError(0xdeadbeef);
303 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
304 dwLastError = GetLastError();
305 ok(Success, "Setting console wnd info should have succeeded!\n");
306 ok(dwLastError != ERROR_INVALID_PARAMETER, "GetLastError: %lu\n", dwLastError);
307
308 /* Check the new reported window size rect */
309 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
310 ok(Success, "Getting SB info\n");
311 if (Success)
312 {
313 ok(csbi2.srWindow.Left == ConRect.Left, "srWindow.Left = %d, expected %d\n",
314 csbi2.srWindow.Left, ConRect.Left);
315 ok(csbi2.srWindow.Top == ConRect.Top, "srWindow.Top = %d, expected %d\n",
316 csbi2.srWindow.Top, ConRect.Top);
317 ok(csbi2.srWindow.Right == ConRect.Right, "srWindow.Right = %d, expected %d\n",
318 csbi2.srWindow.Right, ConRect.Right);
319 ok(csbi2.srWindow.Bottom == ConRect.Bottom, "srWindow.Bottom = %d, expected %d\n",
320 csbi2.srWindow.Bottom, ConRect.Bottom);
321 }
322
323 /* And now try to set the console window to a size larger than the maximum size.
324 * The SetConsoleWindowInfo call should fail */
325 ConRect.Left = ConRect.Top = 0;
326 ConRect.Right = csbi.dwMaximumWindowSize.X + 1;
327 ConRect.Bottom = csbi.dwMaximumWindowSize.Y + 1;
328 SetLastError(0xdeadbeef);
329 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
330 dwLastError = GetLastError();
331 ok(!Success, "Setting console wnd info should have failed!\n");
332 ok(dwLastError == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
333 ERROR_INVALID_PARAMETER, dwLastError);
334
335 /* Check the new reported window size rect */
336 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
337 ok(Success, "Getting SB info\n");
338 if (Success)
339 {
340 ok(csbi2.srWindow.Left == 0, "srWindow.Left = %d, expected %d\n",
341 csbi2.srWindow.Left, 0);
342 ok(csbi2.srWindow.Top == 0, "srWindow.Top = %d, expected %d\n",
343 csbi2.srWindow.Top, 0);
344 ok(csbi2.srWindow.Right == csbi.dwMaximumWindowSize.X - 1, "srWindow.Right = %d, expected %d\n",
345 csbi2.srWindow.Right, csbi.dwMaximumWindowSize.X - 1);
346 ok(csbi2.srWindow.Bottom == csbi.dwMaximumWindowSize.Y - 1, "srWindow.Bottom = %d, expected %d\n",
347 csbi2.srWindow.Bottom, csbi.dwMaximumWindowSize.Y - 1);
348 }
349
350
351 /* Done! Restore the original console screen buffer size and perform cleanup */
352 ResizeTextConsole(hConOut, &csbi, org_csbi.dwSize, &org_csbi.srWindow);
353
354 Cleanup:
355 CloseHandle(hConOut);
356 }