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 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 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