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