1 /* 2 * Unit tests for console API 3 * 4 * Copyright (c) 2003,2004 Eric Pouech 5 * Copyright (c) 2007 Kirill K. Smirnov 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "precomp.h" 23 24 static BOOL (WINAPI *pGetConsoleInputExeNameA)(DWORD, LPSTR); 25 static DWORD (WINAPI *pGetConsoleProcessList)(LPDWORD, DWORD); 26 static HANDLE (WINAPI *pOpenConsoleW)(LPCWSTR,DWORD,BOOL,DWORD); 27 static BOOL (WINAPI *pSetConsoleInputExeNameA)(LPCSTR); 28 static BOOL (WINAPI *pVerifyConsoleIoHandle)(HANDLE handle); 29 30 /* DEFAULT_ATTRIB is used for all initial filling of the console. 31 * all modifications are made with TEST_ATTRIB so that we could check 32 * what has to be modified or not 33 */ 34 #define TEST_ATTRIB (BACKGROUND_BLUE | FOREGROUND_GREEN) 35 #define DEFAULT_ATTRIB (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED) 36 /* when filling the screen with non-blank chars, this macro defines 37 * what character should be at position 'c' 38 */ 39 #define CONTENT(c) ('A' + (((c).Y * 17 + (c).X) % 23)) 40 41 #define okCURSOR(hCon, c) do { \ 42 CONSOLE_SCREEN_BUFFER_INFO __sbi; \ 43 BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \ 44 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \ 45 ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \ 46 (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \ 47 } while (0) 48 49 #define okCHAR(hCon, c, ch, attr) do { \ 50 char __ch; WORD __attr; DWORD __len; BOOL expect; \ 51 expect = ReadConsoleOutputCharacterA((hCon), &__ch, 1, (c), &__len) == 1 && __len == 1 && __ch == (ch); \ 52 ok(expect, "At (%d,%d): expecting char '%c'/%02x got '%c'/%02x\n", (c).X, (c).Y, (ch), (ch), __ch, __ch); \ 53 expect = ReadConsoleOutputAttribute((hCon), &__attr, 1, (c), &__len) == 1 && __len == 1 && __attr == (attr); \ 54 ok(expect, "At (%d,%d): expecting attr %04x got %04x\n", (c).X, (c).Y, (attr), __attr); \ 55 } while (0) 56 57 static void init_function_pointers(void) 58 { 59 HMODULE hKernel32; 60 61 #define KERNEL32_GET_PROC(func) \ 62 p##func = (void *)GetProcAddress(hKernel32, #func); \ 63 if(!p##func) trace("GetProcAddress(hKernel32, '%s') failed\n", #func); 64 65 hKernel32 = GetModuleHandleA("kernel32.dll"); 66 KERNEL32_GET_PROC(GetConsoleInputExeNameA); 67 KERNEL32_GET_PROC(GetConsoleProcessList); 68 KERNEL32_GET_PROC(OpenConsoleW); 69 KERNEL32_GET_PROC(SetConsoleInputExeNameA); 70 KERNEL32_GET_PROC(VerifyConsoleIoHandle); 71 72 #undef KERNEL32_GET_PROC 73 } 74 75 /* FIXME: this could be optimized on a speed point of view */ 76 static void resetContent(HANDLE hCon, COORD sbSize, BOOL content) 77 { 78 COORD c; 79 WORD attr = DEFAULT_ATTRIB; 80 char ch; 81 DWORD len; 82 83 for (c.X = 0; c.X < sbSize.X; c.X++) 84 { 85 for (c.Y = 0; c.Y < sbSize.Y; c.Y++) 86 { 87 ch = (content) ? CONTENT(c) : ' '; 88 WriteConsoleOutputAttribute(hCon, &attr, 1, c, &len); 89 WriteConsoleOutputCharacterA(hCon, &ch, 1, c, &len); 90 } 91 } 92 } 93 94 static void testCursor(HANDLE hCon, COORD sbSize) 95 { 96 COORD c; 97 98 c.X = c.Y = 0; 99 ok(SetConsoleCursorPosition(0, c) == 0, "No handle\n"); 100 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n", 101 ERROR_INVALID_HANDLE, GetLastError()); 102 103 c.X = c.Y = 0; 104 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n"); 105 okCURSOR(hCon, c); 106 107 c.X = sbSize.X - 1; 108 c.Y = sbSize.Y - 1; 109 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in lower-right\n"); 110 okCURSOR(hCon, c); 111 112 c.X = sbSize.X; 113 c.Y = sbSize.Y - 1; 114 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n"); 115 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n", 116 ERROR_INVALID_PARAMETER, GetLastError()); 117 118 c.X = sbSize.X - 1; 119 c.Y = sbSize.Y; 120 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n"); 121 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n", 122 ERROR_INVALID_PARAMETER, GetLastError()); 123 124 c.X = -1; 125 c.Y = 0; 126 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n"); 127 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n", 128 ERROR_INVALID_PARAMETER, GetLastError()); 129 130 c.X = 0; 131 c.Y = -1; 132 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n"); 133 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n", 134 ERROR_INVALID_PARAMETER, GetLastError()); 135 } 136 137 static void testCursorInfo(HANDLE hCon) 138 { 139 BOOL ret; 140 CONSOLE_CURSOR_INFO info; 141 142 SetLastError(0xdeadbeef); 143 ret = GetConsoleCursorInfo(NULL, NULL); 144 ok(!ret, "Expected failure\n"); 145 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n", 146 ERROR_INVALID_HANDLE, GetLastError()); 147 148 SetLastError(0xdeadbeef); 149 info.dwSize = -1; 150 ret = GetConsoleCursorInfo(NULL, &info); 151 ok(!ret, "Expected failure\n"); 152 ok(info.dwSize == -1, "Expected no change for dwSize\n"); 153 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n", 154 ERROR_INVALID_HANDLE, GetLastError()); 155 156 /* Test the correct call first to distinguish between win9x and the rest */ 157 SetLastError(0xdeadbeef); 158 ret = GetConsoleCursorInfo(hCon, &info); 159 ok(ret, "Expected success\n"); 160 ok(info.dwSize == 25 || 161 info.dwSize == 12 /* win9x */, 162 "Expected 12 or 25, got %d\n", info.dwSize); 163 ok(info.bVisible, "Expected the cursor to be visible\n"); 164 ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %u\n", 165 0xdeadbeef, GetLastError()); 166 167 /* Don't test NULL CONSOLE_CURSOR_INFO, it crashes on win9x and win7 */ 168 } 169 170 static void testEmptyWrite(HANDLE hCon) 171 { 172 static const char emptybuf[16]; 173 COORD c; 174 DWORD len; 175 176 c.X = c.Y = 0; 177 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n"); 178 179 len = -1; 180 ok(WriteConsoleA(hCon, NULL, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n"); 181 okCURSOR(hCon, c); 182 183 /* Passing a NULL lpBuffer with sufficiently large non-zero length succeeds 184 * on native Windows and result in memory-like contents being written to 185 * the console. Calling WriteConsoleW like this will crash on Wine. */ 186 if (0) 187 { 188 len = -1; 189 ok(!WriteConsoleA(hCon, NULL, 16, &len, NULL) && len == -1, "WriteConsole\n"); 190 okCURSOR(hCon, c); 191 192 /* Cursor advances for this call. */ 193 len = -1; 194 ok(WriteConsoleA(hCon, NULL, 128, &len, NULL) != 0 && len == 128, "WriteConsole\n"); 195 } 196 197 len = -1; 198 ok(WriteConsoleA(hCon, emptybuf, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n"); 199 okCURSOR(hCon, c); 200 201 /* WriteConsole does not halt on a null terminator and is happy to write 202 * memory contents beyond the actual size of the buffer. */ 203 len = -1; 204 ok(WriteConsoleA(hCon, emptybuf, 16, &len, NULL) != 0 && len == 16, "WriteConsole\n"); 205 c.X += 16; 206 okCURSOR(hCon, c); 207 } 208 209 static void testWriteSimple(HANDLE hCon) 210 { 211 COORD c; 212 DWORD len; 213 const char* mytest = "abcdefg"; 214 const int mylen = strlen(mytest); 215 216 /* single line write */ 217 c.X = c.Y = 0; 218 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n"); 219 220 ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); 221 c.Y = 0; 222 for (c.X = 0; c.X < mylen; c.X++) 223 { 224 okCHAR(hCon, c, mytest[c.X], TEST_ATTRIB); 225 } 226 227 okCURSOR(hCon, c); 228 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 229 } 230 231 static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize) 232 { 233 COORD c; 234 DWORD len, mode; 235 const char* mytest = "123"; 236 const int mylen = strlen(mytest); 237 int ret; 238 int p; 239 240 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode & ~(ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT)), 241 "clearing wrap at EOL & processed output\n"); 242 243 /* write line, wrapping disabled, buffer exceeds sb width */ 244 c.X = sbSize.X - 3; c.Y = 0; 245 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n"); 246 247 ret = WriteConsoleA(hCon, mytest, mylen, &len, NULL); 248 ok(ret != 0 && len == mylen, "Couldn't write, ret = %d, len = %d\n", ret, len); 249 c.Y = 0; 250 for (p = mylen - 3; p < mylen; p++) 251 { 252 c.X = sbSize.X - 3 + p % 3; 253 okCHAR(hCon, c, mytest[p], TEST_ATTRIB); 254 } 255 256 c.X = 0; c.Y = 1; 257 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 258 259 p = sbSize.X - 3 + mylen % 3; 260 c.X = p; c.Y = 0; 261 262 /* write line, wrapping disabled, strings end on end of line */ 263 c.X = sbSize.X - mylen; c.Y = 0; 264 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n"); 265 266 ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); 267 } 268 269 static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize) 270 { 271 COORD c; 272 DWORD len, mode; 273 const char* mytest = "abcd\nf\tg"; 274 const int mylen = strlen(mytest); 275 const int mylen2 = strchr(mytest, '\n') - mytest; 276 int p; 277 WORD attr; 278 279 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, (mode | ENABLE_PROCESSED_OUTPUT) & ~ENABLE_WRAP_AT_EOL_OUTPUT), 280 "clearing wrap at EOL & setting processed output\n"); 281 282 /* write line, wrapping disabled, buffer exceeds sb width */ 283 c.X = sbSize.X - 5; c.Y = 0; 284 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-5\n"); 285 286 ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); 287 c.Y = 0; 288 for (c.X = sbSize.X - 5; c.X < sbSize.X - 1; c.X++) 289 { 290 okCHAR(hCon, c, mytest[c.X - sbSize.X + 5], TEST_ATTRIB); 291 } 292 293 ReadConsoleOutputAttribute(hCon, &attr, 1, c, &len); 294 /* Win9x and WinMe change the attribs for '\n' up to 'f' */ 295 if (attr == TEST_ATTRIB) 296 { 297 win_skip("Win9x/WinMe don't respect ~ENABLE_WRAP_AT_EOL_OUTPUT\n"); 298 return; 299 } 300 301 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 302 303 c.X = 0; c.Y++; 304 okCHAR(hCon, c, mytest[5], TEST_ATTRIB); 305 for (c.X = 1; c.X < 8; c.X++) 306 okCHAR(hCon, c, ' ', TEST_ATTRIB); 307 okCHAR(hCon, c, mytest[7], TEST_ATTRIB); 308 c.X++; 309 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 310 311 okCURSOR(hCon, c); 312 313 /* write line, wrapping disabled, strings end on end of line */ 314 c.X = sbSize.X - 4; c.Y = 0; 315 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4\n"); 316 317 ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); 318 c.Y = 0; 319 for (c.X = sbSize.X - 4; c.X < sbSize.X; c.X++) 320 { 321 okCHAR(hCon, c, mytest[c.X - sbSize.X + 4], TEST_ATTRIB); 322 } 323 c.X = 0; c.Y++; 324 okCHAR(hCon, c, mytest[5], TEST_ATTRIB); 325 for (c.X = 1; c.X < 8; c.X++) 326 okCHAR(hCon, c, ' ', TEST_ATTRIB); 327 okCHAR(hCon, c, mytest[7], TEST_ATTRIB); 328 c.X++; 329 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 330 331 okCURSOR(hCon, c); 332 333 /* write line, wrapping disabled, strings end after end of line */ 334 c.X = sbSize.X - 3; c.Y = 0; 335 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4\n"); 336 337 ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); 338 c.Y = 0; 339 for (p = mylen2 - 3; p < mylen2; p++) 340 { 341 c.X = sbSize.X - 3 + p % 3; 342 okCHAR(hCon, c, mytest[p], TEST_ATTRIB); 343 } 344 c.X = 0; c.Y = 1; 345 okCHAR(hCon, c, mytest[5], TEST_ATTRIB); 346 for (c.X = 1; c.X < 8; c.X++) 347 okCHAR(hCon, c, ' ', TEST_ATTRIB); 348 okCHAR(hCon, c, mytest[7], TEST_ATTRIB); 349 c.X++; 350 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 351 352 okCURSOR(hCon, c); 353 } 354 355 static void testWriteWrappedNotProcessed(HANDLE hCon, COORD sbSize) 356 { 357 COORD c; 358 DWORD len, mode; 359 const char* mytest = "abcd\nf\tg"; 360 const int mylen = strlen(mytest); 361 int p; 362 363 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon,(mode | ENABLE_WRAP_AT_EOL_OUTPUT) & ~(ENABLE_PROCESSED_OUTPUT)), 364 "setting wrap at EOL & clearing processed output\n"); 365 366 /* write line, wrapping enabled, buffer doesn't exceed sb width */ 367 c.X = sbSize.X - 9; c.Y = 0; 368 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n"); 369 370 ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); 371 c.Y = 0; 372 for (p = 0; p < mylen; p++) 373 { 374 c.X = sbSize.X - 9 + p; 375 okCHAR(hCon, c, mytest[p], TEST_ATTRIB); 376 } 377 c.X = sbSize.X - 9 + mylen; 378 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 379 c.X = 0; c.Y = 1; 380 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 381 382 /* write line, wrapping enabled, buffer does exceed sb width */ 383 c.X = sbSize.X - 3; c.Y = 0; 384 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n"); 385 386 c.Y = 1; 387 c.X = mylen - 3; 388 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 389 } 390 391 static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize) 392 { 393 COORD c; 394 DWORD len, mode; 395 const char* mytest = "abcd\nf\tg"; 396 const int mylen = strlen(mytest); 397 int p; 398 WORD attr; 399 400 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode | (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)), 401 "setting wrap at EOL & processed output\n"); 402 403 /* write line, wrapping enabled, buffer doesn't exceed sb width */ 404 c.X = sbSize.X - 9; c.Y = 0; 405 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n"); 406 407 ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); 408 for (p = 0; p < 4; p++) 409 { 410 c.X = sbSize.X - 9 + p; 411 okCHAR(hCon, c, mytest[p], TEST_ATTRIB); 412 } 413 c.X = sbSize.X - 9 + p; 414 ReadConsoleOutputAttribute(hCon, &attr, 1, c, &len); 415 if (attr == TEST_ATTRIB) 416 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n"); 417 else 418 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 419 c.X = 0; c.Y++; 420 okCHAR(hCon, c, mytest[5], TEST_ATTRIB); 421 for (c.X = 1; c.X < 8; c.X++) 422 okCHAR(hCon, c, ' ', TEST_ATTRIB); 423 okCHAR(hCon, c, mytest[7], TEST_ATTRIB); 424 c.X++; 425 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 426 okCURSOR(hCon, c); 427 428 /* write line, wrapping enabled, buffer does exceed sb width */ 429 c.X = sbSize.X - 3; c.Y = 2; 430 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n"); 431 432 ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); 433 for (p = 0; p < 3; p++) 434 { 435 c.X = sbSize.X - 3 + p; 436 okCHAR(hCon, c, mytest[p], TEST_ATTRIB); 437 } 438 c.X = 0; c.Y++; 439 okCHAR(hCon, c, mytest[3], TEST_ATTRIB); 440 c.X++; 441 ReadConsoleOutputAttribute(hCon, &attr, 1, c, &len); 442 if (attr == TEST_ATTRIB) 443 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n"); 444 else 445 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 446 447 c.X = 0; c.Y++; 448 okCHAR(hCon, c, mytest[5], TEST_ATTRIB); 449 for (c.X = 1; c.X < 8; c.X++) 450 okCHAR(hCon, c, ' ', TEST_ATTRIB); 451 okCHAR(hCon, c, mytest[7], TEST_ATTRIB); 452 c.X++; 453 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB); 454 okCURSOR(hCon, c); 455 } 456 457 static void testWrite(HANDLE hCon, COORD sbSize) 458 { 459 /* FIXME: should in fact ensure that the sb is at least 10 characters wide */ 460 ok(SetConsoleTextAttribute(hCon, TEST_ATTRIB), "Setting default text color\n"); 461 resetContent(hCon, sbSize, FALSE); 462 testEmptyWrite(hCon); 463 resetContent(hCon, sbSize, FALSE); 464 testWriteSimple(hCon); 465 resetContent(hCon, sbSize, FALSE); 466 testWriteNotWrappedNotProcessed(hCon, sbSize); 467 resetContent(hCon, sbSize, FALSE); 468 testWriteNotWrappedProcessed(hCon, sbSize); 469 resetContent(hCon, sbSize, FALSE); 470 testWriteWrappedNotProcessed(hCon, sbSize); 471 resetContent(hCon, sbSize, FALSE); 472 testWriteWrappedProcessed(hCon, sbSize); 473 } 474 475 static void testScroll(HANDLE hCon, COORD sbSize) 476 { 477 SMALL_RECT scroll, clip; 478 COORD dst, c, tc; 479 CHAR_INFO ci; 480 BOOL ret; 481 482 #define W 11 483 #define H 7 484 485 #define IN_SRECT(r,c) ((r).Left <= (c).X && (c).X <= (r).Right && (r).Top <= (c).Y && (c).Y <= (r).Bottom) 486 #define IN_SRECT2(r,d,c) ((d).X <= (c).X && (c).X <= (d).X + (r).Right - (r).Left && (d).Y <= (c).Y && (c).Y <= (d).Y + (r).Bottom - (r).Top) 487 488 /* no clipping, src & dst rect don't overlap */ 489 resetContent(hCon, sbSize, TRUE); 490 491 scroll.Left = 0; 492 scroll.Right = W - 1; 493 scroll.Top = 0; 494 scroll.Bottom = H - 1; 495 dst.X = W + 3; 496 dst.Y = H + 3; 497 ci.Char.UnicodeChar = '#'; 498 ci.Attributes = TEST_ATTRIB; 499 500 clip.Left = 0; 501 clip.Right = sbSize.X - 1; 502 clip.Top = 0; 503 clip.Bottom = sbSize.Y - 1; 504 505 ok(ScrollConsoleScreenBufferA(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n"); 506 507 for (c.Y = 0; c.Y < sbSize.Y; c.Y++) 508 { 509 for (c.X = 0; c.X < sbSize.X; c.X++) 510 { 511 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c)) 512 { 513 tc.X = c.X - dst.X; 514 tc.Y = c.Y - dst.Y; 515 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB); 516 } 517 else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c)) 518 okCHAR(hCon, c, '#', TEST_ATTRIB); 519 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB); 520 } 521 } 522 523 /* no clipping, src & dst rect do overlap */ 524 resetContent(hCon, sbSize, TRUE); 525 526 scroll.Left = 0; 527 scroll.Right = W - 1; 528 scroll.Top = 0; 529 scroll.Bottom = H - 1; 530 dst.X = W /2; 531 dst.Y = H / 2; 532 ci.Char.UnicodeChar = '#'; 533 ci.Attributes = TEST_ATTRIB; 534 535 clip.Left = 0; 536 clip.Right = sbSize.X - 1; 537 clip.Top = 0; 538 clip.Bottom = sbSize.Y - 1; 539 540 ok(ScrollConsoleScreenBufferA(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n"); 541 542 for (c.Y = 0; c.Y < sbSize.Y; c.Y++) 543 { 544 for (c.X = 0; c.X < sbSize.X; c.X++) 545 { 546 if (dst.X <= c.X && c.X < dst.X + W && dst.Y <= c.Y && c.Y < dst.Y + H) 547 { 548 tc.X = c.X - dst.X; 549 tc.Y = c.Y - dst.Y; 550 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB); 551 } 552 else if (c.X < W && c.Y < H) okCHAR(hCon, c, '#', TEST_ATTRIB); 553 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB); 554 } 555 } 556 557 /* clipping, src & dst rect don't overlap */ 558 resetContent(hCon, sbSize, TRUE); 559 560 scroll.Left = 0; 561 scroll.Right = W - 1; 562 scroll.Top = 0; 563 scroll.Bottom = H - 1; 564 dst.X = W + 3; 565 dst.Y = H + 3; 566 ci.Char.UnicodeChar = '#'; 567 ci.Attributes = TEST_ATTRIB; 568 569 clip.Left = W / 2; 570 clip.Right = min(W + W / 2, sbSize.X - 1); 571 clip.Top = H / 2; 572 clip.Bottom = min(H + H / 2, sbSize.Y - 1); 573 574 SetLastError(0xdeadbeef); 575 ret = ScrollConsoleScreenBufferA(hCon, &scroll, &clip, dst, &ci); 576 if (ret) 577 { 578 for (c.Y = 0; c.Y < sbSize.Y; c.Y++) 579 { 580 for (c.X = 0; c.X < sbSize.X; c.X++) 581 { 582 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c)) 583 { 584 tc.X = c.X - dst.X; 585 tc.Y = c.Y - dst.Y; 586 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB); 587 } 588 else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c)) 589 okCHAR(hCon, c, '#', TEST_ATTRIB); 590 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB); 591 } 592 } 593 } 594 else 595 { 596 /* Win9x will fail, Only accept ERROR_NOT_ENOUGH_MEMORY */ 597 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, 598 "Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError()); 599 } 600 601 /* clipping, src & dst rect do overlap */ 602 resetContent(hCon, sbSize, TRUE); 603 604 scroll.Left = 0; 605 scroll.Right = W - 1; 606 scroll.Top = 0; 607 scroll.Bottom = H - 1; 608 dst.X = W / 2 - 3; 609 dst.Y = H / 2 - 3; 610 ci.Char.UnicodeChar = '#'; 611 ci.Attributes = TEST_ATTRIB; 612 613 clip.Left = W / 2; 614 clip.Right = min(W + W / 2, sbSize.X - 1); 615 clip.Top = H / 2; 616 clip.Bottom = min(H + H / 2, sbSize.Y - 1); 617 618 ok(ScrollConsoleScreenBufferA(hCon, &scroll, &clip, dst, &ci), "Scrolling SB\n"); 619 620 for (c.Y = 0; c.Y < sbSize.Y; c.Y++) 621 { 622 for (c.X = 0; c.X < sbSize.X; c.X++) 623 { 624 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c)) 625 { 626 tc.X = c.X - dst.X; 627 tc.Y = c.Y - dst.Y; 628 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB); 629 } 630 else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c)) 631 okCHAR(hCon, c, '#', TEST_ATTRIB); 632 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB); 633 } 634 } 635 } 636 637 static int mch_count; 638 /* we need the event as Wine console event generation isn't synchronous 639 * (ie GenerateConsoleCtrlEvent returns before all ctrl-handlers in all 640 * processes have been called). 641 */ 642 static HANDLE mch_event; 643 static BOOL WINAPI mch(DWORD event) 644 { 645 mch_count++; 646 SetEvent(mch_event); 647 return TRUE; 648 } 649 650 static void testCtrlHandler(void) 651 { 652 ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n"); 653 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %u\n", GetLastError()); 654 ok(SetConsoleCtrlHandler(mch, TRUE), "Couldn't set handler\n"); 655 /* wine requires the event for the test, as we cannot ensure, so far, that 656 * events are processed synchronously in GenerateConsoleCtrlEvent() 657 */ 658 mch_event = CreateEventA(NULL, TRUE, FALSE, NULL); 659 mch_count = 0; 660 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n"); 661 /* FIXME: it isn't synchronous on wine but it can still happen before we test */ 662 if (0) ok(mch_count == 1, "Event isn't synchronous\n"); 663 ok(WaitForSingleObject(mch_event, 3000) == WAIT_OBJECT_0, "event sending didn't work\n"); 664 CloseHandle(mch_event); 665 666 /* Turning off ctrl-c handling doesn't work on win9x such way ... */ 667 ok(SetConsoleCtrlHandler(NULL, TRUE), "Couldn't turn off ctrl-c handling\n"); 668 mch_event = CreateEventA(NULL, TRUE, FALSE, NULL); 669 mch_count = 0; 670 if(!(GetVersion() & 0x80000000)) 671 /* ... and next line leads to an unhandled exception on 9x. Avoid it on 9x. */ 672 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n"); 673 ok(WaitForSingleObject(mch_event, 3000) == WAIT_TIMEOUT && mch_count == 0, "Event shouldn't have been sent\n"); 674 CloseHandle(mch_event); 675 ok(SetConsoleCtrlHandler(mch, FALSE), "Couldn't remove handler\n"); 676 ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n"); 677 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %u\n", GetLastError()); 678 } 679 680 /* 681 * Test console screen buffer: 682 * 1) Try to set invalid handle. 683 * 2) Try to set non-console handles. 684 * 3) Use CONOUT$ file as active SB. 685 * 4) Test cursor. 686 * 5) Test output codepage to show it is not a property of SB. 687 * 6) Test switching to old SB if we close all handles to current SB - works 688 * in Windows, TODO in wine. 689 * 690 * What is not tested but should be: 691 * 1) ScreenBufferInfo 692 */ 693 static void testScreenBuffer(HANDLE hConOut) 694 { 695 HANDLE hConOutRW, hConOutRO, hConOutWT; 696 HANDLE hFileOutRW, hFileOutRO, hFileOutWT; 697 HANDLE hConOutNew; 698 char test_str1[] = "Test for SB1"; 699 char test_str2[] = "Test for SB2"; 700 char test_cp866[] = {0xe2, 0xa5, 0xe1, 0xe2, 0}; 701 char test_cp1251[] = {0xf2, 0xe5, 0xf1, 0xf2, 0}; 702 WCHAR test_unicode[] = {0x0442, 0x0435, 0x0441, 0x0442, 0}; 703 WCHAR str_wbuf[20]; 704 char str_buf[20]; 705 DWORD len, error; 706 COORD c; 707 BOOL ret; 708 DWORD oldcp; 709 710 if (!IsValidCodePage(866)) 711 { 712 skip("Codepage 866 not available\n"); 713 return; 714 } 715 716 /* In the beginning set output codepage to 866 */ 717 oldcp = GetConsoleOutputCP(); 718 SetLastError(0xdeadbeef); 719 ret = SetConsoleOutputCP(866); 720 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 721 { 722 win_skip("SetConsoleOutputCP is not implemented\n"); 723 return; 724 } 725 ok(ret, "Cannot set output codepage to 866\n"); 726 727 hConOutRW = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 728 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 729 CONSOLE_TEXTMODE_BUFFER, NULL); 730 ok(hConOutRW != INVALID_HANDLE_VALUE, 731 "Cannot create a new screen buffer for ReadWrite\n"); 732 hConOutRO = CreateConsoleScreenBuffer(GENERIC_READ, 733 FILE_SHARE_READ, NULL, 734 CONSOLE_TEXTMODE_BUFFER, NULL); 735 ok(hConOutRO != INVALID_HANDLE_VALUE, 736 "Cannot create a new screen buffer for ReadOnly\n"); 737 hConOutWT = CreateConsoleScreenBuffer(GENERIC_WRITE, 738 FILE_SHARE_WRITE, NULL, 739 CONSOLE_TEXTMODE_BUFFER, NULL); 740 ok(hConOutWT != INVALID_HANDLE_VALUE, 741 "Cannot create a new screen buffer for WriteOnly\n"); 742 743 hFileOutRW = CreateFileA("NUL", GENERIC_READ | GENERIC_WRITE, 744 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 745 OPEN_EXISTING, 0, NULL); 746 ok(hFileOutRW != INVALID_HANDLE_VALUE, "Cannot open NUL for ReadWrite\n"); 747 hFileOutRO = CreateFileA("NUL", GENERIC_READ, FILE_SHARE_READ, 748 NULL, OPEN_EXISTING, 0, NULL); 749 ok(hFileOutRO != INVALID_HANDLE_VALUE, "Cannot open NUL for ReadOnly\n"); 750 hFileOutWT = CreateFileA("NUL", GENERIC_WRITE, FILE_SHARE_WRITE, 751 NULL, OPEN_EXISTING, 0, NULL); 752 ok(hFileOutWT != INVALID_HANDLE_VALUE, "Cannot open NUL for WriteOnly\n"); 753 754 /* Trying to set invalid handle */ 755 SetLastError(0); 756 ok(!SetConsoleActiveScreenBuffer(INVALID_HANDLE_VALUE), 757 "Shouldn't succeed\n"); 758 ok(GetLastError() == ERROR_INVALID_HANDLE, 759 "GetLastError: expecting %u got %u\n", 760 ERROR_INVALID_HANDLE, GetLastError()); 761 762 /* Trying to set non-console handles */ 763 SetLastError(0); 764 ok(!SetConsoleActiveScreenBuffer(hFileOutRW), "Shouldn't succeed\n"); 765 ok(GetLastError() == ERROR_INVALID_HANDLE, 766 "GetLastError: expecting %u got %u\n", 767 ERROR_INVALID_HANDLE, GetLastError()); 768 769 SetLastError(0); 770 ok(!SetConsoleActiveScreenBuffer(hFileOutRO), "Shouldn't succeed\n"); 771 ok(GetLastError() == ERROR_INVALID_HANDLE, 772 "GetLastError: expecting %u got %u\n", 773 ERROR_INVALID_HANDLE, GetLastError()); 774 775 SetLastError(0); 776 ok(!SetConsoleActiveScreenBuffer(hFileOutWT), "Shouldn't succeed\n"); 777 ok(GetLastError() == ERROR_INVALID_HANDLE, 778 "GetLastError: expecting %u got %u\n", 779 ERROR_INVALID_HANDLE, GetLastError()); 780 781 /* trying to write non-console handle */ 782 SetLastError(0xdeadbeef); 783 ret = WriteConsoleA(hFileOutRW, test_str1, lstrlenA(test_str1), &len, NULL); 784 error = GetLastError(); 785 ok(!ret, "Shouldn't succeed\n"); 786 ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION, 787 "GetLastError: got %u\n", error); 788 789 SetLastError(0xdeadbeef); 790 ret = WriteConsoleA(hFileOutRO, test_str1, lstrlenA(test_str1), &len, NULL); 791 error = GetLastError(); 792 ok(!ret, "Shouldn't succeed\n"); 793 ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION, 794 "GetLastError: got %u\n", error); 795 796 SetLastError(0xdeadbeef); 797 ret = WriteConsoleA(hFileOutWT, test_str1, lstrlenA(test_str1), &len, NULL); 798 error = GetLastError(); 799 ok(!ret, "Shouldn't succeed\n"); 800 todo_wine ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION, 801 "GetLastError: got %u\n", error); 802 803 CloseHandle(hFileOutRW); 804 CloseHandle(hFileOutRO); 805 CloseHandle(hFileOutWT); 806 807 /* Trying to set SB handles with various access modes */ 808 SetLastError(0); 809 ok(!SetConsoleActiveScreenBuffer(hConOutRO), "Shouldn't succeed\n"); 810 ok(GetLastError() == ERROR_INVALID_HANDLE, 811 "GetLastError: expecting %u got %u\n", 812 ERROR_INVALID_HANDLE, GetLastError()); 813 814 ok(SetConsoleActiveScreenBuffer(hConOutWT), "Couldn't set new WriteOnly SB\n"); 815 816 ok(SetConsoleActiveScreenBuffer(hConOutRW), "Couldn't set new ReadWrite SB\n"); 817 818 CloseHandle(hConOutWT); 819 CloseHandle(hConOutRO); 820 821 /* Now we have two ReadWrite SB, active must be hConOutRW */ 822 /* Open current SB via CONOUT$ */ 823 hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, 824 NULL, OPEN_EXISTING, 0, 0); 825 ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n"); 826 827 828 /* test cursor */ 829 c.X = c.Y = 10; 830 SetConsoleCursorPosition(hConOut, c); 831 c.X = c.Y = 5; 832 SetConsoleCursorPosition(hConOutRW, c); 833 okCURSOR(hConOutNew, c); 834 c.X = c.Y = 10; 835 okCURSOR(hConOut, c); 836 837 838 c.X = c.Y = 0; 839 840 /* Write using hConOutNew... */ 841 SetConsoleCursorPosition(hConOutNew, c); 842 ret = WriteConsoleA(hConOutNew, test_str2, lstrlenA(test_str2), &len, NULL); 843 ok (ret && len == lstrlenA(test_str2), "WriteConsoleA failed\n"); 844 /* ... and read it back via hConOutRW */ 845 ret = ReadConsoleOutputCharacterA(hConOutRW, str_buf, lstrlenA(test_str2), c, &len); 846 ok(ret && len == lstrlenA(test_str2), "ReadConsoleOutputCharacterA failed\n"); 847 str_buf[lstrlenA(test_str2)] = 0; 848 ok(!lstrcmpA(str_buf, test_str2), "got '%s' expected '%s'\n", str_buf, test_str2); 849 850 851 /* Now test output codepage handling. Current is 866 as we set earlier. */ 852 SetConsoleCursorPosition(hConOutRW, c); 853 ret = WriteConsoleA(hConOutRW, test_cp866, lstrlenA(test_cp866), &len, NULL); 854 ok(ret && len == lstrlenA(test_cp866), "WriteConsoleA failed\n"); 855 ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp866), c, &len); 856 ok(ret && len == lstrlenA(test_cp866), "ReadConsoleOutputCharacterW failed\n"); 857 str_wbuf[lstrlenA(test_cp866)] = 0; 858 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n"); 859 860 /* 861 * cp866 is OK, let's switch to cp1251. 862 * We expect that this codepage will be used in every SB - active and not. 863 */ 864 ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n"); 865 SetConsoleCursorPosition(hConOutRW, c); 866 ret = WriteConsoleA(hConOutRW, test_cp1251, lstrlenA(test_cp1251), &len, NULL); 867 ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n"); 868 ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp1251), c, &len); 869 ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n"); 870 str_wbuf[lstrlenA(test_cp1251)] = 0; 871 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n"); 872 873 /* Check what has happened to hConOut. */ 874 SetConsoleCursorPosition(hConOut, c); 875 ret = WriteConsoleA(hConOut, test_cp1251, lstrlenA(test_cp1251), &len, NULL); 876 ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n"); 877 ret = ReadConsoleOutputCharacterW(hConOut, str_wbuf, lstrlenA(test_cp1251), c, &len); 878 ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n"); 879 str_wbuf[lstrlenA(test_cp1251)] = 0; 880 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n"); 881 882 /* Close all handles of current console SB */ 883 CloseHandle(hConOutNew); 884 CloseHandle(hConOutRW); 885 886 /* Now active SB should be hConOut */ 887 hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, 888 NULL, OPEN_EXISTING, 0, 0); 889 ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n"); 890 891 /* Write using hConOutNew... */ 892 SetConsoleCursorPosition(hConOutNew, c); 893 ret = WriteConsoleA(hConOutNew, test_str1, lstrlenA(test_str1), &len, NULL); 894 ok (ret && len == lstrlenA(test_str1), "WriteConsoleA failed\n"); 895 /* ... and read it back via hConOut */ 896 ret = ReadConsoleOutputCharacterA(hConOut, str_buf, lstrlenA(test_str1), c, &len); 897 ok(ret && len == lstrlenA(test_str1), "ReadConsoleOutputCharacterA failed\n"); 898 str_buf[lstrlenA(test_str1)] = 0; 899 todo_wine ok(!lstrcmpA(str_buf, test_str1), "got '%s' expected '%s'\n", str_buf, test_str1); 900 CloseHandle(hConOutNew); 901 902 /* This is not really needed under Windows */ 903 SetConsoleActiveScreenBuffer(hConOut); 904 905 /* restore codepage */ 906 SetConsoleOutputCP(oldcp); 907 } 908 909 static void CALLBACK signaled_function(void *p, BOOLEAN timeout) 910 { 911 HANDLE event = p; 912 SetEvent(event); 913 ok(!timeout, "wait shouldn't have timed out\n"); 914 } 915 916 static void testWaitForConsoleInput(HANDLE input_handle) 917 { 918 HANDLE wait_handle; 919 HANDLE complete_event; 920 INPUT_RECORD record; 921 DWORD events_written; 922 DWORD wait_ret; 923 BOOL ret; 924 925 complete_event = CreateEventW(NULL, FALSE, FALSE, NULL); 926 927 /* Test success case */ 928 ret = RegisterWaitForSingleObject(&wait_handle, input_handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE); 929 ok(ret == TRUE, "Expected RegisterWaitForSingleObject to return TRUE, got %d\n", ret); 930 /* give worker thread a chance to start up */ 931 Sleep(100); 932 record.EventType = KEY_EVENT; 933 record.Event.KeyEvent.bKeyDown = 1; 934 record.Event.KeyEvent.wRepeatCount = 1; 935 record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN; 936 record.Event.KeyEvent.wVirtualScanCode = VK_RETURN; 937 record.Event.KeyEvent.uChar.UnicodeChar = '\r'; 938 record.Event.KeyEvent.dwControlKeyState = 0; 939 ret = WriteConsoleInputW(input_handle, &record, 1, &events_written); 940 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 941 wait_ret = WaitForSingleObject(complete_event, INFINITE); 942 ok(wait_ret == WAIT_OBJECT_0, "Expected the handle to be signaled\n"); 943 ret = UnregisterWait(wait_handle); 944 /* If the callback is still running, this fails with ERROR_IO_PENDING, but 945 that's ok and expected. */ 946 ok(ret != 0 || GetLastError() == ERROR_IO_PENDING, 947 "UnregisterWait failed with error %d\n", GetLastError()); 948 949 /* Test timeout case */ 950 FlushConsoleInputBuffer(input_handle); 951 ret = RegisterWaitForSingleObject(&wait_handle, input_handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE); 952 wait_ret = WaitForSingleObject(complete_event, 100); 953 ok(wait_ret == WAIT_TIMEOUT, "Expected the wait to time out\n"); 954 ret = UnregisterWait(wait_handle); 955 ok(ret, "UnregisterWait failed with error %d\n", GetLastError()); 956 957 /* Clean up */ 958 CloseHandle(complete_event); 959 } 960 961 static void test_GetSetConsoleInputExeName(void) 962 { 963 BOOL ret; 964 DWORD error; 965 char buffer[MAX_PATH], module[MAX_PATH], *p; 966 static char input_exe[MAX_PATH] = "winetest.exe"; 967 968 SetLastError(0xdeadbeef); 969 ret = pGetConsoleInputExeNameA(0, NULL); 970 error = GetLastError(); 971 ok(ret, "GetConsoleInputExeNameA failed\n"); 972 ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error); 973 974 SetLastError(0xdeadbeef); 975 ret = pGetConsoleInputExeNameA(0, buffer); 976 error = GetLastError(); 977 ok(ret, "GetConsoleInputExeNameA failed\n"); 978 ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error); 979 980 GetModuleFileNameA(GetModuleHandleA(NULL), module, sizeof(module)); 981 p = strrchr(module, '\\') + 1; 982 983 ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer); 984 ok(ret, "GetConsoleInputExeNameA failed\n"); 985 todo_wine ok(!lstrcmpA(buffer, p), "got %s expected %s\n", buffer, p); 986 987 SetLastError(0xdeadbeef); 988 ret = pSetConsoleInputExeNameA(NULL); 989 error = GetLastError(); 990 ok(!ret, "SetConsoleInputExeNameA failed\n"); 991 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error); 992 993 SetLastError(0xdeadbeef); 994 ret = pSetConsoleInputExeNameA(""); 995 error = GetLastError(); 996 ok(!ret, "SetConsoleInputExeNameA failed\n"); 997 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error); 998 999 ret = pSetConsoleInputExeNameA(input_exe); 1000 ok(ret, "SetConsoleInputExeNameA failed\n"); 1001 1002 ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer); 1003 ok(ret, "GetConsoleInputExeNameA failed\n"); 1004 ok(!lstrcmpA(buffer, input_exe), "got %s expected %s\n", buffer, input_exe); 1005 } 1006 1007 static void test_GetConsoleProcessList(void) 1008 { 1009 DWORD ret, *list = NULL; 1010 1011 if (!pGetConsoleProcessList) 1012 { 1013 win_skip("GetConsoleProcessList is not available\n"); 1014 return; 1015 } 1016 1017 SetLastError(0xdeadbeef); 1018 ret = pGetConsoleProcessList(NULL, 0); 1019 ok(ret == 0, "Expected failure\n"); 1020 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1021 "Expected ERROR_INVALID_PARAMETER, got %d\n", 1022 GetLastError()); 1023 1024 SetLastError(0xdeadbeef); 1025 ret = pGetConsoleProcessList(NULL, 1); 1026 ok(ret == 0, "Expected failure\n"); 1027 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1028 "Expected ERROR_INVALID_PARAMETER, got %d\n", 1029 GetLastError()); 1030 1031 /* We should only have 1 process but only for these specific unit tests as 1032 * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would 1033 * give us two processes for example. 1034 */ 1035 list = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD)); 1036 1037 SetLastError(0xdeadbeef); 1038 ret = pGetConsoleProcessList(list, 0); 1039 ok(ret == 0, "Expected failure\n"); 1040 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1041 "Expected ERROR_INVALID_PARAMETER, got %d\n", 1042 GetLastError()); 1043 1044 SetLastError(0xdeadbeef); 1045 ret = pGetConsoleProcessList(list, 1); 1046 todo_wine 1047 ok(ret == 1, "Expected 1, got %d\n", ret); 1048 1049 HeapFree(GetProcessHeap(), 0, list); 1050 1051 list = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(DWORD)); 1052 1053 SetLastError(0xdeadbeef); 1054 ret = pGetConsoleProcessList(list, ret); 1055 todo_wine 1056 ok(ret == 1, "Expected 1, got %d\n", ret); 1057 1058 if (ret == 1) 1059 { 1060 DWORD pid = GetCurrentProcessId(); 1061 ok(list[0] == pid, "Expected %d, got %d\n", pid, list[0]); 1062 } 1063 1064 HeapFree(GetProcessHeap(), 0, list); 1065 } 1066 1067 static void test_OpenCON(void) 1068 { 1069 static const WCHAR conW[] = {'C','O','N',0}; 1070 static const DWORD accesses[] = {CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING, 1071 OPEN_ALWAYS, TRUNCATE_EXISTING}; 1072 unsigned i; 1073 HANDLE h; 1074 1075 for (i = 0; i < sizeof(accesses) / sizeof(accesses[0]); i++) 1076 { 1077 h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL); 1078 ok(h != INVALID_HANDLE_VALUE || broken(accesses[i] == TRUNCATE_EXISTING /* Win8 */), 1079 "Expected to open the CON device on write (%x)\n", accesses[i]); 1080 CloseHandle(h); 1081 1082 h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL); 1083 /* Windows versions differ here: 1084 * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE 1085 * NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING 1086 * So don't test when disposition is TRUNCATE_EXISTING 1087 */ 1088 ok(h != INVALID_HANDLE_VALUE || broken(accesses[i] == TRUNCATE_EXISTING /* Win7+ */), 1089 "Expected to open the CON device on read (%x)\n", accesses[i]); 1090 CloseHandle(h); 1091 h = CreateFileW(conW, GENERIC_READ|GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL); 1092 ok(h == INVALID_HANDLE_VALUE, "Expected not to open the CON device on read-write (%x)\n", accesses[i]); 1093 ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_PARAMETER, 1094 "Unexpected error %x\n", GetLastError()); 1095 } 1096 } 1097 1098 static void test_OpenConsoleW(void) 1099 { 1100 static const WCHAR coninW[] = {'C','O','N','I','N','$',0}; 1101 static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0}; 1102 static const WCHAR emptyW[] = {0}; 1103 static const WCHAR invalidW[] = {'I','N','V','A','L','I','D',0}; 1104 DWORD gle; 1105 1106 static const struct 1107 { 1108 LPCWSTR name; 1109 DWORD access; 1110 BOOL inherit; 1111 DWORD creation; 1112 DWORD gle, gle2; 1113 } invalid_table[] = { 1114 {NULL, 0, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1115 {NULL, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1116 {NULL, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1117 {NULL, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1118 {NULL, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1119 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1120 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1121 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1122 {emptyW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1123 {emptyW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1124 {emptyW, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1125 {emptyW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1126 {emptyW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1127 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1128 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1129 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND}, 1130 {invalidW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND}, 1131 {invalidW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0}, 1132 {invalidW, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND}, 1133 {invalidW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0}, 1134 {invalidW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND}, 1135 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND}, 1136 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND}, 1137 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND}, 1138 {coninW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0}, 1139 {coninW, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED}, 1140 {coninW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0}, 1141 {conoutW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0}, 1142 {conoutW, 0xceadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED}, 1143 {conoutW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0}, 1144 }; 1145 static const struct 1146 { 1147 LPCWSTR name; 1148 DWORD access; 1149 BOOL inherit; 1150 DWORD creation; 1151 } valid_table[] = { 1152 {coninW, 0, FALSE, 0 }, 1153 {coninW, 0, TRUE, 0 }, 1154 {coninW, GENERIC_EXECUTE, TRUE, 0 }, 1155 {coninW, GENERIC_ALL, TRUE, 0 }, 1156 {coninW, 0, FALSE, OPEN_ALWAYS }, 1157 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, 0 }, 1158 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW }, 1159 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS }, 1160 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS }, 1161 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, TRUNCATE_EXISTING}, 1162 {conoutW, 0, FALSE, 0 }, 1163 {conoutW, 0, FALSE, OPEN_ALWAYS }, 1164 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, 0 }, 1165 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, }, 1166 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS }, 1167 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS }, 1168 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, TRUNCATE_EXISTING}, 1169 }; 1170 1171 int index; 1172 HANDLE ret; 1173 1174 if (!pOpenConsoleW) 1175 { 1176 win_skip("OpenConsoleW is not available\n"); 1177 return; 1178 } 1179 1180 for (index = 0; index < sizeof(invalid_table)/sizeof(invalid_table[0]); index++) 1181 { 1182 SetLastError(0xdeadbeef); 1183 ret = pOpenConsoleW(invalid_table[index].name, invalid_table[index].access, 1184 invalid_table[index].inherit, invalid_table[index].creation); 1185 gle = GetLastError(); 1186 ok(ret == INVALID_HANDLE_VALUE, 1187 "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n", 1188 index, ret); 1189 ok(gle == invalid_table[index].gle || (gle != 0 && gle == invalid_table[index].gle2), 1190 "Expected GetLastError() to return %u/%u for index %d, got %u\n", 1191 invalid_table[index].gle, invalid_table[index].gle2, index, gle); 1192 } 1193 1194 for (index = 0; index < sizeof(valid_table)/sizeof(valid_table[0]); index++) 1195 { 1196 ret = pOpenConsoleW(valid_table[index].name, valid_table[index].access, 1197 valid_table[index].inherit, valid_table[index].creation); 1198 todo_wine 1199 ok(ret != INVALID_HANDLE_VALUE || broken(ret == INVALID_HANDLE_VALUE /* until Win7 */), 1200 "Expected OpenConsoleW to succeed for index %d, got %p\n", index, ret); 1201 if (ret != INVALID_HANDLE_VALUE) 1202 CloseHandle(ret); 1203 } 1204 1205 ret = pOpenConsoleW(coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING); 1206 ok(ret != INVALID_HANDLE_VALUE, "Expected OpenConsoleW to return a valid handle\n"); 1207 if (ret != INVALID_HANDLE_VALUE) 1208 CloseHandle(ret); 1209 1210 ret = pOpenConsoleW(conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING); 1211 ok(ret != INVALID_HANDLE_VALUE, "Expected OpenConsoleW to return a valid handle\n"); 1212 if (ret != INVALID_HANDLE_VALUE) 1213 CloseHandle(ret); 1214 } 1215 1216 static void test_CreateFileW(void) 1217 { 1218 static const WCHAR coninW[] = {'C','O','N','I','N','$',0}; 1219 static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0}; 1220 1221 static const struct 1222 { 1223 LPCWSTR name; 1224 DWORD access; 1225 BOOL inherit; 1226 DWORD creation; 1227 DWORD gle; 1228 BOOL is_broken; 1229 } cf_table[] = { 1230 {coninW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE}, 1231 {coninW, 0, FALSE, OPEN_ALWAYS, 0, FALSE}, 1232 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE}, 1233 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, 0, FALSE}, 1234 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, 0, FALSE}, 1235 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, 0, FALSE}, 1236 {conoutW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE}, 1237 {conoutW, 0, FALSE, OPEN_ALWAYS, 0, FALSE}, 1238 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE}, 1239 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, 0, FALSE}, 1240 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, 0, FALSE}, 1241 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, 0, FALSE}, 1242 /* TRUNCATE_EXISTING is forbidden starting with Windows 8 */ 1243 }; 1244 1245 int index; 1246 HANDLE ret; 1247 SECURITY_ATTRIBUTES sa; 1248 1249 for (index = 0; index < sizeof(cf_table)/sizeof(cf_table[0]); index++) 1250 { 1251 SetLastError(0xdeadbeef); 1252 1253 sa.nLength = sizeof(sa); 1254 sa.lpSecurityDescriptor = NULL; 1255 sa.bInheritHandle = cf_table[index].inherit; 1256 1257 ret = CreateFileW(cf_table[index].name, cf_table[index].access, 1258 FILE_SHARE_READ|FILE_SHARE_WRITE, &sa, 1259 cf_table[index].creation, FILE_ATTRIBUTE_NORMAL, NULL); 1260 if (ret == INVALID_HANDLE_VALUE) 1261 { 1262 ok(cf_table[index].gle, 1263 "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index); 1264 ok(GetLastError() == cf_table[index].gle, 1265 "Expected GetLastError() to return %u for index %d, got %u\n", 1266 cf_table[index].gle, index, GetLastError()); 1267 } 1268 else 1269 { 1270 ok(!cf_table[index].gle || broken(cf_table[index].is_broken) /* Win7 */, 1271 "Expected CreateFileW to succeed for index %d\n", index); 1272 CloseHandle(ret); 1273 } 1274 } 1275 } 1276 1277 static void test_VerifyConsoleIoHandle( HANDLE handle ) 1278 { 1279 BOOL ret; 1280 DWORD error; 1281 1282 if (!pVerifyConsoleIoHandle) 1283 { 1284 win_skip("VerifyConsoleIoHandle is not available\n"); 1285 return; 1286 } 1287 1288 /* invalid handle */ 1289 SetLastError(0xdeadbeef); 1290 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee0); 1291 error = GetLastError(); 1292 ok(!ret, "expected VerifyConsoleIoHandle to fail\n"); 1293 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error); 1294 1295 /* invalid handle + 1 */ 1296 SetLastError(0xdeadbeef); 1297 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee1); 1298 error = GetLastError(); 1299 ok(!ret, "expected VerifyConsoleIoHandle to fail\n"); 1300 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error); 1301 1302 /* invalid handle + 2 */ 1303 SetLastError(0xdeadbeef); 1304 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee2); 1305 error = GetLastError(); 1306 ok(!ret, "expected VerifyConsoleIoHandle to fail\n"); 1307 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error); 1308 1309 /* invalid handle + 3 */ 1310 SetLastError(0xdeadbeef); 1311 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee3); 1312 error = GetLastError(); 1313 ok(!ret, "expected VerifyConsoleIoHandle to fail\n"); 1314 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error); 1315 1316 /* valid handle */ 1317 SetLastError(0xdeadbeef); 1318 ret = pVerifyConsoleIoHandle(handle); 1319 error = GetLastError(); 1320 ok(ret || 1321 broken(!ret), /* Windows 8 and 10 */ 1322 "expected VerifyConsoleIoHandle to succeed\n"); 1323 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error); 1324 } 1325 1326 static void test_GetSetStdHandle(void) 1327 { 1328 HANDLE handle; 1329 DWORD error; 1330 BOOL ret; 1331 1332 /* get invalid std handle */ 1333 SetLastError(0xdeadbeef); 1334 handle = GetStdHandle(42); 1335 error = GetLastError(); 1336 ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */, 1337 "wrong GetLastError() %d\n", error); 1338 ok(handle == INVALID_HANDLE_VALUE, "expected INVALID_HANDLE_VALUE\n"); 1339 1340 /* get valid */ 1341 SetLastError(0xdeadbeef); 1342 handle = GetStdHandle(STD_INPUT_HANDLE); 1343 error = GetLastError(); 1344 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error); 1345 1346 /* set invalid std handle */ 1347 SetLastError(0xdeadbeef); 1348 ret = SetStdHandle(42, handle); 1349 error = GetLastError(); 1350 ok(!ret, "expected SetStdHandle to fail\n"); 1351 ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */, 1352 "wrong GetLastError() %d\n", error); 1353 1354 /* set valid (restore old value) */ 1355 SetLastError(0xdeadbeef); 1356 ret = SetStdHandle(STD_INPUT_HANDLE, handle); 1357 error = GetLastError(); 1358 ok(ret, "expected SetStdHandle to succeed\n"); 1359 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error); 1360 } 1361 1362 static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle) 1363 { 1364 DWORD count; 1365 BOOL ret; 1366 int i; 1367 1368 const struct 1369 { 1370 HANDLE handle; 1371 LPDWORD nrofevents; 1372 DWORD last_error; 1373 } invalid_table[] = 1374 { 1375 {NULL, NULL, ERROR_INVALID_HANDLE}, 1376 {NULL, &count, ERROR_INVALID_HANDLE}, 1377 {INVALID_HANDLE_VALUE, NULL, ERROR_INVALID_HANDLE}, 1378 {INVALID_HANDLE_VALUE, &count, ERROR_INVALID_HANDLE}, 1379 }; 1380 1381 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 1382 { 1383 SetLastError(0xdeadbeef); 1384 if (invalid_table[i].nrofevents) count = 0xdeadbeef; 1385 ret = GetNumberOfConsoleInputEvents(invalid_table[i].handle, 1386 invalid_table[i].nrofevents); 1387 ok(!ret, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i, ret); 1388 if (invalid_table[i].nrofevents) 1389 { 1390 ok(count == 0xdeadbeef, 1391 "[%d] Expected output count to be unmodified, got %u\n", i, count); 1392 } 1393 ok(GetLastError() == invalid_table[i].last_error, 1394 "[%d] Expected last error to be %u, got %u\n", 1395 i, invalid_table[i].last_error, GetLastError()); 1396 } 1397 1398 /* Test crashes on Windows 7. */ 1399 if (0) 1400 { 1401 SetLastError(0xdeadbeef); 1402 ret = GetNumberOfConsoleInputEvents(input_handle, NULL); 1403 ok(!ret, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret); 1404 ok(GetLastError() == ERROR_INVALID_ACCESS, 1405 "Expected last error to be ERROR_INVALID_ACCESS, got %u\n", 1406 GetLastError()); 1407 } 1408 1409 count = 0xdeadbeef; 1410 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1411 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1412 ok(count != 0xdeadbeef, "Expected output count to initialized\n"); 1413 } 1414 1415 static void test_WriteConsoleInputA(HANDLE input_handle) 1416 { 1417 INPUT_RECORD event; 1418 INPUT_RECORD event_list[5]; 1419 MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED }; 1420 KEY_EVENT_RECORD key_event; 1421 DWORD count, console_mode, gle; 1422 BOOL ret; 1423 int i; 1424 1425 const struct 1426 { 1427 HANDLE handle; 1428 const INPUT_RECORD *buffer; 1429 DWORD count; 1430 LPDWORD written; 1431 DWORD gle, gle2; 1432 int win_crash; 1433 } invalid_table[] = 1434 { 1435 {NULL, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1436 {NULL, NULL, 0, &count,ERROR_INVALID_HANDLE}, 1437 {NULL, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1438 {NULL, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS}, 1439 {NULL, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1440 {NULL, &event, 0, &count, ERROR_INVALID_HANDLE}, 1441 {NULL, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1442 {NULL, &event, 1, &count, ERROR_INVALID_HANDLE}, 1443 {INVALID_HANDLE_VALUE, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1444 {INVALID_HANDLE_VALUE, NULL, 0, &count, ERROR_INVALID_HANDLE}, 1445 {INVALID_HANDLE_VALUE, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1446 {INVALID_HANDLE_VALUE, NULL, 1, &count, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS}, 1447 {INVALID_HANDLE_VALUE, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1448 {INVALID_HANDLE_VALUE, &event, 0, &count, ERROR_INVALID_HANDLE}, 1449 {INVALID_HANDLE_VALUE, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1450 {INVALID_HANDLE_VALUE, &event, 1, &count, ERROR_INVALID_HANDLE}, 1451 {input_handle, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1452 {input_handle, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1453 {input_handle, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS}, 1454 {input_handle, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1455 {input_handle, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1456 }; 1457 1458 /* Suppress external sources of input events for the duration of the test. */ 1459 ret = GetConsoleMode(input_handle, &console_mode); 1460 ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret); 1461 if (!ret) 1462 { 1463 skip("GetConsoleMode failed with last error %u\n", GetLastError()); 1464 return; 1465 } 1466 1467 ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT)); 1468 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret); 1469 if (!ret) 1470 { 1471 skip("SetConsoleMode failed with last error %u\n", GetLastError()); 1472 return; 1473 } 1474 1475 /* Discard any events queued before the tests. */ 1476 ret = FlushConsoleInputBuffer(input_handle); 1477 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1478 1479 event.EventType = MOUSE_EVENT; 1480 event.Event.MouseEvent = mouse_event; 1481 1482 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 1483 { 1484 if (invalid_table[i].win_crash) 1485 continue; 1486 1487 SetLastError(0xdeadbeef); 1488 if (invalid_table[i].written) count = 0xdeadbeef; 1489 ret = WriteConsoleInputA(invalid_table[i].handle, 1490 invalid_table[i].buffer, 1491 invalid_table[i].count, 1492 invalid_table[i].written); 1493 ok(!ret, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i, ret); 1494 gle = GetLastError(); 1495 ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2), 1496 "[%d] Expected last error to be %u or %u, got %u\n", 1497 i, invalid_table[i].gle, invalid_table[i].gle2, gle); 1498 } 1499 1500 count = 0xdeadbeef; 1501 ret = WriteConsoleInputA(input_handle, NULL, 0, &count); 1502 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1503 ok(count == 0, "Expected count to be 0, got %u\n", count); 1504 1505 count = 0xdeadbeef; 1506 ret = WriteConsoleInputA(input_handle, &event, 0, &count); 1507 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1508 ok(count == 0, "Expected count to be 0, got %u\n", count); 1509 1510 count = 0xdeadbeef; 1511 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1512 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1513 ok(count == 1, "Expected count to be 1, got %u\n", count); 1514 1515 ret = FlushConsoleInputBuffer(input_handle); 1516 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1517 1518 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */ 1519 event.EventType = MOUSE_EVENT; 1520 event.Event.MouseEvent = mouse_event; 1521 1522 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1523 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1524 ok(count == 1, "Expected count to be 1, got %u\n", count); 1525 1526 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1527 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1528 ok(count == 1, "Expected count to be 1, got %u\n", count); 1529 1530 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1531 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1532 ok(count == 1, "Expected count to be 1, got %u\n", count); 1533 1534 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1535 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1536 todo_wine 1537 ok(count == 1, "Expected count to be 1, got %u\n", count); 1538 1539 ret = FlushConsoleInputBuffer(input_handle); 1540 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1541 1542 for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++) 1543 { 1544 event_list[i].EventType = MOUSE_EVENT; 1545 event_list[i].Event.MouseEvent = mouse_event; 1546 } 1547 1548 /* Writing consecutive chunks of mouse events appears to work. */ 1549 ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count); 1550 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1551 ok(count == sizeof(event_list)/sizeof(event_list[0]), 1552 "Expected count to be event list length, got %u\n", count); 1553 1554 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1555 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1556 ok(count == sizeof(event_list)/sizeof(event_list[0]), 1557 "Expected count to be event list length, got %u\n", count); 1558 1559 ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count); 1560 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1561 ok(count == sizeof(event_list)/sizeof(event_list[0]), 1562 "Expected count to be event list length, got %u\n", count); 1563 1564 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1565 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1566 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]), 1567 "Expected count to be twice event list length, got %u\n", count); 1568 1569 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */ 1570 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1571 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1572 ok(count == 1, "Expected count to be 1, got %u\n", count); 1573 1574 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1575 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1576 todo_wine 1577 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]), 1578 "Expected count to be twice event list length, got %u\n", count); 1579 1580 ret = FlushConsoleInputBuffer(input_handle); 1581 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1582 1583 key_event.bKeyDown = FALSE; 1584 key_event.wRepeatCount = 0; 1585 key_event.wVirtualKeyCode = VK_SPACE; 1586 key_event.wVirtualScanCode = VK_SPACE; 1587 key_event.uChar.AsciiChar = ' '; 1588 key_event.dwControlKeyState = 0; 1589 1590 event.EventType = KEY_EVENT; 1591 event.Event.KeyEvent = key_event; 1592 1593 /* Key events don't exhibit the same behavior as mouse events. */ 1594 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1595 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1596 ok(count == 1, "Expected count to be 1, got %u\n", count); 1597 1598 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1599 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1600 ok(count == 1, "Expected count to be 1, got %u\n", count); 1601 1602 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1603 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1604 ok(count == 1, "Expected count to be 1, got %u\n", count); 1605 1606 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1607 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1608 ok(count == 2, "Expected count to be 2, got %u\n", count); 1609 1610 ret = FlushConsoleInputBuffer(input_handle); 1611 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1612 1613 /* Try interleaving mouse and key events. */ 1614 event.EventType = MOUSE_EVENT; 1615 event.Event.MouseEvent = mouse_event; 1616 1617 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1618 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1619 ok(count == 1, "Expected count to be 1, got %u\n", count); 1620 1621 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1622 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1623 ok(count == 1, "Expected count to be 1, got %u\n", count); 1624 1625 event.EventType = KEY_EVENT; 1626 event.Event.KeyEvent = key_event; 1627 1628 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1629 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1630 ok(count == 1, "Expected count to be 1, got %u\n", count); 1631 1632 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1633 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1634 ok(count == 2, "Expected count to be 2, got %u\n", count); 1635 1636 event.EventType = MOUSE_EVENT; 1637 event.Event.MouseEvent = mouse_event; 1638 1639 ret = WriteConsoleInputA(input_handle, &event, 1, &count); 1640 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret); 1641 ok(count == 1, "Expected count to be 1, got %u\n", count); 1642 1643 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1644 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1645 ok(count == 3, "Expected count to be 3, got %u\n", count); 1646 1647 /* Restore the old console mode. */ 1648 ret = SetConsoleMode(input_handle, console_mode); 1649 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret); 1650 } 1651 1652 static void test_WriteConsoleInputW(HANDLE input_handle) 1653 { 1654 INPUT_RECORD event; 1655 INPUT_RECORD event_list[5]; 1656 MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED }; 1657 KEY_EVENT_RECORD key_event; 1658 DWORD count, console_mode, gle; 1659 BOOL ret; 1660 int i; 1661 1662 const struct 1663 { 1664 HANDLE handle; 1665 const INPUT_RECORD *buffer; 1666 DWORD count; 1667 LPDWORD written; 1668 DWORD gle, gle2; 1669 int win_crash; 1670 } invalid_table[] = 1671 { 1672 {NULL, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1673 {NULL, NULL, 0, &count, ERROR_INVALID_HANDLE}, 1674 {NULL, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1675 {NULL, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS}, 1676 {NULL, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1677 {NULL, &event, 0, &count, ERROR_INVALID_HANDLE}, 1678 {NULL, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1679 {NULL, &event, 1, &count, ERROR_INVALID_HANDLE}, 1680 {INVALID_HANDLE_VALUE, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1681 {INVALID_HANDLE_VALUE, NULL, 0, &count, ERROR_INVALID_HANDLE}, 1682 {INVALID_HANDLE_VALUE, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1683 {INVALID_HANDLE_VALUE, NULL, 1, &count, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS}, 1684 {INVALID_HANDLE_VALUE, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1685 {INVALID_HANDLE_VALUE, &event, 0, &count, ERROR_INVALID_HANDLE}, 1686 {INVALID_HANDLE_VALUE, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1687 {INVALID_HANDLE_VALUE, &event, 1, &count, ERROR_INVALID_HANDLE}, 1688 {input_handle, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1689 {input_handle, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1690 {input_handle, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS}, 1691 {input_handle, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1692 {input_handle, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1}, 1693 }; 1694 1695 /* Suppress external sources of input events for the duration of the test. */ 1696 ret = GetConsoleMode(input_handle, &console_mode); 1697 ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret); 1698 if (!ret) 1699 { 1700 skip("GetConsoleMode failed with last error %u\n", GetLastError()); 1701 return; 1702 } 1703 1704 ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT)); 1705 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret); 1706 if (!ret) 1707 { 1708 skip("SetConsoleMode failed with last error %u\n", GetLastError()); 1709 return; 1710 } 1711 1712 /* Discard any events queued before the tests. */ 1713 ret = FlushConsoleInputBuffer(input_handle); 1714 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1715 1716 event.EventType = MOUSE_EVENT; 1717 event.Event.MouseEvent = mouse_event; 1718 1719 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 1720 { 1721 if (invalid_table[i].win_crash) 1722 continue; 1723 1724 SetLastError(0xdeadbeef); 1725 if (invalid_table[i].written) count = 0xdeadbeef; 1726 ret = WriteConsoleInputW(invalid_table[i].handle, 1727 invalid_table[i].buffer, 1728 invalid_table[i].count, 1729 invalid_table[i].written); 1730 ok(!ret, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i, ret); 1731 gle = GetLastError(); 1732 ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2), 1733 "[%d] Expected last error to be %u or %u, got %u\n", 1734 i, invalid_table[i].gle, invalid_table[i].gle2, gle); 1735 } 1736 1737 count = 0xdeadbeef; 1738 ret = WriteConsoleInputW(input_handle, NULL, 0, &count); 1739 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1740 ok(count == 0, "Expected count to be 0, got %u\n", count); 1741 1742 count = 0xdeadbeef; 1743 ret = WriteConsoleInputW(input_handle, &event, 0, &count); 1744 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1745 ok(count == 0, "Expected count to be 0, got %u\n", count); 1746 1747 count = 0xdeadbeef; 1748 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1749 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1750 ok(count == 1, "Expected count to be 1, got %u\n", count); 1751 1752 ret = FlushConsoleInputBuffer(input_handle); 1753 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1754 1755 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */ 1756 event.EventType = MOUSE_EVENT; 1757 event.Event.MouseEvent = mouse_event; 1758 1759 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1760 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1761 ok(count == 1, "Expected count to be 1, got %u\n", count); 1762 1763 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1764 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1765 ok(count == 1, "Expected count to be 1, got %u\n", count); 1766 1767 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1768 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1769 ok(count == 1, "Expected count to be 1, got %u\n", count); 1770 1771 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1772 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1773 todo_wine 1774 ok(count == 1, "Expected count to be 1, got %u\n", count); 1775 1776 ret = FlushConsoleInputBuffer(input_handle); 1777 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1778 1779 for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++) 1780 { 1781 event_list[i].EventType = MOUSE_EVENT; 1782 event_list[i].Event.MouseEvent = mouse_event; 1783 } 1784 1785 /* Writing consecutive chunks of mouse events appears to work. */ 1786 ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count); 1787 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1788 ok(count == sizeof(event_list)/sizeof(event_list[0]), 1789 "Expected count to be event list length, got %u\n", count); 1790 1791 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1792 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1793 ok(count == sizeof(event_list)/sizeof(event_list[0]), 1794 "Expected count to be event list length, got %u\n", count); 1795 1796 ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count); 1797 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1798 ok(count == sizeof(event_list)/sizeof(event_list[0]), 1799 "Expected count to be event list length, got %u\n", count); 1800 1801 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1802 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1803 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]), 1804 "Expected count to be twice event list length, got %u\n", count); 1805 1806 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */ 1807 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1808 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1809 ok(count == 1, "Expected count to be 1, got %u\n", count); 1810 1811 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1812 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1813 todo_wine 1814 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]), 1815 "Expected count to be twice event list length, got %u\n", count); 1816 1817 ret = FlushConsoleInputBuffer(input_handle); 1818 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1819 1820 key_event.bKeyDown = FALSE; 1821 key_event.wRepeatCount = 0; 1822 key_event.wVirtualKeyCode = VK_SPACE; 1823 key_event.wVirtualScanCode = VK_SPACE; 1824 key_event.uChar.UnicodeChar = ' '; 1825 key_event.dwControlKeyState = 0; 1826 1827 event.EventType = KEY_EVENT; 1828 event.Event.KeyEvent = key_event; 1829 1830 /* Key events don't exhibit the same behavior as mouse events. */ 1831 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1832 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1833 ok(count == 1, "Expected count to be 1, got %u\n", count); 1834 1835 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1836 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1837 ok(count == 1, "Expected count to be 1, got %u\n", count); 1838 1839 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1840 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1841 ok(count == 1, "Expected count to be 1, got %u\n", count); 1842 1843 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1844 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1845 ok(count == 2, "Expected count to be 2, got %u\n", count); 1846 1847 ret = FlushConsoleInputBuffer(input_handle); 1848 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret); 1849 1850 /* Try interleaving mouse and key events. */ 1851 event.EventType = MOUSE_EVENT; 1852 event.Event.MouseEvent = mouse_event; 1853 1854 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1855 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1856 ok(count == 1, "Expected count to be 1, got %u\n", count); 1857 1858 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1859 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1860 ok(count == 1, "Expected count to be 1, got %u\n", count); 1861 1862 event.EventType = KEY_EVENT; 1863 event.Event.KeyEvent = key_event; 1864 1865 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1866 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1867 ok(count == 1, "Expected count to be 1, got %u\n", count); 1868 1869 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1870 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1871 ok(count == 2, "Expected count to be 2, got %u\n", count); 1872 1873 event.EventType = MOUSE_EVENT; 1874 event.Event.MouseEvent = mouse_event; 1875 1876 ret = WriteConsoleInputW(input_handle, &event, 1, &count); 1877 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret); 1878 ok(count == 1, "Expected count to be 1, got %u\n", count); 1879 1880 ret = GetNumberOfConsoleInputEvents(input_handle, &count); 1881 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret); 1882 ok(count == 3, "Expected count to be 3, got %u\n", count); 1883 1884 /* Restore the old console mode. */ 1885 ret = SetConsoleMode(input_handle, console_mode); 1886 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret); 1887 } 1888 1889 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle) 1890 { 1891 static const char output[] = {'a', 0}; 1892 1893 COORD origin = {0, 0}; 1894 DWORD count; 1895 BOOL ret; 1896 int i; 1897 1898 const struct 1899 { 1900 HANDLE hConsoleOutput; 1901 LPCSTR str; 1902 DWORD length; 1903 COORD coord; 1904 LPDWORD lpNumCharsWritten; 1905 DWORD expected_count; 1906 DWORD last_error; 1907 int win7_crash; 1908 } invalid_table[] = 1909 { 1910 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1911 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 1912 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1913 {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1914 {NULL, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1915 {NULL, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 1916 {NULL, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1917 {NULL, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 1918 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1919 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 1920 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1921 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1922 {INVALID_HANDLE_VALUE, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1923 {INVALID_HANDLE_VALUE, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 1924 {INVALID_HANDLE_VALUE, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1925 {INVALID_HANDLE_VALUE, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 1926 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1927 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1928 {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1929 {output_handle, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1930 {output_handle, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1931 }; 1932 1933 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 1934 { 1935 if (invalid_table[i].win7_crash) 1936 continue; 1937 1938 SetLastError(0xdeadbeef); 1939 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef; 1940 ret = WriteConsoleOutputCharacterA(invalid_table[i].hConsoleOutput, 1941 invalid_table[i].str, 1942 invalid_table[i].length, 1943 invalid_table[i].coord, 1944 invalid_table[i].lpNumCharsWritten); 1945 ok(!ret, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i, ret); 1946 if (invalid_table[i].lpNumCharsWritten) 1947 { 1948 ok(count == invalid_table[i].expected_count, 1949 "[%d] Expected count to be %u, got %u\n", 1950 i, invalid_table[i].expected_count, count); 1951 } 1952 ok(GetLastError() == invalid_table[i].last_error, 1953 "[%d] Expected last error to be %u, got %u\n", 1954 i, invalid_table[i].last_error, GetLastError()); 1955 } 1956 1957 count = 0xdeadbeef; 1958 ret = WriteConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count); 1959 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret); 1960 ok(count == 0, "Expected count to be 0, got %u\n", count); 1961 1962 count = 0xdeadbeef; 1963 ret = WriteConsoleOutputCharacterA(output_handle, output, 0, origin, &count); 1964 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret); 1965 ok(count == 0, "Expected count to be 0, got %u\n", count); 1966 1967 count = 0xdeadbeef; 1968 ret = WriteConsoleOutputCharacterA(output_handle, output, 1, origin, &count); 1969 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret); 1970 ok(count == 1, "Expected count to be 1, got %u\n", count); 1971 } 1972 1973 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle) 1974 { 1975 static const WCHAR outputW[] = {'a',0}; 1976 1977 COORD origin = {0, 0}; 1978 DWORD count; 1979 BOOL ret; 1980 int i; 1981 1982 const struct 1983 { 1984 HANDLE hConsoleOutput; 1985 LPCWSTR str; 1986 DWORD length; 1987 COORD coord; 1988 LPDWORD lpNumCharsWritten; 1989 DWORD expected_count; 1990 DWORD last_error; 1991 int win7_crash; 1992 } invalid_table[] = 1993 { 1994 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1995 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 1996 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1997 {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1998 {NULL, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 1999 {NULL, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2000 {NULL, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2001 {NULL, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2002 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2003 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2004 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2005 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2006 {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2007 {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2008 {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2009 {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2010 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2011 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2012 {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2013 {output_handle, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2014 {output_handle, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2015 }; 2016 2017 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 2018 { 2019 if (invalid_table[i].win7_crash) 2020 continue; 2021 2022 SetLastError(0xdeadbeef); 2023 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef; 2024 ret = WriteConsoleOutputCharacterW(invalid_table[i].hConsoleOutput, 2025 invalid_table[i].str, 2026 invalid_table[i].length, 2027 invalid_table[i].coord, 2028 invalid_table[i].lpNumCharsWritten); 2029 ok(!ret, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i, ret); 2030 if (invalid_table[i].lpNumCharsWritten) 2031 { 2032 ok(count == invalid_table[i].expected_count, 2033 "[%d] Expected count to be %u, got %u\n", 2034 i, invalid_table[i].expected_count, count); 2035 } 2036 ok(GetLastError() == invalid_table[i].last_error, 2037 "[%d] Expected last error to be %u, got %u\n", 2038 i, invalid_table[i].last_error, GetLastError()); 2039 } 2040 2041 count = 0xdeadbeef; 2042 ret = WriteConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count); 2043 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret); 2044 ok(count == 0, "Expected count to be 0, got %u\n", count); 2045 2046 count = 0xdeadbeef; 2047 ret = WriteConsoleOutputCharacterW(output_handle, outputW, 0, origin, &count); 2048 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret); 2049 ok(count == 0, "Expected count to be 0, got %u\n", count); 2050 2051 count = 0xdeadbeef; 2052 ret = WriteConsoleOutputCharacterW(output_handle, outputW, 1, origin, &count); 2053 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret); 2054 ok(count == 1, "Expected count to be 1, got %u\n", count); 2055 } 2056 2057 static void test_WriteConsoleOutputAttribute(HANDLE output_handle) 2058 { 2059 WORD attr = FOREGROUND_BLUE; 2060 COORD origin = {0, 0}; 2061 DWORD count; 2062 BOOL ret; 2063 int i; 2064 2065 const struct 2066 { 2067 HANDLE hConsoleOutput; 2068 const WORD *attr; 2069 DWORD length; 2070 COORD coord; 2071 LPDWORD lpNumAttrsWritten; 2072 DWORD expected_count; 2073 DWORD last_error; 2074 int win7_crash; 2075 } invalid_table[] = 2076 { 2077 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2078 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2079 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2080 {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2081 {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2082 {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2083 {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2084 {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2085 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2086 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2087 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2088 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2089 {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2090 {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2091 {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2092 {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2093 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2094 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2095 {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2096 {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2097 {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2098 }; 2099 2100 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 2101 { 2102 if (invalid_table[i].win7_crash) 2103 continue; 2104 2105 SetLastError(0xdeadbeef); 2106 if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef; 2107 ret = WriteConsoleOutputAttribute(invalid_table[i].hConsoleOutput, 2108 invalid_table[i].attr, 2109 invalid_table[i].length, 2110 invalid_table[i].coord, 2111 invalid_table[i].lpNumAttrsWritten); 2112 ok(!ret, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i, ret); 2113 if (invalid_table[i].lpNumAttrsWritten) 2114 { 2115 ok(count == invalid_table[i].expected_count, 2116 "[%d] Expected count to be %u, got %u\n", 2117 i, invalid_table[i].expected_count, count); 2118 } 2119 ok(GetLastError() == invalid_table[i].last_error, 2120 "[%d] Expected last error to be %u, got %u\n", 2121 i, invalid_table[i].last_error, GetLastError()); 2122 } 2123 2124 count = 0xdeadbeef; 2125 ret = WriteConsoleOutputAttribute(output_handle, NULL, 0, origin, &count); 2126 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret); 2127 ok(count == 0, "Expected count to be 0, got %u\n", count); 2128 2129 count = 0xdeadbeef; 2130 ret = WriteConsoleOutputAttribute(output_handle, &attr, 0, origin, &count); 2131 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret); 2132 ok(count == 0, "Expected count to be 0, got %u\n", count); 2133 2134 count = 0xdeadbeef; 2135 ret = WriteConsoleOutputAttribute(output_handle, &attr, 1, origin, &count); 2136 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret); 2137 ok(count == 1, "Expected count to be 1, got %u\n", count); 2138 } 2139 2140 static void test_FillConsoleOutputCharacterA(HANDLE output_handle) 2141 { 2142 COORD origin = {0, 0}; 2143 DWORD count; 2144 BOOL ret; 2145 int i; 2146 2147 const struct 2148 { 2149 HANDLE hConsoleOutput; 2150 CHAR ch; 2151 DWORD length; 2152 COORD coord; 2153 LPDWORD lpNumCharsWritten; 2154 DWORD last_error; 2155 int win7_crash; 2156 } invalid_table[] = 2157 { 2158 {NULL, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2159 {NULL, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2160 {NULL, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2161 {NULL, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2162 {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2163 {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2164 {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2165 {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2166 {output_handle, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2167 {output_handle, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2168 }; 2169 2170 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 2171 { 2172 if (invalid_table[i].win7_crash) 2173 continue; 2174 2175 SetLastError(0xdeadbeef); 2176 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef; 2177 ret = FillConsoleOutputCharacterA(invalid_table[i].hConsoleOutput, 2178 invalid_table[i].ch, 2179 invalid_table[i].length, 2180 invalid_table[i].coord, 2181 invalid_table[i].lpNumCharsWritten); 2182 ok(!ret, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i, ret); 2183 ok(GetLastError() == invalid_table[i].last_error, 2184 "[%d] Expected last error to be %u, got %u\n", 2185 i, invalid_table[i].last_error, GetLastError()); 2186 } 2187 2188 count = 0xdeadbeef; 2189 ret = FillConsoleOutputCharacterA(output_handle, 'a', 0, origin, &count); 2190 ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret); 2191 ok(count == 0, "Expected count to be 0, got %u\n", count); 2192 2193 count = 0xdeadbeef; 2194 ret = FillConsoleOutputCharacterA(output_handle, 'a', 1, origin, &count); 2195 ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret); 2196 ok(count == 1, "Expected count to be 1, got %u\n", count); 2197 } 2198 2199 static void test_FillConsoleOutputCharacterW(HANDLE output_handle) 2200 { 2201 COORD origin = {0, 0}; 2202 DWORD count; 2203 BOOL ret; 2204 int i; 2205 2206 const struct 2207 { 2208 HANDLE hConsoleOutput; 2209 WCHAR ch; 2210 DWORD length; 2211 COORD coord; 2212 LPDWORD lpNumCharsWritten; 2213 DWORD last_error; 2214 int win7_crash; 2215 } invalid_table[] = 2216 { 2217 {NULL, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2218 {NULL, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2219 {NULL, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2220 {NULL, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2221 {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2222 {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2223 {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2224 {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2225 {output_handle, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2226 {output_handle, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2227 }; 2228 2229 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 2230 { 2231 if (invalid_table[i].win7_crash) 2232 continue; 2233 2234 SetLastError(0xdeadbeef); 2235 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef; 2236 ret = FillConsoleOutputCharacterW(invalid_table[i].hConsoleOutput, 2237 invalid_table[i].ch, 2238 invalid_table[i].length, 2239 invalid_table[i].coord, 2240 invalid_table[i].lpNumCharsWritten); 2241 ok(!ret, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i, ret); 2242 ok(GetLastError() == invalid_table[i].last_error, 2243 "[%d] Expected last error to be %u, got %u\n", 2244 i, invalid_table[i].last_error, GetLastError()); 2245 } 2246 2247 count = 0xdeadbeef; 2248 ret = FillConsoleOutputCharacterW(output_handle, 'a', 0, origin, &count); 2249 ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret); 2250 ok(count == 0, "Expected count to be 0, got %u\n", count); 2251 2252 count = 0xdeadbeef; 2253 ret = FillConsoleOutputCharacterW(output_handle, 'a', 1, origin, &count); 2254 ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret); 2255 ok(count == 1, "Expected count to be 1, got %u\n", count); 2256 } 2257 2258 static void test_FillConsoleOutputAttribute(HANDLE output_handle) 2259 { 2260 COORD origin = {0, 0}; 2261 DWORD count; 2262 BOOL ret; 2263 int i; 2264 2265 const struct 2266 { 2267 HANDLE hConsoleOutput; 2268 WORD attr; 2269 DWORD length; 2270 COORD coord; 2271 LPDWORD lpNumAttrsWritten; 2272 DWORD last_error; 2273 int win7_crash; 2274 } invalid_table[] = 2275 { 2276 {NULL, FOREGROUND_BLUE, 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2277 {NULL, FOREGROUND_BLUE, 0, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2278 {NULL, FOREGROUND_BLUE, 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2279 {NULL, FOREGROUND_BLUE, 1, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2280 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2281 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2282 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2283 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, &count, ERROR_INVALID_HANDLE}, 2284 {output_handle, FOREGROUND_BLUE, 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2285 {output_handle, FOREGROUND_BLUE, 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1}, 2286 }; 2287 2288 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 2289 { 2290 if (invalid_table[i].win7_crash) 2291 continue; 2292 2293 SetLastError(0xdeadbeef); 2294 if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef; 2295 ret = FillConsoleOutputAttribute(invalid_table[i].hConsoleOutput, 2296 invalid_table[i].attr, 2297 invalid_table[i].length, 2298 invalid_table[i].coord, 2299 invalid_table[i].lpNumAttrsWritten); 2300 ok(!ret, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i, ret); 2301 ok(GetLastError() == invalid_table[i].last_error, 2302 "[%d] Expected last error to be %u, got %u\n", 2303 i, invalid_table[i].last_error, GetLastError()); 2304 } 2305 2306 count = 0xdeadbeef; 2307 ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 0, origin, &count); 2308 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret); 2309 ok(count == 0, "Expected count to be 0, got %u\n", count); 2310 2311 count = 0xdeadbeef; 2312 ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 1, origin, &count); 2313 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret); 2314 ok(count == 1, "Expected count to be 1, got %u\n", count); 2315 2316 count = 0xdeadbeef; 2317 ret = FillConsoleOutputAttribute(output_handle, ~0, 1, origin, &count); 2318 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret); 2319 ok(count == 1, "Expected count to be 1, got %u\n", count); 2320 } 2321 2322 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle) 2323 { 2324 CHAR read; 2325 COORD origin = {0, 0}; 2326 DWORD count; 2327 BOOL ret; 2328 int i; 2329 2330 const struct 2331 { 2332 HANDLE hConsoleOutput; 2333 LPSTR lpstr; 2334 DWORD length; 2335 COORD coord; 2336 LPDWORD read_count; 2337 DWORD expected_count; 2338 DWORD last_error; 2339 int win7_crash; 2340 } invalid_table[] = 2341 { 2342 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2343 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2344 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2345 {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1}, 2346 {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2347 {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2348 {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2349 {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2350 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2351 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2352 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2353 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1}, 2354 {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2355 {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2356 {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2357 {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2358 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2359 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2360 {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1}, 2361 {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1}, 2362 {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2363 {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2364 }; 2365 2366 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 2367 { 2368 if (invalid_table[i].win7_crash) 2369 continue; 2370 2371 SetLastError(0xdeadbeef); 2372 if (invalid_table[i].read_count) count = 0xdeadbeef; 2373 ret = ReadConsoleOutputCharacterA(invalid_table[i].hConsoleOutput, 2374 invalid_table[i].lpstr, 2375 invalid_table[i].length, 2376 invalid_table[i].coord, 2377 invalid_table[i].read_count); 2378 ok(!ret, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i, ret); 2379 if (invalid_table[i].read_count) 2380 { 2381 ok(count == invalid_table[i].expected_count, 2382 "[%d] Expected count to be %u, got %u\n", 2383 i, invalid_table[i].expected_count, count); 2384 } 2385 ok(GetLastError() == invalid_table[i].last_error, 2386 "[%d] Expected last error to be %u, got %u\n", 2387 i, invalid_table[i].last_error, GetLastError()); 2388 } 2389 2390 count = 0xdeadbeef; 2391 ret = ReadConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count); 2392 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret); 2393 ok(count == 0, "Expected count to be 0, got %u\n", count); 2394 2395 count = 0xdeadbeef; 2396 ret = ReadConsoleOutputCharacterA(output_handle, &read, 0, origin, &count); 2397 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret); 2398 ok(count == 0, "Expected count to be 0, got %u\n", count); 2399 2400 count = 0xdeadbeef; 2401 ret = ReadConsoleOutputCharacterA(output_handle, &read, 1, origin, &count); 2402 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret); 2403 ok(count == 1, "Expected count to be 1, got %u\n", count); 2404 } 2405 2406 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle) 2407 { 2408 WCHAR read; 2409 COORD origin = {0, 0}; 2410 DWORD count; 2411 BOOL ret; 2412 int i; 2413 2414 const struct 2415 { 2416 HANDLE hConsoleOutput; 2417 LPWSTR buffer; 2418 DWORD length; 2419 COORD coord; 2420 LPDWORD read_count; 2421 DWORD expected_count; 2422 DWORD last_error; 2423 int win7_crash; 2424 } invalid_table[] = 2425 { 2426 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2427 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2428 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2429 {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1}, 2430 {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2431 {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2432 {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2433 {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2434 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2435 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2436 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2437 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1}, 2438 {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2439 {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2440 {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2441 {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2442 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2443 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2444 {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1}, 2445 {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1}, 2446 {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2447 {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2448 }; 2449 2450 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 2451 { 2452 if (invalid_table[i].win7_crash) 2453 continue; 2454 2455 SetLastError(0xdeadbeef); 2456 if (invalid_table[i].read_count) count = 0xdeadbeef; 2457 ret = ReadConsoleOutputCharacterW(invalid_table[i].hConsoleOutput, 2458 invalid_table[i].buffer, 2459 invalid_table[i].length, 2460 invalid_table[i].coord, 2461 invalid_table[i].read_count); 2462 ok(!ret, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i, ret); 2463 if (invalid_table[i].read_count) 2464 { 2465 ok(count == invalid_table[i].expected_count, 2466 "[%d] Expected count to be %u, got %u\n", 2467 i, invalid_table[i].expected_count, count); 2468 } 2469 ok(GetLastError() == invalid_table[i].last_error, 2470 "[%d] Expected last error to be %u, got %u\n", 2471 i, invalid_table[i].last_error, GetLastError()); 2472 } 2473 2474 count = 0xdeadbeef; 2475 ret = ReadConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count); 2476 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret); 2477 ok(count == 0, "Expected count to be 0, got %u\n", count); 2478 2479 count = 0xdeadbeef; 2480 ret = ReadConsoleOutputCharacterW(output_handle, &read, 0, origin, &count); 2481 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret); 2482 ok(count == 0, "Expected count to be 0, got %u\n", count); 2483 2484 count = 0xdeadbeef; 2485 ret = ReadConsoleOutputCharacterW(output_handle, &read, 1, origin, &count); 2486 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret); 2487 ok(count == 1, "Expected count to be 1, got %u\n", count); 2488 } 2489 2490 static void test_ReadConsoleOutputAttribute(HANDLE output_handle) 2491 { 2492 WORD attr; 2493 COORD origin = {0, 0}; 2494 DWORD count; 2495 BOOL ret; 2496 int i; 2497 2498 const struct 2499 { 2500 HANDLE hConsoleOutput; 2501 LPWORD lpAttribute; 2502 DWORD length; 2503 COORD coord; 2504 LPDWORD read_count; 2505 DWORD expected_count; 2506 DWORD last_error; 2507 int win7_crash; 2508 } invalid_table[] = 2509 { 2510 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2511 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2512 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2513 {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1}, 2514 {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2515 {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2516 {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2517 {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2518 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2519 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2520 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2521 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1}, 2522 {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2523 {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2524 {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2525 {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE}, 2526 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2527 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2528 {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1}, 2529 {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2530 {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1}, 2531 }; 2532 2533 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++) 2534 { 2535 if (invalid_table[i].win7_crash) 2536 continue; 2537 2538 SetLastError(0xdeadbeef); 2539 if (invalid_table[i].read_count) count = 0xdeadbeef; 2540 ret = ReadConsoleOutputAttribute(invalid_table[i].hConsoleOutput, 2541 invalid_table[i].lpAttribute, 2542 invalid_table[i].length, 2543 invalid_table[i].coord, 2544 invalid_table[i].read_count); 2545 ok(!ret, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i, ret); 2546 if (invalid_table[i].read_count) 2547 { 2548 ok(count == invalid_table[i].expected_count, 2549 "[%d] Expected count to be %u, got %u\n", 2550 i, invalid_table[i].expected_count, count); 2551 } 2552 ok(GetLastError() == invalid_table[i].last_error, 2553 "[%d] Expected last error to be %u, got %u\n", 2554 i, invalid_table[i].last_error, GetLastError()); 2555 } 2556 2557 count = 0xdeadbeef; 2558 ret = ReadConsoleOutputAttribute(output_handle, NULL, 0, origin, &count); 2559 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret); 2560 ok(count == 0, "Expected count to be 0, got %u\n", count); 2561 2562 count = 0xdeadbeef; 2563 ret = ReadConsoleOutputAttribute(output_handle, &attr, 0, origin, &count); 2564 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret); 2565 ok(count == 0, "Expected count to be 0, got %u\n", count); 2566 2567 count = 0xdeadbeef; 2568 ret = ReadConsoleOutputAttribute(output_handle, &attr, 1, origin, &count); 2569 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret); 2570 ok(count == 1, "Expected count to be 1, got %u\n", count); 2571 } 2572 2573 static void test_ReadConsole(void) 2574 { 2575 HANDLE std_input; 2576 DWORD ret, bytes; 2577 char buf[1024]; 2578 2579 std_input = GetStdHandle(STD_INPUT_HANDLE); 2580 2581 SetLastError(0xdeadbeef); 2582 ret = GetFileSize(std_input, NULL); 2583 ok(ret == INVALID_FILE_SIZE, "expected INVALID_FILE_SIZE, got %#x\n", ret); 2584 ok(GetLastError() == ERROR_INVALID_HANDLE || 2585 GetLastError() == ERROR_INVALID_FUNCTION, /* Win 8, 10 */ 2586 "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 2587 2588 bytes = 0xdeadbeef; 2589 SetLastError(0xdeadbeef); 2590 ret = ReadFile(std_input, buf, -128, &bytes, NULL); 2591 ok(!ret, "expected 0, got %u\n", ret); 2592 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY || 2593 GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */ 2594 "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError()); 2595 ok(!bytes, "expected 0, got %u\n", bytes); 2596 2597 bytes = 0xdeadbeef; 2598 SetLastError(0xdeadbeef); 2599 ret = ReadConsoleA(std_input, buf, -128, &bytes, NULL); 2600 ok(!ret, "expected 0, got %u\n", ret); 2601 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY || 2602 GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */ 2603 "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError()); 2604 ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes); 2605 2606 bytes = 0xdeadbeef; 2607 SetLastError(0xdeadbeef); 2608 ret = ReadConsoleW(std_input, buf, -128, &bytes, NULL); 2609 ok(!ret, "expected 0, got %u\n", ret); 2610 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY || 2611 GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */ 2612 "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError()); 2613 ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes); 2614 } 2615 2616 static void test_GetCurrentConsoleFont(HANDLE std_output) 2617 { 2618 BOOL ret; 2619 CONSOLE_FONT_INFO cfi; 2620 CONSOLE_SCREEN_BUFFER_INFO csbi; 2621 short int width, height; 2622 COORD c; 2623 2624 memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO)); 2625 SetLastError(0xdeadbeef); 2626 ret = GetCurrentConsoleFont(NULL, FALSE, &cfi); 2627 ok(!ret, "got %d, expected 0\n", ret); 2628 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2629 ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X); 2630 ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y); 2631 2632 memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO)); 2633 SetLastError(0xdeadbeef); 2634 ret = GetCurrentConsoleFont(NULL, TRUE, &cfi); 2635 ok(!ret, "got %d, expected 0\n", ret); 2636 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2637 ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X); 2638 ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y); 2639 2640 memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO)); 2641 SetLastError(0xdeadbeef); 2642 ret = GetCurrentConsoleFont(GetStdHandle(STD_INPUT_HANDLE), FALSE, &cfi); 2643 ok(!ret, "got %d, expected 0\n", ret); 2644 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2645 ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X); 2646 ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y); 2647 2648 memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO)); 2649 SetLastError(0xdeadbeef); 2650 ret = GetCurrentConsoleFont(GetStdHandle(STD_INPUT_HANDLE), TRUE, &cfi); 2651 ok(!ret, "got %d, expected 0\n", ret); 2652 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2653 ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X); 2654 ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y); 2655 2656 memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO)); 2657 SetLastError(0xdeadbeef); 2658 ret = GetCurrentConsoleFont(std_output, FALSE, &cfi); 2659 ok(ret, "got %d, expected non-zero\n", ret); 2660 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); 2661 GetConsoleScreenBufferInfo(std_output, &csbi); 2662 width = csbi.srWindow.Right - csbi.srWindow.Left + 1; 2663 height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; 2664 c = GetConsoleFontSize(std_output, cfi.nFont); 2665 ok(cfi.dwFontSize.X == width || cfi.dwFontSize.X == c.X /* Vista and higher */, 2666 "got %d, expected %d\n", cfi.dwFontSize.X, width); 2667 ok(cfi.dwFontSize.Y == height || cfi.dwFontSize.Y == c.Y /* Vista and higher */, 2668 "got %d, expected %d\n", cfi.dwFontSize.Y, height); 2669 2670 memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO)); 2671 SetLastError(0xdeadbeef); 2672 ret = GetCurrentConsoleFont(std_output, TRUE, &cfi); 2673 ok(ret, "got %d, expected non-zero\n", ret); 2674 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); 2675 ok(cfi.dwFontSize.X == csbi.dwMaximumWindowSize.X, 2676 "got %d, expected %d\n", cfi.dwFontSize.X, csbi.dwMaximumWindowSize.X); 2677 ok(cfi.dwFontSize.Y == csbi.dwMaximumWindowSize.Y, 2678 "got %d, expected %d\n", cfi.dwFontSize.Y, csbi.dwMaximumWindowSize.Y); 2679 } 2680 2681 static void test_GetConsoleFontSize(HANDLE std_output) 2682 { 2683 COORD c; 2684 DWORD index = 0; 2685 CONSOLE_FONT_INFO cfi; 2686 RECT r; 2687 CONSOLE_SCREEN_BUFFER_INFO csbi; 2688 LONG font_width, font_height; 2689 HMODULE hmod; 2690 DWORD (WINAPI *pGetNumberOfConsoleFonts)(void); 2691 2692 memset(&c, 10, sizeof(COORD)); 2693 SetLastError(0xdeadbeef); 2694 c = GetConsoleFontSize(NULL, index); 2695 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2696 ok(!c.X, "got %d, expected 0\n", c.X); 2697 ok(!c.Y, "got %d, expected 0\n", c.Y); 2698 2699 memset(&c, 10, sizeof(COORD)); 2700 SetLastError(0xdeadbeef); 2701 c = GetConsoleFontSize(GetStdHandle(STD_INPUT_HANDLE), index); 2702 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2703 ok(!c.X, "got %d, expected 0\n", c.X); 2704 ok(!c.Y, "got %d, expected 0\n", c.Y); 2705 2706 GetCurrentConsoleFont(std_output, FALSE, &cfi); 2707 memset(&c, 10, sizeof(COORD)); 2708 SetLastError(0xdeadbeef); 2709 c = GetConsoleFontSize(std_output, cfi.nFont); 2710 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); 2711 GetClientRect(GetConsoleWindow(), &r); 2712 GetConsoleScreenBufferInfo(std_output, &csbi); 2713 font_width = (r.right - r.left + 1) / csbi.srWindow.Right; 2714 font_height = (r.bottom - r.top + 1) / csbi.srWindow.Bottom; 2715 ok(c.X == font_width, "got %d, expected %d\n", c.X, font_width); 2716 ok(c.Y == font_height, "got %d, expected %d\n", c.Y, font_height); 2717 2718 hmod = GetModuleHandleA("kernel32.dll"); 2719 pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts"); 2720 if (!pGetNumberOfConsoleFonts) 2721 { 2722 win_skip("GetNumberOfConsoleFonts is not available\n"); 2723 return; 2724 } 2725 index = pGetNumberOfConsoleFonts(); 2726 2727 memset(&c, 10, sizeof(COORD)); 2728 SetLastError(0xdeadbeef); 2729 c = GetConsoleFontSize(std_output, index); 2730 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); 2731 ok(!c.X, "got %d, expected 0\n", c.X); 2732 ok(!c.Y, "got %d, expected 0\n", c.Y); 2733 } 2734 2735 static void test_GetLargestConsoleWindowSize(HANDLE std_output) 2736 { 2737 COORD c, font; 2738 RECT r; 2739 LONG workarea_w, workarea_h, maxcon_w, maxcon_h; 2740 CONSOLE_SCREEN_BUFFER_INFO sbi; 2741 CONSOLE_FONT_INFO cfi; 2742 DWORD index, i; 2743 HMODULE hmod; 2744 BOOL ret; 2745 DWORD (WINAPI *pGetNumberOfConsoleFonts)(void); 2746 BOOL (WINAPI *pSetConsoleFont)(HANDLE, DWORD); 2747 2748 memset(&c, 10, sizeof(COORD)); 2749 SetLastError(0xdeadbeef); 2750 c = GetLargestConsoleWindowSize(NULL); 2751 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2752 ok(!c.X, "got %d, expected 0\n", c.X); 2753 ok(!c.Y, "got %d, expected 0\n", c.Y); 2754 2755 memset(&c, 10, sizeof(COORD)); 2756 SetLastError(0xdeadbeef); 2757 c = GetLargestConsoleWindowSize(GetStdHandle(STD_INPUT_HANDLE)); 2758 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2759 ok(!c.X, "got %d, expected 0\n", c.X); 2760 ok(!c.Y, "got %d, expected 0\n", c.Y); 2761 2762 SystemParametersInfoW(SPI_GETWORKAREA, 0, &r, 0); 2763 workarea_w = r.right - r.left; 2764 workarea_h = r.bottom - r.top - GetSystemMetrics(SM_CYCAPTION); 2765 2766 GetCurrentConsoleFont(std_output, FALSE, &cfi); 2767 index = cfi.nFont; /* save current font index */ 2768 2769 hmod = GetModuleHandleA("kernel32.dll"); 2770 pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts"); 2771 if (!pGetNumberOfConsoleFonts) 2772 { 2773 win_skip("GetNumberOfConsoleFonts is not available\n"); 2774 return; 2775 } 2776 pSetConsoleFont = (void *)GetProcAddress(hmod, "SetConsoleFont"); 2777 if (!pSetConsoleFont) 2778 { 2779 win_skip("SetConsoleFont is not available\n"); 2780 return; 2781 } 2782 2783 for (i = 0; i < pGetNumberOfConsoleFonts(); i++) 2784 { 2785 pSetConsoleFont(std_output, i); 2786 memset(&c, 10, sizeof(COORD)); 2787 SetLastError(0xdeadbeef); 2788 c = GetLargestConsoleWindowSize(std_output); 2789 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); 2790 GetCurrentConsoleFont(std_output, FALSE, &cfi); 2791 font = GetConsoleFontSize(std_output, cfi.nFont); 2792 maxcon_w = workarea_w / font.X; 2793 maxcon_h = workarea_h / font.Y; 2794 ok(c.X == maxcon_w || c.X == maxcon_w - 1 /* Win10 */, "got %d, expected %d\n", c.X, maxcon_w); 2795 ok(c.Y == maxcon_h || c.Y == maxcon_h - 1 /* Win10 */, "got %d, expected %d\n", c.Y, maxcon_h); 2796 2797 ret = GetConsoleScreenBufferInfo(std_output, &sbi); 2798 ok(ret, "GetConsoleScreenBufferInfo failed %u\n", GetLastError()); 2799 ok(sbi.dwMaximumWindowSize.X == min(c.X, sbi.dwSize.X), "got %d, expected %d\n", 2800 sbi.dwMaximumWindowSize.X, min(c.X, sbi.dwSize.X)); 2801 ok(sbi.dwMaximumWindowSize.Y == min(c.Y, sbi.dwSize.Y), "got %d, expected %d\n", 2802 sbi.dwMaximumWindowSize.Y, min(c.Y, sbi.dwSize.Y)); 2803 } 2804 pSetConsoleFont(std_output, index); /* restore original font size */ 2805 } 2806 2807 static void test_GetConsoleFontInfo(HANDLE std_output) 2808 { 2809 HANDLE hmod; 2810 BOOL (WINAPI *pGetConsoleFontInfo)(HANDLE, BOOL, DWORD, CONSOLE_FONT_INFO *); 2811 DWORD (WINAPI *pGetNumberOfConsoleFonts)(void); 2812 DWORD num_fonts, index, i; 2813 int memsize, win_width, win_height, tmp_w, tmp_h; 2814 CONSOLE_FONT_INFO *cfi; 2815 BOOL ret; 2816 CONSOLE_SCREEN_BUFFER_INFO csbi; 2817 COORD orig_sb_size, tmp_sb_size, orig_font, tmp_font; 2818 2819 hmod = GetModuleHandleA("kernel32.dll"); 2820 pGetConsoleFontInfo = (void *)GetProcAddress(hmod, "GetConsoleFontInfo"); 2821 if (!pGetConsoleFontInfo) 2822 { 2823 win_skip("GetConsoleFontInfo is not available\n"); 2824 return; 2825 } 2826 2827 pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts"); 2828 if (!pGetNumberOfConsoleFonts) 2829 { 2830 win_skip("GetNumberOfConsoleFonts is not available\n"); 2831 return; 2832 } 2833 2834 num_fonts = pGetNumberOfConsoleFonts(); 2835 memsize = num_fonts * sizeof(CONSOLE_FONT_INFO); 2836 cfi = HeapAlloc(GetProcessHeap(), 0, memsize); 2837 memset(cfi, 0, memsize); 2838 2839 GetConsoleScreenBufferInfo(std_output, &csbi); 2840 orig_sb_size = csbi.dwSize; 2841 tmp_sb_size.X = csbi.dwSize.X + 3; 2842 tmp_sb_size.Y = csbi.dwSize.Y + 5; 2843 SetConsoleScreenBufferSize(std_output, tmp_sb_size); 2844 2845 SetLastError(0xdeadbeef); 2846 ret = pGetConsoleFontInfo(NULL, FALSE, 0, cfi); 2847 ok(!ret, "got %d, expected zero\n", ret); 2848 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2849 2850 SetLastError(0xdeadbeef); 2851 ret = pGetConsoleFontInfo(GetStdHandle(STD_INPUT_HANDLE), FALSE, 0, cfi); 2852 ok(!ret, "got %d, expected zero\n", ret); 2853 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2854 2855 SetLastError(0xdeadbeef); 2856 ret = pGetConsoleFontInfo(std_output, FALSE, 0, cfi); 2857 ok(!ret, "got %d, expected zero\n", ret); 2858 todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); 2859 2860 GetConsoleScreenBufferInfo(std_output, &csbi); 2861 win_width = csbi.srWindow.Right - csbi.srWindow.Left + 1; 2862 win_height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; 2863 2864 GetCurrentConsoleFont(std_output, FALSE, &cfi[0]); 2865 index = cfi[0].nFont; 2866 orig_font = GetConsoleFontSize(std_output, index); 2867 2868 memset(cfi, 0, memsize); 2869 ret = pGetConsoleFontInfo(std_output, FALSE, num_fonts, cfi); 2870 todo_wine ok(ret, "got %d, expected non-zero\n", ret); 2871 2872 todo_wine ok(cfi[index].dwFontSize.X == win_width, "got %d, expected %d\n", 2873 cfi[index].dwFontSize.X, win_width); 2874 todo_wine ok(cfi[index].dwFontSize.Y == win_height, "got %d, expected %d\n", 2875 cfi[index].dwFontSize.Y, win_height); 2876 2877 for (i = 0; i < num_fonts; i++) 2878 { 2879 ok(cfi[i].nFont == i, "element out of order, got nFont %d, expected %d\n", cfi[i].nFont, i); 2880 tmp_font = GetConsoleFontSize(std_output, cfi[i].nFont); 2881 tmp_w = (double)orig_font.X / tmp_font.X * win_width; 2882 tmp_h = (double)orig_font.Y / tmp_font.Y * win_height; 2883 todo_wine ok(cfi[i].dwFontSize.X == tmp_w, "got %d, expected %d\n", cfi[i].dwFontSize.X, tmp_w); 2884 todo_wine ok(cfi[i].dwFontSize.Y == tmp_h, "got %d, expected %d\n", cfi[i].dwFontSize.Y, tmp_h); 2885 } 2886 2887 SetLastError(0xdeadbeef); 2888 ret = pGetConsoleFontInfo(NULL, TRUE, 0, cfi); 2889 ok(!ret, "got %d, expected zero\n", ret); 2890 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2891 2892 SetLastError(0xdeadbeef); 2893 ret = pGetConsoleFontInfo(GetStdHandle(STD_INPUT_HANDLE), TRUE, 0, cfi); 2894 ok(!ret, "got %d, expected zero\n", ret); 2895 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2896 2897 SetLastError(0xdeadbeef); 2898 ret = pGetConsoleFontInfo(std_output, TRUE, 0, cfi); 2899 ok(!ret, "got %d, expected zero\n", ret); 2900 todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); 2901 2902 memset(cfi, 0, memsize); 2903 ret = pGetConsoleFontInfo(std_output, TRUE, num_fonts, cfi); 2904 todo_wine ok(ret, "got %d, expected non-zero\n", ret); 2905 2906 todo_wine ok(cfi[index].dwFontSize.X == csbi.dwMaximumWindowSize.X, "got %d, expected %d\n", 2907 cfi[index].dwFontSize.X, csbi.dwMaximumWindowSize.X); 2908 todo_wine ok(cfi[index].dwFontSize.Y == csbi.dwMaximumWindowSize.Y, "got %d, expected %d\n", 2909 cfi[index].dwFontSize.Y, csbi.dwMaximumWindowSize.Y); 2910 2911 for (i = 0; i < num_fonts; i++) 2912 { 2913 ok(cfi[i].nFont == i, "element out of order, got nFont %d, expected %d\n", cfi[i].nFont, i); 2914 tmp_font = GetConsoleFontSize(std_output, cfi[i].nFont); 2915 tmp_w = (double)orig_font.X / tmp_font.X * csbi.dwMaximumWindowSize.X; 2916 tmp_h = (double)orig_font.Y / tmp_font.Y * csbi.dwMaximumWindowSize.Y; 2917 todo_wine ok(cfi[i].dwFontSize.X == tmp_w, "got %d, expected %d\n", cfi[i].dwFontSize.X, tmp_w); 2918 todo_wine ok(cfi[i].dwFontSize.Y == tmp_h, "got %d, expected %d\n", cfi[i].dwFontSize.Y, tmp_h); 2919 } 2920 2921 HeapFree(GetProcessHeap(), 0, cfi); 2922 SetConsoleScreenBufferSize(std_output, orig_sb_size); 2923 } 2924 2925 static void test_SetConsoleFont(HANDLE std_output) 2926 { 2927 HANDLE hmod; 2928 BOOL (WINAPI *pSetConsoleFont)(HANDLE, DWORD); 2929 BOOL ret; 2930 DWORD (WINAPI *pGetNumberOfConsoleFonts)(void); 2931 DWORD num_fonts; 2932 2933 hmod = GetModuleHandleA("kernel32.dll"); 2934 pSetConsoleFont = (void *)GetProcAddress(hmod, "SetConsoleFont"); 2935 if (!pSetConsoleFont) 2936 { 2937 win_skip("SetConsoleFont is not available\n"); 2938 return; 2939 } 2940 2941 SetLastError(0xdeadbeef); 2942 ret = pSetConsoleFont(NULL, 0); 2943 ok(!ret, "got %d, expected zero\n", ret); 2944 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2945 2946 SetLastError(0xdeadbeef); 2947 ret = pSetConsoleFont(GetStdHandle(STD_INPUT_HANDLE), 0); 2948 ok(!ret, "got %d, expected zero\n", ret); 2949 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 2950 2951 pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts"); 2952 if (!pGetNumberOfConsoleFonts) 2953 { 2954 win_skip("GetNumberOfConsoleFonts is not available\n"); 2955 return; 2956 } 2957 2958 num_fonts = pGetNumberOfConsoleFonts(); 2959 2960 SetLastError(0xdeadbeef); 2961 ret = pSetConsoleFont(std_output, num_fonts); 2962 ok(!ret, "got %d, expected zero\n", ret); 2963 todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); 2964 } 2965 2966 static void test_GetConsoleScreenBufferInfoEx(HANDLE std_output) 2967 { 2968 HANDLE hmod; 2969 BOOL (WINAPI *pGetConsoleScreenBufferInfoEx)(HANDLE, CONSOLE_SCREEN_BUFFER_INFOEX *); 2970 CONSOLE_SCREEN_BUFFER_INFOEX csbix; 2971 BOOL ret; 2972 HANDLE std_input = GetStdHandle(STD_INPUT_HANDLE); 2973 2974 hmod = GetModuleHandleA("kernel32.dll"); 2975 pGetConsoleScreenBufferInfoEx = (void *)GetProcAddress(hmod, "GetConsoleScreenBufferInfoEx"); 2976 if (!pGetConsoleScreenBufferInfoEx) 2977 { 2978 win_skip("GetConsoleScreenBufferInfoEx is not available\n"); 2979 return; 2980 } 2981 2982 SetLastError(0xdeadbeef); 2983 ret = pGetConsoleScreenBufferInfoEx(NULL, &csbix); 2984 ok(!ret, "got %d, expected zero\n", ret); 2985 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); 2986 2987 SetLastError(0xdeadbeef); 2988 ret = pGetConsoleScreenBufferInfoEx(std_input, &csbix); 2989 ok(!ret, "got %d, expected zero\n", ret); 2990 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); 2991 2992 SetLastError(0xdeadbeef); 2993 ret = pGetConsoleScreenBufferInfoEx(std_output, &csbix); 2994 ok(!ret, "got %d, expected zero\n", ret); 2995 ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); 2996 2997 csbix.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); 2998 2999 SetLastError(0xdeadbeef); 3000 ret = pGetConsoleScreenBufferInfoEx(NULL, &csbix); 3001 ok(!ret, "got %d, expected zero\n", ret); 3002 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 3003 3004 SetLastError(0xdeadbeef); 3005 ret = pGetConsoleScreenBufferInfoEx(std_input, &csbix); 3006 ok(!ret, "got %d, expected zero\n", ret); 3007 ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); 3008 3009 SetLastError(0xdeadbeef); 3010 ret = pGetConsoleScreenBufferInfoEx(std_output, &csbix); 3011 ok(ret, "got %d, expected non-zero\n", ret); 3012 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); 3013 } 3014 3015 START_TEST(console) 3016 { 3017 static const char font_name[] = "Lucida Console"; 3018 HANDLE hConIn, hConOut; 3019 BOOL ret; 3020 CONSOLE_SCREEN_BUFFER_INFO sbi; 3021 LONG err; 3022 HKEY console_key; 3023 char old_font[LF_FACESIZE]; 3024 BOOL delete = FALSE; 3025 DWORD size; 3026 3027 init_function_pointers(); 3028 3029 /* be sure we have a clean console (and that's our own) 3030 * FIXME: this will make the test fail (currently) if we don't run 3031 * under X11 3032 * Another solution would be to rerun the test under wineconsole with 3033 * the curses backend 3034 */ 3035 3036 /* ReadConsoleOutputW doesn't retrieve characters from the output buffer 3037 * correctly for characters that don't have a glyph in the console font. So, 3038 * we first set the console font to Lucida Console (which has a wider 3039 * selection of glyphs available than the default raster fonts). We want 3040 * to be able to restore the original font afterwards, so don't change 3041 * if we can't read the original font. 3042 */ 3043 err = RegOpenKeyExA(HKEY_CURRENT_USER, "Console", 0, 3044 KEY_QUERY_VALUE | KEY_SET_VALUE, &console_key); 3045 if (err == ERROR_SUCCESS) 3046 { 3047 size = sizeof(old_font); 3048 err = RegQueryValueExA(console_key, "FaceName", NULL, NULL, 3049 (LPBYTE) old_font, &size); 3050 if (err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND) 3051 { 3052 delete = (err == ERROR_FILE_NOT_FOUND); 3053 err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ, 3054 (const BYTE *) font_name, sizeof(font_name)); 3055 if (err != ERROR_SUCCESS) 3056 trace("Unable to change default console font, error %d\n", err); 3057 } 3058 else 3059 { 3060 trace("Unable to query default console font, error %d\n", err); 3061 RegCloseKey(console_key); 3062 console_key = NULL; 3063 } 3064 } 3065 else 3066 { 3067 trace("Unable to open HKCU\\Console, error %d\n", err); 3068 console_key = NULL; 3069 } 3070 3071 /* Now detach and open a fresh console to play with */ 3072 FreeConsole(); 3073 ok(AllocConsole(), "Couldn't alloc console\n"); 3074 3075 /* Restore default console font if needed */ 3076 if (console_key != NULL) 3077 { 3078 if (delete) 3079 err = RegDeleteValueA(console_key, "FaceName"); 3080 else 3081 err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ, 3082 (const BYTE *) old_font, strlen(old_font) + 1); 3083 ok(err == ERROR_SUCCESS, "Unable to restore default console font, error %d\n", err); 3084 } 3085 hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); 3086 hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); 3087 3088 /* now verify everything's ok */ 3089 ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n"); 3090 ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n"); 3091 3092 ret = GetConsoleScreenBufferInfo(hConOut, &sbi); 3093 ok(ret, "Getting sb info\n"); 3094 if (!ret) return; 3095 3096 /* Reduce the size of the buffer to the visible area plus 3 lines to speed 3097 * up the tests. 3098 */ 3099 trace("Visible area: %dx%d - %dx%d Buffer size: %dx%d\n", sbi.srWindow.Left, sbi.srWindow.Top, sbi.srWindow.Right, sbi.srWindow.Bottom, sbi.dwSize.X, sbi.dwSize.Y); 3100 sbi.dwSize.Y = size = (sbi.srWindow.Bottom + 1) + 3; 3101 ret = SetConsoleScreenBufferSize(hConOut, sbi.dwSize); 3102 ok(ret, "Setting sb info\n"); 3103 ret = GetConsoleScreenBufferInfo(hConOut, &sbi); 3104 ok(ret, "Getting sb info\n"); 3105 ok(sbi.dwSize.Y == size, "Unexpected buffer size: %d instead of %d\n", sbi.dwSize.Y, size); 3106 if (!ret) return; 3107 3108 test_ReadConsole(); 3109 /* Non interactive tests */ 3110 testCursor(hConOut, sbi.dwSize); 3111 /* test parameters (FIXME: test functionality) */ 3112 testCursorInfo(hConOut); 3113 /* will test wrapped (on/off) & processed (on/off) strings output */ 3114 testWrite(hConOut, sbi.dwSize); 3115 /* will test line scrolling at the bottom of the screen */ 3116 /* testBottomScroll(); */ 3117 /* will test all the scrolling operations */ 3118 testScroll(hConOut, sbi.dwSize); 3119 /* will test sb creation / modification / codepage handling */ 3120 testScreenBuffer(hConOut); 3121 /* Test waiting for a console handle */ 3122 testWaitForConsoleInput(hConIn); 3123 3124 /* clear duplicated console font table */ 3125 CloseHandle(hConIn); 3126 CloseHandle(hConOut); 3127 FreeConsole(); 3128 ok(AllocConsole(), "Couldn't alloc console\n"); 3129 hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); 3130 hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); 3131 ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n"); 3132 ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n"); 3133 3134 testCtrlHandler(); 3135 /* still to be done: access rights & access on objects */ 3136 3137 if (!pGetConsoleInputExeNameA || !pSetConsoleInputExeNameA) 3138 win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n"); 3139 else 3140 test_GetSetConsoleInputExeName(); 3141 3142 test_GetConsoleProcessList(); 3143 test_OpenConsoleW(); 3144 test_CreateFileW(); 3145 test_OpenCON(); 3146 test_VerifyConsoleIoHandle(hConOut); 3147 test_GetSetStdHandle(); 3148 test_GetNumberOfConsoleInputEvents(hConIn); 3149 test_WriteConsoleInputA(hConIn); 3150 test_WriteConsoleInputW(hConIn); 3151 test_WriteConsoleOutputCharacterA(hConOut); 3152 test_WriteConsoleOutputCharacterW(hConOut); 3153 test_WriteConsoleOutputAttribute(hConOut); 3154 test_FillConsoleOutputCharacterA(hConOut); 3155 test_FillConsoleOutputCharacterW(hConOut); 3156 test_FillConsoleOutputAttribute(hConOut); 3157 test_ReadConsoleOutputCharacterA(hConOut); 3158 test_ReadConsoleOutputCharacterW(hConOut); 3159 test_ReadConsoleOutputAttribute(hConOut); 3160 test_GetCurrentConsoleFont(hConOut); 3161 test_GetConsoleFontSize(hConOut); 3162 test_GetLargestConsoleWindowSize(hConOut); 3163 test_GetConsoleFontInfo(hConOut); 3164 test_SetConsoleFont(hConOut); 3165 test_GetConsoleScreenBufferInfoEx(hConOut); 3166 } 3167