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