52b4cad3fa573a8935da1cb537cf1e2e3546a2d0
[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 ok(csbi2.srWindow.Left == 0, "srWindow.Left = %d, expected 0\n", csbi2.srWindow.Left);
170 ok(csbi2.srWindow.Top == 0, "srWindow.Top = %d, expected 0\n", csbi2.srWindow.Top);
171
172 /* NOTE that here we compare against the old csbi data! */
173 ok(csbi2.srWindow.Right == csbi.dwSize.X - 2, "srWindow.Right = %d, expected %d\n",
174 csbi2.srWindow.Right, csbi.dwSize.X - 2);
175 ok(csbi2.srWindow.Bottom == csbi.dwSize.Y - 2, "srWindow.Bottom = %d, expected %d\n",
176 csbi2.srWindow.Bottom, csbi.dwSize.Y - 2);
177 }
178
179 /* Test 3: Similar to Test 2, but set the Right/Bottom members too large
180 * with respect to the screen buffer size, so that after their shift, they
181 * are still too large (fails, agrees with MSDN) */
182 ConRect.Left = ConRect.Top = -5;
183 ConRect.Right = csbi.dwSize.X + 2; // Bigger than SB size
184 ConRect.Bottom = csbi.dwSize.Y + 2; // Bigger than SB size
185 SetLastError(0xdeadbeef);
186 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
187 dwLastError = GetLastError();
188 ok(!Success, "Setting console wnd info should have failed!\n");
189 ok(dwLastError == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
190 ERROR_INVALID_PARAMETER, dwLastError);
191
192 /* Check the new reported window size rect */
193 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
194 ok(Success, "Getting SB info\n");
195 if (Success)
196 {
197 /* NOTE that here we compare against the old csbi data! */
198 ok(csbi2.srWindow.Left == 0, "srWindow(2).Left = %d, expected equal to %d\n",
199 csbi2.srWindow.Left, 0);
200 ok(csbi2.srWindow.Top == 0, "srWindow(2).Top = %d, expected equal to %d\n",
201 csbi2.srWindow.Top, 0);
202 ok(csbi2.srWindow.Right == csbi.dwSize.X - 2, "srWindow(2).Right = %d, expected equal to %d\n",
203 csbi2.srWindow.Right, csbi.dwSize.X - 2);
204 ok(csbi2.srWindow.Bottom == csbi.dwSize.Y - 2, "srWindow(2).Bottom = %d, expected equal to %d\n",
205 csbi2.srWindow.Bottom, csbi.dwSize.Y - 2);
206 }
207
208 /* Test 4: Similar to Tests 2 and 3, but we here just check what happens for
209 * the Right/Bottom members when they are too large, without caring about the
210 * Left/Top members (the latter being set to valid values this time)
211 * (fails, agrees with MSDN) */
212 ConRect.Left = ConRect.Top = 2; // OK
213 ConRect.Right = csbi.dwSize.X + 7; // Bigger than SB size
214 ConRect.Bottom = csbi.dwSize.Y + 7; // Bigger than SB size
215 SetLastError(0xdeadbeef);
216 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
217 dwLastError = GetLastError();
218 ok(!Success, "Setting console wnd info should have failed!\n");
219 ok(dwLastError == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
220 ERROR_INVALID_PARAMETER, dwLastError);
221
222 /* Check the new reported window size rect */
223 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
224 ok(Success, "Getting SB info\n");
225 if (Success)
226 {
227 ok(csbi2.srWindow.Left == 0, "srWindow.Left = %d, expected 0\n", csbi2.srWindow.Left);
228 ok(csbi2.srWindow.Top == 0, "srWindow.Top = %d, expected 0\n", csbi2.srWindow.Top);
229
230 /* NOTE that here we compare against the old csbi data! */
231 ok(csbi2.srWindow.Right == csbi.dwSize.X - 2, "srWindow.Right = %d, expected %d\n",
232 csbi2.srWindow.Right, csbi.dwSize.X - 2);
233 ok(csbi2.srWindow.Bottom == csbi.dwSize.Y - 2, "srWindow.Bottom = %d, expected %d\n",
234 csbi2.srWindow.Bottom, csbi.dwSize.Y - 2);
235 }
236
237 /* Test 5: Set Right/Bottom members strictly smaller than Left/Top members
238 * (fails, agrees with MSDN) */
239 ConRect.Left = csbi.dwSize.X - 5;
240 ConRect.Right = 0;
241 ConRect.Top = csbi.dwSize.Y - 5;
242 ConRect.Bottom = 0;
243 SetLastError(0xdeadbeef);
244 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
245 dwLastError = GetLastError();
246 ok(!Success, "Setting console wnd info should have failed!\n");
247 ok(dwLastError == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
248 ERROR_INVALID_PARAMETER, dwLastError);
249
250 /* Test 6: Set Left/Top members equal to the Right/Bottom members respectively
251 * (succeeds, disagrees with MSDN) */
252 ConRect.Left = ConRect.Right = 2;
253 ConRect.Top = ConRect.Bottom = 5;
254 SetLastError(0xdeadbeef);
255 Success = SetConsoleWindowInfo(hConOut, TRUE, &ConRect);
256 dwLastError = GetLastError();
257 ok(Success, "Setting console wnd info should have succeeded!\n");
258 ok(dwLastError != ERROR_INVALID_PARAMETER, "GetLastError: %lu\n", dwLastError);
259
260 /* Check the new reported window size rect */
261 Success = GetConsoleScreenBufferInfo(hConOut, &csbi2);
262 ok(Success, "Getting SB info\n");
263 if (Success)
264 {
265 ok(csbi2.srWindow.Left == 2, "srWindow.Left = %d, expected 2\n", csbi2.srWindow.Left);
266 ok(csbi2.srWindow.Right == 2, "srWindow.Right = %d, expected 2\n", csbi2.srWindow.Right);
267
268 ok(csbi2.srWindow.Top == 5, "srWindow.Top = %d, expected 5\n", csbi2.srWindow.Top);
269 ok(csbi2.srWindow.Bottom == 5, "srWindow.Bottom = %d, expected 5\n", csbi2.srWindow.Bottom);
270 }
271
272
273 /* Done! Restore the original console screen buffer size and perform cleanup */
274 ResizeTextConsole(hConOut, &csbi, org_csbi.dwSize, &org_csbi.srWindow);
275
276 Cleanup:
277 CloseHandle(hConOut);
278 }