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