kernel32: Added some tests about CON special file treatment in CreateFile.
[wine/multimedia.git] / dlls / kernel32 / tests / console.c
blob0cd88a372a9672f19c25db405f4a73807505fda1
1 /*
2 * Unit tests for console API
4 * Copyright (c) 2003,2004 Eric Pouech
5 * Copyright (c) 2007 Kirill K. Smirnov
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.
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.
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
22 #include "wine/test.h"
23 #include <windows.h>
24 #include <stdio.h>
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);
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
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'
41 #define CONTENT(c) ('A' + (((c).Y * 17 + (c).X) % 23))
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)
51 #define okCHAR(hCon, c, ch, attr) do { \
52 char __ch; WORD __attr; DWORD __len; BOOL expect; \
53 expect = ReadConsoleOutputCharacter((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)
59 static void init_function_pointers(void)
61 HMODULE hKernel32;
63 #define KERNEL32_GET_PROC(func) \
64 p##func = (void *)GetProcAddress(hKernel32, #func); \
65 if(!p##func) trace("GetProcAddress(hKernel32, '%s') failed\n", #func);
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);
74 #undef KERNEL32_GET_PROC
77 /* FIXME: this could be optimized on a speed point of view */
78 static void resetContent(HANDLE hCon, COORD sbSize, BOOL content)
80 COORD c;
81 WORD attr = DEFAULT_ATTRIB;
82 char ch;
83 DWORD len;
85 for (c.X = 0; c.X < sbSize.X; c.X++)
87 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
89 ch = (content) ? CONTENT(c) : ' ';
90 WriteConsoleOutputAttribute(hCon, &attr, 1, c, &len);
91 WriteConsoleOutputCharacterA(hCon, &ch, 1, c, &len);
96 static void testCursor(HANDLE hCon, COORD sbSize)
98 COORD c;
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());
105 c.X = c.Y = 0;
106 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
107 okCURSOR(hCon, c);
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);
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());
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());
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());
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());
139 static void testCursorInfo(HANDLE hCon)
141 BOOL ret;
142 CONSOLE_CURSOR_INFO info;
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());
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());
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());
169 /* Don't test NULL CONSOLE_CURSOR_INFO, it crashes on win9x and win7 */
172 static void testEmptyWrite(HANDLE hCon)
174 static const char emptybuf[16];
175 COORD c;
176 DWORD len;
178 c.X = c.Y = 0;
179 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
181 len = -1;
182 ok(WriteConsole(hCon, NULL, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
183 okCURSOR(hCon, c);
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)
190 len = -1;
191 ok(!WriteConsole(hCon, NULL, 16, &len, NULL) && len == -1, "WriteConsole\n");
192 okCURSOR(hCon, c);
194 /* Cursor advances for this call. */
195 len = -1;
196 ok(WriteConsole(hCon, NULL, 128, &len, NULL) != 0 && len == 128, "WriteConsole\n");
199 len = -1;
200 ok(WriteConsole(hCon, emptybuf, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
201 okCURSOR(hCon, c);
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(WriteConsole(hCon, emptybuf, 16, &len, NULL) != 0 && len == 16, "WriteConsole\n");
207 c.X += 16;
208 okCURSOR(hCon, c);
211 static void testWriteSimple(HANDLE hCon)
213 COORD c;
214 DWORD len;
215 const char* mytest = "abcdefg";
216 const int mylen = strlen(mytest);
218 /* single line write */
219 c.X = c.Y = 0;
220 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
222 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
223 c.Y = 0;
224 for (c.X = 0; c.X < mylen; c.X++)
226 okCHAR(hCon, c, mytest[c.X], TEST_ATTRIB);
229 okCURSOR(hCon, c);
230 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
233 static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize)
235 COORD c;
236 DWORD len, mode;
237 const char* mytest = "123";
238 const int mylen = strlen(mytest);
239 int ret;
240 int p;
242 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode & ~(ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT)),
243 "clearing wrap at EOL & processed output\n");
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");
249 ret = WriteConsole(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++)
254 c.X = sbSize.X - 3 + p % 3;
255 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
258 c.X = 0; c.Y = 1;
259 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
261 p = sbSize.X - 3 + mylen % 3;
262 c.X = p; c.Y = 0;
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");
268 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
271 static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
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;
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");
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");
288 ok(WriteConsole(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++)
292 okCHAR(hCon, c, mytest[c.X - sbSize.X + 5], TEST_ATTRIB);
295 ReadConsoleOutputAttribute(hCon, &attr, 1, c, &len);
296 /* Win9x and WinMe change the attribs for '\n' up to 'f' */
297 if (attr == TEST_ATTRIB)
299 win_skip("Win9x/WinMe don't respect ~ENABLE_WRAP_AT_EOL_OUTPUT\n");
300 return;
303 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
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);
313 okCURSOR(hCon, c);
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");
319 ok(WriteConsole(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++)
323 okCHAR(hCon, c, mytest[c.X - sbSize.X + 4], TEST_ATTRIB);
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);
333 okCURSOR(hCon, c);
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");
339 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
340 c.Y = 0;
341 for (p = mylen2 - 3; p < mylen2; p++)
343 c.X = sbSize.X - 3 + p % 3;
344 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
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);
354 okCURSOR(hCon, c);
357 static void testWriteWrappedNotProcessed(HANDLE hCon, COORD sbSize)
359 COORD c;
360 DWORD len, mode;
361 const char* mytest = "abcd\nf\tg";
362 const int mylen = strlen(mytest);
363 int p;
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");
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");
372 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
373 c.Y = 0;
374 for (p = 0; p < mylen; p++)
376 c.X = sbSize.X - 9 + p;
377 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
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);
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");
388 c.Y = 1;
389 c.X = mylen - 3;
390 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
393 static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize)
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;
402 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode | (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)),
403 "setting wrap at EOL & processed output\n");
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");
409 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
410 for (p = 0; p < 4; p++)
412 c.X = sbSize.X - 9 + p;
413 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
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);
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");
434 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
435 for (p = 0; p < 3; p++)
437 c.X = sbSize.X - 3 + p;
438 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
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);
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);
459 static void testWrite(HANDLE hCon, COORD sbSize)
461 /* FIXME: should in fact insure that the sb is at least 10 character 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);
477 static void testScroll(HANDLE hCon, COORD sbSize)
479 SMALL_RECT scroll, clip;
480 COORD dst, c, tc;
481 CHAR_INFO ci;
482 BOOL ret;
484 #define W 11
485 #define H 7
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)
490 /* no clipping, src & dst rect don't overlap */
491 resetContent(hCon, sbSize, TRUE);
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;
502 clip.Left = 0;
503 clip.Right = sbSize.X - 1;
504 clip.Top = 0;
505 clip.Bottom = sbSize.Y - 1;
507 ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
509 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
511 for (c.X = 0; c.X < sbSize.X; c.X++)
513 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
515 tc.X = c.X - dst.X;
516 tc.Y = c.Y - dst.Y;
517 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
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);
525 /* no clipping, src & dst rect do overlap */
526 resetContent(hCon, sbSize, TRUE);
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;
537 clip.Left = 0;
538 clip.Right = sbSize.X - 1;
539 clip.Top = 0;
540 clip.Bottom = sbSize.Y - 1;
542 ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
544 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
546 for (c.X = 0; c.X < sbSize.X; c.X++)
548 if (dst.X <= c.X && c.X < dst.X + W && dst.Y <= c.Y && c.Y < dst.Y + H)
550 tc.X = c.X - dst.X;
551 tc.Y = c.Y - dst.Y;
552 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
554 else if (c.X < W && c.Y < H) okCHAR(hCon, c, '#', TEST_ATTRIB);
555 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
559 /* clipping, src & dst rect don't overlap */
560 resetContent(hCon, sbSize, TRUE);
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;
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);
576 SetLastError(0xdeadbeef);
577 ret = ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci);
578 if (ret)
580 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
582 for (c.X = 0; c.X < sbSize.X; c.X++)
584 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
586 tc.X = c.X - dst.X;
587 tc.Y = c.Y - dst.Y;
588 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
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);
596 else
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());
603 /* clipping, src & dst rect do overlap */
604 resetContent(hCon, sbSize, TRUE);
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;
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);
620 ok(ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci), "Scrolling SB\n");
622 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
624 for (c.X = 0; c.X < sbSize.X; c.X++)
626 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
628 tc.X = c.X - dst.X;
629 tc.Y = c.Y - dst.Y;
630 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
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);
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).
644 static HANDLE mch_event;
645 static BOOL WINAPI mch(DWORD event)
647 mch_count++;
648 SetEvent(mch_event);
649 return TRUE;
652 static void testCtrlHandler(void)
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 insure, so far, that event
658 * are processed synchronously in GenerateConsoleCtrlEvent()
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);
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());
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.
692 * What is not tested but should be:
693 * 1) ScreenBufferInfo
695 static void testScreenBuffer(HANDLE hConOut)
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;
708 COORD c;
709 BOOL ret;
710 DWORD oldcp;
712 if (!IsValidCodePage(866))
714 skip("Codepage 866 not available\n");
715 return;
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)
724 win_skip("SetConsoleOutputCP is not implemented\n");
725 return;
727 ok(ret, "Cannot set output codepage to 866\n");
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");
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");
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());
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());
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());
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());
783 CloseHandle(hFileOutRW);
784 CloseHandle(hFileOutRO);
785 CloseHandle(hFileOutWT);
787 /* Trying to set SB handles with various access modes */
788 SetLastError(0);
789 ok(!SetConsoleActiveScreenBuffer(hConOutRO), "Shouldn't succeed\n");
790 ok(GetLastError() == ERROR_INVALID_HANDLE,
791 "GetLastError: expecting %u got %u\n",
792 ERROR_INVALID_HANDLE, GetLastError());
794 ok(SetConsoleActiveScreenBuffer(hConOutWT), "Couldn't set new WriteOnly SB\n");
796 ok(SetConsoleActiveScreenBuffer(hConOutRW), "Couldn't set new ReadWrite SB\n");
798 CloseHandle(hConOutWT);
799 CloseHandle(hConOutRO);
801 /* Now we have two ReadWrite SB, active must be hConOutRW */
802 /* Open current SB via CONOUT$ */
803 hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0,
804 NULL, OPEN_EXISTING, 0, 0);
805 ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n");
808 /* test cursor */
809 c.X = c.Y = 10;
810 SetConsoleCursorPosition(hConOut, c);
811 c.X = c.Y = 5;
812 SetConsoleCursorPosition(hConOutRW, c);
813 okCURSOR(hConOutNew, c);
814 c.X = c.Y = 10;
815 okCURSOR(hConOut, c);
818 c.X = c.Y = 0;
820 /* Write using hConOutNew... */
821 SetConsoleCursorPosition(hConOutNew, c);
822 ret = WriteConsoleA(hConOutNew, test_str2, lstrlenA(test_str2), &len, NULL);
823 ok (ret && len == lstrlenA(test_str2), "WriteConsoleA failed\n");
824 /* ... and read it back via hConOutRW */
825 ret = ReadConsoleOutputCharacterA(hConOutRW, str_buf, lstrlenA(test_str2), c, &len);
826 ok(ret && len == lstrlenA(test_str2), "ReadConsoleOutputCharacterA failed\n");
827 str_buf[lstrlenA(test_str2)] = 0;
828 ok(!lstrcmpA(str_buf, test_str2), "got '%s' expected '%s'\n", str_buf, test_str2);
831 /* Now test output codepage handling. Current is 866 as we set earlier. */
832 SetConsoleCursorPosition(hConOutRW, c);
833 ret = WriteConsoleA(hConOutRW, test_cp866, lstrlenA(test_cp866), &len, NULL);
834 ok(ret && len == lstrlenA(test_cp866), "WriteConsoleA failed\n");
835 ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp866), c, &len);
836 ok(ret && len == lstrlenA(test_cp866), "ReadConsoleOutputCharacterW failed\n");
837 str_wbuf[lstrlenA(test_cp866)] = 0;
838 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
841 * cp866 is OK, let's switch to cp1251.
842 * We expect that this codepage will be used in every SB - active and not.
844 ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n");
845 SetConsoleCursorPosition(hConOutRW, c);
846 ret = WriteConsoleA(hConOutRW, test_cp1251, lstrlenA(test_cp1251), &len, NULL);
847 ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n");
848 ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp1251), c, &len);
849 ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n");
850 str_wbuf[lstrlenA(test_cp1251)] = 0;
851 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
853 /* Check what has happened to hConOut. */
854 SetConsoleCursorPosition(hConOut, c);
855 ret = WriteConsoleA(hConOut, test_cp1251, lstrlenA(test_cp1251), &len, NULL);
856 ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n");
857 ret = ReadConsoleOutputCharacterW(hConOut, str_wbuf, lstrlenA(test_cp1251), c, &len);
858 ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n");
859 str_wbuf[lstrlenA(test_cp1251)] = 0;
860 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
862 /* Close all handles of current console SB */
863 CloseHandle(hConOutNew);
864 CloseHandle(hConOutRW);
866 /* Now active SB should be hConOut */
867 hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0,
868 NULL, OPEN_EXISTING, 0, 0);
869 ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n");
871 /* Write using hConOutNew... */
872 SetConsoleCursorPosition(hConOutNew, c);
873 ret = WriteConsoleA(hConOutNew, test_str1, lstrlenA(test_str1), &len, NULL);
874 ok (ret && len == lstrlenA(test_str1), "WriteConsoleA failed\n");
875 /* ... and read it back via hConOut */
876 ret = ReadConsoleOutputCharacterA(hConOut, str_buf, lstrlenA(test_str1), c, &len);
877 ok(ret && len == lstrlenA(test_str1), "ReadConsoleOutputCharacterA failed\n");
878 str_buf[lstrlenA(test_str1)] = 0;
879 todo_wine ok(!lstrcmpA(str_buf, test_str1), "got '%s' expected '%s'\n", str_buf, test_str1);
880 CloseHandle(hConOutNew);
882 /* This is not really needed under Windows */
883 SetConsoleActiveScreenBuffer(hConOut);
885 /* restore codepage */
886 SetConsoleOutputCP(oldcp);
889 static void test_GetSetConsoleInputExeName(void)
891 BOOL ret;
892 DWORD error;
893 char buffer[MAX_PATH], module[MAX_PATH], *p;
894 static char input_exe[MAX_PATH] = "winetest.exe";
896 SetLastError(0xdeadbeef);
897 ret = pGetConsoleInputExeNameA(0, NULL);
898 error = GetLastError();
899 ok(ret, "GetConsoleInputExeNameA failed\n");
900 ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
902 SetLastError(0xdeadbeef);
903 ret = pGetConsoleInputExeNameA(0, buffer);
904 error = GetLastError();
905 ok(ret, "GetConsoleInputExeNameA failed\n");
906 ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
908 GetModuleFileNameA(GetModuleHandle(NULL), module, sizeof(module));
909 p = strrchr(module, '\\') + 1;
911 ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
912 ok(ret, "GetConsoleInputExeNameA failed\n");
913 todo_wine ok(!lstrcmpA(buffer, p), "got %s expected %s\n", buffer, p);
915 SetLastError(0xdeadbeef);
916 ret = pSetConsoleInputExeNameA(NULL);
917 error = GetLastError();
918 ok(!ret, "SetConsoleInputExeNameA failed\n");
919 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
921 SetLastError(0xdeadbeef);
922 ret = pSetConsoleInputExeNameA("");
923 error = GetLastError();
924 ok(!ret, "SetConsoleInputExeNameA failed\n");
925 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
927 ret = pSetConsoleInputExeNameA(input_exe);
928 ok(ret, "SetConsoleInputExeNameA failed\n");
930 ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
931 ok(ret, "GetConsoleInputExeNameA failed\n");
932 ok(!lstrcmpA(buffer, input_exe), "got %s expected %s\n", buffer, input_exe);
935 static void test_GetConsoleProcessList(void)
937 DWORD ret, *list = NULL;
939 if (!pGetConsoleProcessList)
941 win_skip("GetConsoleProcessList is not available\n");
942 return;
945 SetLastError(0xdeadbeef);
946 ret = pGetConsoleProcessList(NULL, 0);
947 ok(ret == 0, "Expected failure\n");
948 ok(GetLastError() == ERROR_INVALID_PARAMETER,
949 "Expected ERROR_INVALID_PARAMETER, got %d\n",
950 GetLastError());
952 SetLastError(0xdeadbeef);
953 ret = pGetConsoleProcessList(NULL, 1);
954 ok(ret == 0, "Expected failure\n");
955 ok(GetLastError() == ERROR_INVALID_PARAMETER,
956 "Expected ERROR_INVALID_PARAMETER, got %d\n",
957 GetLastError());
959 /* We should only have 1 process but only for these specific unit tests as
960 * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would
961 * give us two processes for example.
963 list = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));
965 SetLastError(0xdeadbeef);
966 ret = pGetConsoleProcessList(list, 0);
967 ok(ret == 0, "Expected failure\n");
968 ok(GetLastError() == ERROR_INVALID_PARAMETER,
969 "Expected ERROR_INVALID_PARAMETER, got %d\n",
970 GetLastError());
972 SetLastError(0xdeadbeef);
973 ret = pGetConsoleProcessList(list, 1);
974 todo_wine
975 ok(ret == 1, "Expected 1, got %d\n", ret);
977 HeapFree(GetProcessHeap(), 0, list);
979 list = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(DWORD));
981 SetLastError(0xdeadbeef);
982 ret = pGetConsoleProcessList(list, ret);
983 todo_wine
984 ok(ret == 1, "Expected 1, got %d\n", ret);
986 if (ret == 1)
988 DWORD pid = GetCurrentProcessId();
989 ok(list[0] == pid, "Expected %d, got %d\n", pid, list[0]);
992 HeapFree(GetProcessHeap(), 0, list);
995 static void test_OpenCON(void)
997 static const WCHAR conW[] = {'C','O','N',0};
998 static const DWORD accesses[] = {CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING,
999 OPEN_ALWAYS, TRUNCATE_EXISTING};
1000 unsigned i;
1001 HANDLE h;
1003 for (i = 0; i < sizeof(accesses) / sizeof(accesses[0]); i++)
1005 if (accesses[i] != OPEN_EXISTING) todo_wine {
1006 h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1007 ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on write (%x)\n", accesses[i]);
1008 CloseHandle(h);
1010 h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL);
1011 /* Windows versions differ here:
1012 * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1013 * NT, XP, Vista comply, but Win7 doesn't and allows to open CON with TRUNCATE_EXISTING
1014 * So don't test when disposition is TRUNCATE_EXISTING
1016 if (accesses[i] != TRUNCATE_EXISTING)
1018 ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on read (%x)\n", accesses[i]);
1020 CloseHandle(h);
1021 } else {
1022 h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1023 ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on write (%x)\n", accesses[i]);
1024 CloseHandle(h);
1026 h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL);
1027 /* Windows versions differ here:
1028 * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1029 * NT, XP, Vista comply, but Win7 doesn't and allows to open CON with TRUNCATE_EXISTING
1030 * So don't test when disposition is TRUNCATE_EXISTING
1032 if (accesses[i] != TRUNCATE_EXISTING)
1034 ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on read (%x)\n", accesses[i]);
1036 CloseHandle(h);
1038 h = CreateFileW(conW, GENERIC_READ|GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1039 ok(h == INVALID_HANDLE_VALUE, "Expected not to open the CON device on read-write (%x)\n", accesses[i]);
1040 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Unexpected error %x\n", GetLastError());
1044 static void test_OpenConsoleW(void)
1046 static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1047 static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1048 static const WCHAR emptyW[] = {0};
1049 static const WCHAR invalidW[] = {'I','N','V','A','L','I','D',0};
1051 static const struct
1053 LPCWSTR name;
1054 DWORD access;
1055 BOOL inherit;
1056 DWORD creation;
1057 DWORD gle;
1058 } invalid_table[] = {
1059 {NULL, 0, FALSE, 0, ERROR_INVALID_PARAMETER},
1060 {NULL, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1061 {NULL, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1062 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER},
1063 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1064 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER},
1065 {emptyW, 0, FALSE, 0, ERROR_INVALID_PARAMETER},
1066 {emptyW, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1067 {emptyW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1068 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER},
1069 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1070 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER},
1071 {invalidW, 0, FALSE, 0, ERROR_INVALID_PARAMETER},
1072 {invalidW, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1073 {invalidW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1074 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER},
1075 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1076 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER},
1077 {coninW, 0, FALSE, 0, ERROR_SHARING_VIOLATION},
1078 {coninW, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1079 {coninW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1080 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_SHARING_VIOLATION},
1081 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, ERROR_SHARING_VIOLATION},
1082 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, ERROR_SHARING_VIOLATION},
1083 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1084 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
1085 {conoutW, 0, FALSE, 0, ERROR_SHARING_VIOLATION},
1086 {conoutW, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1087 {conoutW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1088 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_SHARING_VIOLATION},
1089 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, ERROR_SHARING_VIOLATION},
1090 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, ERROR_SHARING_VIOLATION},
1091 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1092 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
1095 int index;
1096 HANDLE ret;
1098 if (!pOpenConsoleW)
1100 win_skip("OpenConsoleW is not available\n");
1101 return;
1104 for (index = 0; index < sizeof(invalid_table)/sizeof(invalid_table[0]); index++)
1106 SetLastError(0xdeadbeef);
1107 ret = pOpenConsoleW(invalid_table[index].name, invalid_table[index].access,
1108 invalid_table[index].inherit, invalid_table[index].creation);
1109 ok(ret == INVALID_HANDLE_VALUE,
1110 "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1111 index, ret);
1112 ok(GetLastError() == invalid_table[index].gle,
1113 "Expected GetLastError() to return %u for index %d, got %u\n",
1114 invalid_table[index].gle, index, GetLastError());
1117 /* OpenConsoleW should not touch the last error on success. */
1118 SetLastError(0xdeadbeef);
1119 ret = pOpenConsoleW(coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1120 ok(ret != INVALID_HANDLE_VALUE,
1121 "Expected OpenConsoleW to return a valid handle\n");
1122 ok(GetLastError() == 0xdeadbeef,
1123 "Expected the last error to be untouched, got %u\n", GetLastError());
1124 if (ret != INVALID_HANDLE_VALUE)
1125 CloseHandle(ret);
1127 SetLastError(0xdeadbeef);
1128 ret = pOpenConsoleW(conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1129 ok(ret != INVALID_HANDLE_VALUE,
1130 "Expected OpenConsoleW to return a valid handle\n");
1131 ok(GetLastError() == 0xdeadbeef,
1132 "Expected the last error to be untouched, got %u\n", GetLastError());
1133 if (ret != INVALID_HANDLE_VALUE)
1134 CloseHandle(ret);
1137 static void test_VerifyConsoleIoHandle( HANDLE handle )
1139 BOOL ret;
1140 DWORD error;
1142 if (!pVerifyConsoleIoHandle)
1144 win_skip("VerifyConsoleIoHandle is not available\n");
1145 return;
1148 /* invalid handle */
1149 SetLastError(0xdeadbeef);
1150 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee0);
1151 error = GetLastError();
1152 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1153 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1155 /* invalid handle + 1 */
1156 SetLastError(0xdeadbeef);
1157 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee1);
1158 error = GetLastError();
1159 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1160 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1162 /* invalid handle + 2 */
1163 SetLastError(0xdeadbeef);
1164 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee2);
1165 error = GetLastError();
1166 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1167 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1169 /* invalid handle + 3 */
1170 SetLastError(0xdeadbeef);
1171 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee3);
1172 error = GetLastError();
1173 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1174 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1176 /* valid handle */
1177 SetLastError(0xdeadbeef);
1178 ret = pVerifyConsoleIoHandle(handle);
1179 error = GetLastError();
1180 ok(ret, "expected VerifyConsoleIoHandle to succeed\n");
1181 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1184 static void test_GetSetStdHandle(void)
1186 HANDLE handle;
1187 DWORD error;
1188 BOOL ret;
1190 /* get invalid std handle */
1191 SetLastError(0xdeadbeef);
1192 handle = GetStdHandle(42);
1193 error = GetLastError();
1194 ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1195 "wrong GetLastError() %d\n", error);
1196 ok(handle == INVALID_HANDLE_VALUE, "expected INVALID_HANDLE_VALUE\n");
1198 /* get valid */
1199 SetLastError(0xdeadbeef);
1200 handle = GetStdHandle(STD_INPUT_HANDLE);
1201 error = GetLastError();
1202 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1204 /* set invalid std handle */
1205 SetLastError(0xdeadbeef);
1206 ret = SetStdHandle(42, handle);
1207 error = GetLastError();
1208 ok(!ret, "expected SetStdHandle to fail\n");
1209 ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1210 "wrong GetLastError() %d\n", error);
1212 /* set valid (restore old value) */
1213 SetLastError(0xdeadbeef);
1214 ret = SetStdHandle(STD_INPUT_HANDLE, handle);
1215 error = GetLastError();
1216 ok(ret, "expected SetStdHandle to succeed\n");
1217 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1220 static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle)
1222 DWORD count;
1223 BOOL ret;
1224 int i;
1226 const struct
1228 HANDLE handle;
1229 LPDWORD nrofevents;
1230 DWORD last_error;
1231 } invalid_table[] =
1233 {NULL, NULL, ERROR_INVALID_HANDLE},
1234 {NULL, &count, ERROR_INVALID_HANDLE},
1235 {INVALID_HANDLE_VALUE, NULL, ERROR_INVALID_HANDLE},
1236 {INVALID_HANDLE_VALUE, &count, ERROR_INVALID_HANDLE},
1239 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1241 SetLastError(0xdeadbeef);
1242 if (invalid_table[i].nrofevents) count = 0xdeadbeef;
1243 ret = GetNumberOfConsoleInputEvents(invalid_table[i].handle,
1244 invalid_table[i].nrofevents);
1245 ok(!ret, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i, ret);
1246 if (invalid_table[i].nrofevents)
1248 ok(count == 0xdeadbeef,
1249 "[%d] Expected output count to be unmodified, got %u\n", i, count);
1251 ok(GetLastError() == invalid_table[i].last_error,
1252 "[%d] Expected last error to be %u, got %u\n",
1253 i, invalid_table[i].last_error, GetLastError());
1256 /* Test crashes on Windows 7. */
1257 if (0)
1259 SetLastError(0xdeadbeef);
1260 ret = GetNumberOfConsoleInputEvents(input_handle, NULL);
1261 ok(!ret, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret);
1262 ok(GetLastError() == ERROR_INVALID_ACCESS,
1263 "Expected last error to be ERROR_INVALID_ACCESS, got %u\n",
1264 GetLastError());
1267 count = 0xdeadbeef;
1268 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1269 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1270 ok(count != 0xdeadbeef, "Expected output count to initialized\n");
1273 static void test_WriteConsoleInputA(HANDLE input_handle)
1275 INPUT_RECORD event;
1276 INPUT_RECORD event_list[5];
1277 MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1278 KEY_EVENT_RECORD key_event;
1279 DWORD count, console_mode;
1280 BOOL ret;
1281 int i;
1283 const struct
1285 HANDLE handle;
1286 const INPUT_RECORD *buffer;
1287 DWORD count;
1288 LPDWORD written;
1289 DWORD expected_count;
1290 DWORD last_error;
1291 int win7_crash;
1292 } invalid_table[] =
1294 {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1295 {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1296 {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1297 {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1298 {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1299 {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1300 {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1301 {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1302 {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1303 {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1304 {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1305 {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1306 {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1307 {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1308 {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1309 {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1310 {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1311 {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1312 {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1313 {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1314 {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1317 /* Suppress external sources of input events for the duration of the test. */
1318 ret = GetConsoleMode(input_handle, &console_mode);
1319 ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1320 if (!ret)
1322 skip("GetConsoleMode failed with last error %u\n", GetLastError());
1323 return;
1326 ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1327 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1328 if (!ret)
1330 skip("SetConsoleMode failed with last error %u\n", GetLastError());
1331 return;
1334 /* Discard any events queued before the tests. */
1335 ret = FlushConsoleInputBuffer(input_handle);
1336 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1338 event.EventType = MOUSE_EVENT;
1339 event.Event.MouseEvent = mouse_event;
1341 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1343 if (invalid_table[i].win7_crash)
1344 continue;
1346 SetLastError(0xdeadbeef);
1347 if (invalid_table[i].written) count = 0xdeadbeef;
1348 ret = WriteConsoleInputA(invalid_table[i].handle,
1349 invalid_table[i].buffer,
1350 invalid_table[i].count,
1351 invalid_table[i].written);
1352 ok(!ret, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i, ret);
1353 if (invalid_table[i].written)
1355 ok(count == invalid_table[i].expected_count,
1356 "[%d] Expected output count to be %u, got %u\n",
1357 i, invalid_table[i].expected_count, count);
1359 ok(GetLastError() == invalid_table[i].last_error,
1360 "[%d] Expected last error to be %u, got %u\n",
1361 i, invalid_table[i].last_error, GetLastError());
1364 count = 0xdeadbeef;
1365 ret = WriteConsoleInputA(input_handle, NULL, 0, &count);
1366 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1367 ok(count == 0, "Expected count to be 0, got %u\n", count);
1369 count = 0xdeadbeef;
1370 ret = WriteConsoleInputA(input_handle, &event, 0, &count);
1371 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1372 ok(count == 0, "Expected count to be 0, got %u\n", count);
1374 count = 0xdeadbeef;
1375 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1376 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1377 ok(count == 1, "Expected count to be 1, got %u\n", count);
1379 ret = FlushConsoleInputBuffer(input_handle);
1380 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1382 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1383 event.EventType = MOUSE_EVENT;
1384 event.Event.MouseEvent = mouse_event;
1386 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1387 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1388 ok(count == 1, "Expected count to be 1, got %u\n", count);
1390 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1391 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1392 ok(count == 1, "Expected count to be 1, got %u\n", count);
1394 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1395 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1396 ok(count == 1, "Expected count to be 1, got %u\n", count);
1398 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1399 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1400 todo_wine
1401 ok(count == 1, "Expected count to be 1, got %u\n", count);
1403 ret = FlushConsoleInputBuffer(input_handle);
1404 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1406 for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1408 event_list[i].EventType = MOUSE_EVENT;
1409 event_list[i].Event.MouseEvent = mouse_event;
1412 /* Writing consecutive chunks of mouse events appears to work. */
1413 ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1414 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1415 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1416 "Expected count to be event list length, got %u\n", count);
1418 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1419 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1420 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1421 "Expected count to be event list length, got %u\n", count);
1423 ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1424 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1425 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1426 "Expected count to be event list length, got %u\n", count);
1428 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1429 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1430 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1431 "Expected count to be twice event list length, got %u\n", count);
1433 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1434 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1435 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1436 ok(count == 1, "Expected count to be 1, got %u\n", count);
1438 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1439 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1440 todo_wine
1441 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1442 "Expected count to be twice event list length, got %u\n", count);
1444 ret = FlushConsoleInputBuffer(input_handle);
1445 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1447 key_event.bKeyDown = FALSE;
1448 key_event.wRepeatCount = 0;
1449 key_event.wVirtualKeyCode = VK_SPACE;
1450 key_event.wVirtualScanCode = VK_SPACE;
1451 key_event.uChar.AsciiChar = ' ';
1452 key_event.dwControlKeyState = 0;
1454 event.EventType = KEY_EVENT;
1455 event.Event.KeyEvent = key_event;
1457 /* Key events don't exhibit the same behavior as mouse events. */
1458 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1459 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1460 ok(count == 1, "Expected count to be 1, got %u\n", count);
1462 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1463 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1464 ok(count == 1, "Expected count to be 1, got %u\n", count);
1466 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1467 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1468 ok(count == 1, "Expected count to be 1, got %u\n", count);
1470 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1471 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1472 ok(count == 2, "Expected count to be 2, got %u\n", count);
1474 ret = FlushConsoleInputBuffer(input_handle);
1475 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1477 /* Try interleaving mouse and key events. */
1478 event.EventType = MOUSE_EVENT;
1479 event.Event.MouseEvent = mouse_event;
1481 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1482 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1483 ok(count == 1, "Expected count to be 1, got %u\n", count);
1485 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1486 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1487 ok(count == 1, "Expected count to be 1, got %u\n", count);
1489 event.EventType = KEY_EVENT;
1490 event.Event.KeyEvent = key_event;
1492 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1493 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1494 ok(count == 1, "Expected count to be 1, got %u\n", count);
1496 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1497 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1498 ok(count == 2, "Expected count to be 2, got %u\n", count);
1500 event.EventType = MOUSE_EVENT;
1501 event.Event.MouseEvent = mouse_event;
1503 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1504 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1505 ok(count == 1, "Expected count to be 1, got %u\n", count);
1507 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1508 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1509 ok(count == 3, "Expected count to be 3, got %u\n", count);
1511 /* Restore the old console mode. */
1512 ret = SetConsoleMode(input_handle, console_mode);
1513 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1516 static void test_WriteConsoleInputW(HANDLE input_handle)
1518 INPUT_RECORD event;
1519 INPUT_RECORD event_list[5];
1520 MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1521 KEY_EVENT_RECORD key_event;
1522 DWORD count, console_mode;
1523 BOOL ret;
1524 int i;
1526 const struct
1528 HANDLE handle;
1529 const INPUT_RECORD *buffer;
1530 DWORD count;
1531 LPDWORD written;
1532 DWORD expected_count;
1533 DWORD last_error;
1534 int win7_crash;
1535 } invalid_table[] =
1537 {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1538 {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1539 {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1540 {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1541 {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1542 {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1543 {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1544 {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1545 {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1546 {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1547 {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1548 {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1549 {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1550 {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1551 {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1552 {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1553 {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1554 {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1555 {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1556 {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1557 {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1560 /* Suppress external sources of input events for the duration of the test. */
1561 ret = GetConsoleMode(input_handle, &console_mode);
1562 ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1563 if (!ret)
1565 skip("GetConsoleMode failed with last error %u\n", GetLastError());
1566 return;
1569 ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1570 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1571 if (!ret)
1573 skip("SetConsoleMode failed with last error %u\n", GetLastError());
1574 return;
1577 /* Discard any events queued before the tests. */
1578 ret = FlushConsoleInputBuffer(input_handle);
1579 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1581 event.EventType = MOUSE_EVENT;
1582 event.Event.MouseEvent = mouse_event;
1584 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1586 if (invalid_table[i].win7_crash)
1587 continue;
1589 SetLastError(0xdeadbeef);
1590 if (invalid_table[i].written) count = 0xdeadbeef;
1591 ret = WriteConsoleInputW(invalid_table[i].handle,
1592 invalid_table[i].buffer,
1593 invalid_table[i].count,
1594 invalid_table[i].written);
1595 ok(!ret, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i, ret);
1596 if (invalid_table[i].written)
1598 ok(count == invalid_table[i].expected_count,
1599 "[%d] Expected output count to be %u, got %u\n",
1600 i, invalid_table[i].expected_count, count);
1602 ok(GetLastError() == invalid_table[i].last_error,
1603 "[%d] Expected last error to be %u, got %u\n",
1604 i, invalid_table[i].last_error, GetLastError());
1607 count = 0xdeadbeef;
1608 ret = WriteConsoleInputW(input_handle, NULL, 0, &count);
1609 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1610 ok(count == 0, "Expected count to be 0, got %u\n", count);
1612 count = 0xdeadbeef;
1613 ret = WriteConsoleInputW(input_handle, &event, 0, &count);
1614 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1615 ok(count == 0, "Expected count to be 0, got %u\n", count);
1617 count = 0xdeadbeef;
1618 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1619 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1620 ok(count == 1, "Expected count to be 1, got %u\n", count);
1622 ret = FlushConsoleInputBuffer(input_handle);
1623 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1625 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1626 event.EventType = MOUSE_EVENT;
1627 event.Event.MouseEvent = mouse_event;
1629 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1630 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1631 ok(count == 1, "Expected count to be 1, got %u\n", count);
1633 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1634 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1635 ok(count == 1, "Expected count to be 1, got %u\n", count);
1637 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1638 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1639 ok(count == 1, "Expected count to be 1, got %u\n", count);
1641 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1642 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1643 todo_wine
1644 ok(count == 1, "Expected count to be 1, got %u\n", count);
1646 ret = FlushConsoleInputBuffer(input_handle);
1647 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1649 for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1651 event_list[i].EventType = MOUSE_EVENT;
1652 event_list[i].Event.MouseEvent = mouse_event;
1655 /* Writing consecutive chunks of mouse events appears to work. */
1656 ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1657 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1658 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1659 "Expected count to be event list length, got %u\n", count);
1661 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1662 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1663 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1664 "Expected count to be event list length, got %u\n", count);
1666 ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1667 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1668 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1669 "Expected count to be event list length, got %u\n", count);
1671 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1672 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1673 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1674 "Expected count to be twice event list length, got %u\n", count);
1676 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1677 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1678 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1679 ok(count == 1, "Expected count to be 1, got %u\n", count);
1681 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1682 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1683 todo_wine
1684 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1685 "Expected count to be twice event list length, got %u\n", count);
1687 ret = FlushConsoleInputBuffer(input_handle);
1688 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1690 key_event.bKeyDown = FALSE;
1691 key_event.wRepeatCount = 0;
1692 key_event.wVirtualKeyCode = VK_SPACE;
1693 key_event.wVirtualScanCode = VK_SPACE;
1694 key_event.uChar.UnicodeChar = ' ';
1695 key_event.dwControlKeyState = 0;
1697 event.EventType = KEY_EVENT;
1698 event.Event.KeyEvent = key_event;
1700 /* Key events don't exhibit the same behavior as mouse events. */
1701 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1702 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1703 ok(count == 1, "Expected count to be 1, got %u\n", count);
1705 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1706 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1707 ok(count == 1, "Expected count to be 1, got %u\n", count);
1709 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1710 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1711 ok(count == 1, "Expected count to be 1, got %u\n", count);
1713 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1714 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1715 ok(count == 2, "Expected count to be 2, got %u\n", count);
1717 ret = FlushConsoleInputBuffer(input_handle);
1718 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1720 /* Try interleaving mouse and key events. */
1721 event.EventType = MOUSE_EVENT;
1722 event.Event.MouseEvent = mouse_event;
1724 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1725 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1726 ok(count == 1, "Expected count to be 1, got %u\n", count);
1728 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1729 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1730 ok(count == 1, "Expected count to be 1, got %u\n", count);
1732 event.EventType = KEY_EVENT;
1733 event.Event.KeyEvent = key_event;
1735 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1736 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1737 ok(count == 1, "Expected count to be 1, got %u\n", count);
1739 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1740 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1741 ok(count == 2, "Expected count to be 2, got %u\n", count);
1743 event.EventType = MOUSE_EVENT;
1744 event.Event.MouseEvent = mouse_event;
1746 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1747 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1748 ok(count == 1, "Expected count to be 1, got %u\n", count);
1750 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1751 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1752 ok(count == 3, "Expected count to be 3, got %u\n", count);
1754 /* Restore the old console mode. */
1755 ret = SetConsoleMode(input_handle, console_mode);
1756 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1759 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle)
1761 static const char output[] = {'a', 0};
1763 COORD origin = {0, 0};
1764 DWORD count;
1765 BOOL ret;
1766 int i;
1768 const struct
1770 HANDLE hConsoleOutput;
1771 LPCSTR str;
1772 DWORD length;
1773 COORD coord;
1774 LPDWORD lpNumCharsWritten;
1775 DWORD expected_count;
1776 DWORD last_error;
1777 int win7_crash;
1778 } invalid_table[] =
1780 {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1781 {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1782 {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1783 {NULL, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1784 {NULL, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1785 {NULL, output, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1786 {NULL, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1787 {NULL, output, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
1788 {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1789 {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1790 {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1791 {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1792 {INVALID_HANDLE_VALUE, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1793 {INVALID_HANDLE_VALUE, output, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1794 {INVALID_HANDLE_VALUE, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1795 {INVALID_HANDLE_VALUE, output, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
1796 {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1797 {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1798 {output_handle, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1799 {output_handle, output, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1800 {output_handle, output, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1803 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1805 if (invalid_table[i].win7_crash)
1806 continue;
1808 SetLastError(0xdeadbeef);
1809 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1810 ret = WriteConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
1811 invalid_table[i].str,
1812 invalid_table[i].length,
1813 invalid_table[i].coord,
1814 invalid_table[i].lpNumCharsWritten);
1815 ok(!ret, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
1816 if (invalid_table[i].lpNumCharsWritten)
1818 ok(count == invalid_table[i].expected_count,
1819 "[%d] Expected count to be %u, got %u\n",
1820 i, invalid_table[i].expected_count, count);
1822 ok(GetLastError() == invalid_table[i].last_error,
1823 "[%d] Expected last error to be %u, got %u\n",
1824 i, invalid_table[i].last_error, GetLastError());
1827 count = 0xdeadbeef;
1828 ret = WriteConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
1829 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1830 ok(count == 0, "Expected count to be 0, got %u\n", count);
1832 count = 0xdeadbeef;
1833 ret = WriteConsoleOutputCharacterA(output_handle, output, 0, origin, &count);
1834 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1835 ok(count == 0, "Expected count to be 0, got %u\n", count);
1837 count = 0xdeadbeef;
1838 ret = WriteConsoleOutputCharacterA(output_handle, output, 1, origin, &count);
1839 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1840 ok(count == 1, "Expected count to be 1, got %u\n", count);
1843 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle)
1845 static const WCHAR outputW[] = {'a',0};
1847 COORD origin = {0, 0};
1848 DWORD count;
1849 BOOL ret;
1850 int i;
1852 const struct
1854 HANDLE hConsoleOutput;
1855 LPCWSTR str;
1856 DWORD length;
1857 COORD coord;
1858 LPDWORD lpNumCharsWritten;
1859 DWORD expected_count;
1860 DWORD last_error;
1861 int win7_crash;
1862 } invalid_table[] =
1864 {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1865 {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1866 {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1867 {NULL, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1868 {NULL, outputW, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1869 {NULL, outputW, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1870 {NULL, outputW, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1871 {NULL, outputW, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
1872 {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1873 {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1874 {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1875 {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1876 {INVALID_HANDLE_VALUE, outputW, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1877 {INVALID_HANDLE_VALUE, outputW, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1878 {INVALID_HANDLE_VALUE, outputW, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1879 {INVALID_HANDLE_VALUE, outputW, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
1880 {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1881 {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1882 {output_handle, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1883 {output_handle, outputW, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1884 {output_handle, outputW, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1887 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1889 if (invalid_table[i].win7_crash)
1890 continue;
1892 SetLastError(0xdeadbeef);
1893 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1894 ret = WriteConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
1895 invalid_table[i].str,
1896 invalid_table[i].length,
1897 invalid_table[i].coord,
1898 invalid_table[i].lpNumCharsWritten);
1899 ok(!ret, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
1900 if (invalid_table[i].lpNumCharsWritten)
1902 ok(count == invalid_table[i].expected_count,
1903 "[%d] Expected count to be %u, got %u\n",
1904 i, invalid_table[i].expected_count, count);
1906 ok(GetLastError() == invalid_table[i].last_error,
1907 "[%d] Expected last error to be %u, got %u\n",
1908 i, invalid_table[i].last_error, GetLastError());
1911 count = 0xdeadbeef;
1912 ret = WriteConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
1913 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1914 ok(count == 0, "Expected count to be 0, got %u\n", count);
1916 count = 0xdeadbeef;
1917 ret = WriteConsoleOutputCharacterW(output_handle, outputW, 0, origin, &count);
1918 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1919 ok(count == 0, "Expected count to be 0, got %u\n", count);
1921 count = 0xdeadbeef;
1922 ret = WriteConsoleOutputCharacterW(output_handle, outputW, 1, origin, &count);
1923 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1924 ok(count == 1, "Expected count to be 1, got %u\n", count);
1927 static void test_WriteConsoleOutputAttribute(HANDLE output_handle)
1929 WORD attr = FOREGROUND_BLUE;
1930 COORD origin = {0, 0};
1931 DWORD count;
1932 BOOL ret;
1933 int i;
1935 const struct
1937 HANDLE hConsoleOutput;
1938 CONST WORD *attr;
1939 DWORD length;
1940 COORD coord;
1941 LPDWORD lpNumAttrsWritten;
1942 DWORD expected_count;
1943 DWORD last_error;
1944 int win7_crash;
1945 } invalid_table[] =
1947 {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1948 {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1949 {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1950 {NULL, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1951 {NULL, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1952 {NULL, &attr, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1953 {NULL, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1954 {NULL, &attr, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
1955 {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1956 {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1957 {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1958 {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1959 {INVALID_HANDLE_VALUE, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1960 {INVALID_HANDLE_VALUE, &attr, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
1961 {INVALID_HANDLE_VALUE, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1962 {INVALID_HANDLE_VALUE, &attr, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
1963 {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1964 {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1965 {output_handle, NULL, 1, origin, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1966 {output_handle, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1967 {output_handle, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1970 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1972 if (invalid_table[i].win7_crash)
1973 continue;
1975 SetLastError(0xdeadbeef);
1976 if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
1977 ret = WriteConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
1978 invalid_table[i].attr,
1979 invalid_table[i].length,
1980 invalid_table[i].coord,
1981 invalid_table[i].lpNumAttrsWritten);
1982 ok(!ret, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
1983 if (invalid_table[i].lpNumAttrsWritten)
1985 ok(count == invalid_table[i].expected_count,
1986 "[%d] Expected count to be %u, got %u\n",
1987 i, invalid_table[i].expected_count, count);
1989 ok(GetLastError() == invalid_table[i].last_error,
1990 "[%d] Expected last error to be %u, got %u\n",
1991 i, invalid_table[i].last_error, GetLastError());
1994 count = 0xdeadbeef;
1995 ret = WriteConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
1996 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
1997 ok(count == 0, "Expected count to be 0, got %u\n", count);
1999 count = 0xdeadbeef;
2000 ret = WriteConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2001 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2002 ok(count == 0, "Expected count to be 0, got %u\n", count);
2004 count = 0xdeadbeef;
2005 ret = WriteConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2006 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2007 ok(count == 1, "Expected count to be 1, got %u\n", count);
2010 static void test_FillConsoleOutputCharacterA(HANDLE output_handle)
2012 COORD origin = {0, 0};
2013 DWORD count;
2014 BOOL ret;
2015 int i;
2017 const struct
2019 HANDLE hConsoleOutput;
2020 CHAR ch;
2021 DWORD length;
2022 COORD coord;
2023 LPDWORD lpNumCharsWritten;
2024 DWORD expected_count;
2025 DWORD last_error;
2026 int win7_crash;
2027 } invalid_table[] =
2029 {NULL, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2030 {NULL, 'a', 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2031 {NULL, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2032 {NULL, 'a', 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2033 {INVALID_HANDLE_VALUE, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2034 {INVALID_HANDLE_VALUE, 'a', 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2035 {INVALID_HANDLE_VALUE, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2036 {INVALID_HANDLE_VALUE, 'a', 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2037 {output_handle, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2038 {output_handle, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2041 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2043 if (invalid_table[i].win7_crash)
2044 continue;
2046 SetLastError(0xdeadbeef);
2047 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2048 ret = FillConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2049 invalid_table[i].ch,
2050 invalid_table[i].length,
2051 invalid_table[i].coord,
2052 invalid_table[i].lpNumCharsWritten);
2053 ok(!ret, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2054 if (invalid_table[i].lpNumCharsWritten)
2056 ok(count == invalid_table[i].expected_count,
2057 "[%d] Expected count to be %u, got %u\n",
2058 i, invalid_table[i].expected_count, count);
2060 ok(GetLastError() == invalid_table[i].last_error,
2061 "[%d] Expected last error to be %u, got %u\n",
2062 i, invalid_table[i].last_error, GetLastError());
2065 count = 0xdeadbeef;
2066 ret = FillConsoleOutputCharacterA(output_handle, 'a', 0, origin, &count);
2067 ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2068 ok(count == 0, "Expected count to be 0, got %u\n", count);
2070 count = 0xdeadbeef;
2071 ret = FillConsoleOutputCharacterA(output_handle, 'a', 1, origin, &count);
2072 ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2073 ok(count == 1, "Expected count to be 1, got %u\n", count);
2076 static void test_FillConsoleOutputCharacterW(HANDLE output_handle)
2078 COORD origin = {0, 0};
2079 DWORD count;
2080 BOOL ret;
2081 int i;
2083 const struct
2085 HANDLE hConsoleOutput;
2086 WCHAR ch;
2087 DWORD length;
2088 COORD coord;
2089 LPDWORD lpNumCharsWritten;
2090 DWORD expected_count;
2091 DWORD last_error;
2092 int win7_crash;
2093 } invalid_table[] =
2095 {NULL, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2096 {NULL, 'a', 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2097 {NULL, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2098 {NULL, 'a', 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2099 {INVALID_HANDLE_VALUE, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2100 {INVALID_HANDLE_VALUE, 'a', 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2101 {INVALID_HANDLE_VALUE, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2102 {INVALID_HANDLE_VALUE, 'a', 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2103 {output_handle, 'a', 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2104 {output_handle, 'a', 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2107 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2109 if (invalid_table[i].win7_crash)
2110 continue;
2112 SetLastError(0xdeadbeef);
2113 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2114 ret = FillConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2115 invalid_table[i].ch,
2116 invalid_table[i].length,
2117 invalid_table[i].coord,
2118 invalid_table[i].lpNumCharsWritten);
2119 ok(!ret, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2120 if (invalid_table[i].lpNumCharsWritten)
2122 ok(count == invalid_table[i].expected_count,
2123 "[%d] Expected count to be %u, got %u\n",
2124 i, invalid_table[i].expected_count, count);
2126 ok(GetLastError() == invalid_table[i].last_error,
2127 "[%d] Expected last error to be %u, got %u\n",
2128 i, invalid_table[i].last_error, GetLastError());
2131 count = 0xdeadbeef;
2132 ret = FillConsoleOutputCharacterW(output_handle, 'a', 0, origin, &count);
2133 ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2134 ok(count == 0, "Expected count to be 0, got %u\n", count);
2136 count = 0xdeadbeef;
2137 ret = FillConsoleOutputCharacterW(output_handle, 'a', 1, origin, &count);
2138 ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2139 ok(count == 1, "Expected count to be 1, got %u\n", count);
2142 static void test_FillConsoleOutputAttribute(HANDLE output_handle)
2144 COORD origin = {0, 0};
2145 DWORD count;
2146 BOOL ret;
2147 int i;
2149 const struct
2151 HANDLE hConsoleOutput;
2152 WORD attr;
2153 DWORD length;
2154 COORD coord;
2155 LPDWORD lpNumAttrsWritten;
2156 DWORD expected_count;
2157 DWORD last_error;
2158 int win7_crash;
2159 } invalid_table[] =
2161 {NULL, FOREGROUND_BLUE, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2162 {NULL, FOREGROUND_BLUE, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2163 {NULL, FOREGROUND_BLUE, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2164 {NULL, FOREGROUND_BLUE, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2165 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2166 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2167 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2168 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2169 {output_handle, FOREGROUND_BLUE, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2170 {output_handle, FOREGROUND_BLUE, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2173 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2175 if (invalid_table[i].win7_crash)
2176 continue;
2178 SetLastError(0xdeadbeef);
2179 if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2180 ret = FillConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2181 invalid_table[i].attr,
2182 invalid_table[i].length,
2183 invalid_table[i].coord,
2184 invalid_table[i].lpNumAttrsWritten);
2185 ok(!ret, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2186 if (invalid_table[i].lpNumAttrsWritten)
2188 ok(count == invalid_table[i].expected_count,
2189 "[%d] Expected count to be %u, got %u\n",
2190 i, invalid_table[i].expected_count, count);
2192 ok(GetLastError() == invalid_table[i].last_error,
2193 "[%d] Expected last error to be %u, got %u\n",
2194 i, invalid_table[i].last_error, GetLastError());
2197 count = 0xdeadbeef;
2198 ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 0, origin, &count);
2199 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2200 ok(count == 0, "Expected count to be 0, got %u\n", count);
2202 count = 0xdeadbeef;
2203 ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 1, origin, &count);
2204 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2205 ok(count == 1, "Expected count to be 1, got %u\n", count);
2207 count = 0xdeadbeef;
2208 ret = FillConsoleOutputAttribute(output_handle, ~0, 1, origin, &count);
2209 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2210 ok(count == 1, "Expected count to be 1, got %u\n", count);
2213 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle)
2215 CHAR read;
2216 COORD origin = {0, 0};
2217 DWORD count;
2218 BOOL ret;
2219 int i;
2221 const struct
2223 HANDLE hConsoleOutput;
2224 LPSTR lpstr;
2225 DWORD length;
2226 COORD coord;
2227 LPDWORD read_count;
2228 DWORD expected_count;
2229 DWORD last_error;
2230 int win7_crash;
2231 } invalid_table[] =
2233 {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2234 {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2235 {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2236 {NULL, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
2237 {NULL, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2238 {NULL, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2239 {NULL, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2240 {NULL, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2241 {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2242 {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2243 {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2244 {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
2245 {INVALID_HANDLE_VALUE, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2246 {INVALID_HANDLE_VALUE, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2247 {INVALID_HANDLE_VALUE, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2248 {INVALID_HANDLE_VALUE, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2249 {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2250 {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2251 {output_handle, NULL, 1, origin, &count, 1, ERROR_INVALID_ACCESS, 1},
2252 {output_handle, NULL, 10, origin, &count, 10, ERROR_INVALID_ACCESS, 1},
2253 {output_handle, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2254 {output_handle, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2257 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2259 if (invalid_table[i].win7_crash)
2260 continue;
2262 SetLastError(0xdeadbeef);
2263 if (invalid_table[i].read_count) count = 0xdeadbeef;
2264 ret = ReadConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2265 invalid_table[i].lpstr,
2266 invalid_table[i].length,
2267 invalid_table[i].coord,
2268 invalid_table[i].read_count);
2269 ok(!ret, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2270 if (invalid_table[i].read_count)
2272 ok(count == invalid_table[i].expected_count,
2273 "[%d] Expected count to be %u, got %u\n",
2274 i, invalid_table[i].expected_count, count);
2276 ok(GetLastError() == invalid_table[i].last_error,
2277 "[%d] Expected last error to be %u, got %u\n",
2278 i, invalid_table[i].last_error, GetLastError());
2281 count = 0xdeadbeef;
2282 ret = ReadConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
2283 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2284 ok(count == 0, "Expected count to be 0, got %u\n", count);
2286 count = 0xdeadbeef;
2287 ret = ReadConsoleOutputCharacterA(output_handle, &read, 0, origin, &count);
2288 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2289 ok(count == 0, "Expected count to be 0, got %u\n", count);
2291 count = 0xdeadbeef;
2292 ret = ReadConsoleOutputCharacterA(output_handle, &read, 1, origin, &count);
2293 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2294 ok(count == 1, "Expected count to be 1, got %u\n", count);
2297 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle)
2299 WCHAR read;
2300 COORD origin = {0, 0};
2301 DWORD count;
2302 BOOL ret;
2303 int i;
2305 const struct
2307 HANDLE hConsoleOutput;
2308 LPWSTR buffer;
2309 DWORD length;
2310 COORD coord;
2311 LPDWORD read_count;
2312 DWORD expected_count;
2313 DWORD last_error;
2314 int win7_crash;
2315 } invalid_table[] =
2317 {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2318 {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2319 {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2320 {NULL, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
2321 {NULL, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2322 {NULL, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2323 {NULL, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2324 {NULL, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2325 {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2326 {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2327 {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2328 {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
2329 {INVALID_HANDLE_VALUE, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2330 {INVALID_HANDLE_VALUE, &read, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2331 {INVALID_HANDLE_VALUE, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2332 {INVALID_HANDLE_VALUE, &read, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2333 {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2334 {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2335 {output_handle, NULL, 1, origin, &count, 1, ERROR_INVALID_ACCESS, 1},
2336 {output_handle, NULL, 10, origin, &count, 10, ERROR_INVALID_ACCESS, 1},
2337 {output_handle, &read, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2338 {output_handle, &read, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2341 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2343 if (invalid_table[i].win7_crash)
2344 continue;
2346 SetLastError(0xdeadbeef);
2347 if (invalid_table[i].read_count) count = 0xdeadbeef;
2348 ret = ReadConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2349 invalid_table[i].buffer,
2350 invalid_table[i].length,
2351 invalid_table[i].coord,
2352 invalid_table[i].read_count);
2353 ok(!ret, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2354 if (invalid_table[i].read_count)
2356 ok(count == invalid_table[i].expected_count,
2357 "[%d] Expected count to be %u, got %u\n",
2358 i, invalid_table[i].expected_count, count);
2360 ok(GetLastError() == invalid_table[i].last_error,
2361 "[%d] Expected last error to be %u, got %u\n",
2362 i, invalid_table[i].last_error, GetLastError());
2365 count = 0xdeadbeef;
2366 ret = ReadConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
2367 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2368 ok(count == 0, "Expected count to be 0, got %u\n", count);
2370 count = 0xdeadbeef;
2371 ret = ReadConsoleOutputCharacterW(output_handle, &read, 0, origin, &count);
2372 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2373 ok(count == 0, "Expected count to be 0, got %u\n", count);
2375 count = 0xdeadbeef;
2376 ret = ReadConsoleOutputCharacterW(output_handle, &read, 1, origin, &count);
2377 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2378 ok(count == 1, "Expected count to be 1, got %u\n", count);
2381 static void test_ReadConsoleOutputAttribute(HANDLE output_handle)
2383 WORD attr;
2384 COORD origin = {0, 0};
2385 DWORD count;
2386 BOOL ret;
2387 int i;
2389 const struct
2391 HANDLE hConsoleOutput;
2392 LPWORD lpAttribute;
2393 DWORD length;
2394 COORD coord;
2395 LPDWORD read_count;
2396 DWORD expected_count;
2397 DWORD last_error;
2398 int win7_crash;
2399 } invalid_table[] =
2401 {NULL, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2402 {NULL, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2403 {NULL, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2404 {NULL, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
2405 {NULL, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2406 {NULL, &attr, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2407 {NULL, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2408 {NULL, &attr, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2409 {INVALID_HANDLE_VALUE, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2410 {INVALID_HANDLE_VALUE, NULL, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2411 {INVALID_HANDLE_VALUE, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2412 {INVALID_HANDLE_VALUE, NULL, 1, origin, &count, 0, ERROR_INVALID_HANDLE, 1},
2413 {INVALID_HANDLE_VALUE, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2414 {INVALID_HANDLE_VALUE, &attr, 0, origin, &count, 0, ERROR_INVALID_HANDLE},
2415 {INVALID_HANDLE_VALUE, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2416 {INVALID_HANDLE_VALUE, &attr, 1, origin, &count, 0, ERROR_INVALID_HANDLE},
2417 {output_handle, NULL, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2418 {output_handle, NULL, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2419 {output_handle, NULL, 1, origin, &count, 1, ERROR_INVALID_ACCESS, 1},
2420 {output_handle, &attr, 0, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2421 {output_handle, &attr, 1, origin, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2424 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2426 if (invalid_table[i].win7_crash)
2427 continue;
2429 SetLastError(0xdeadbeef);
2430 if (invalid_table[i].read_count) count = 0xdeadbeef;
2431 ret = ReadConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2432 invalid_table[i].lpAttribute,
2433 invalid_table[i].length,
2434 invalid_table[i].coord,
2435 invalid_table[i].read_count);
2436 ok(!ret, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2437 if (invalid_table[i].read_count)
2439 ok(count == invalid_table[i].expected_count,
2440 "[%d] Expected count to be %u, got %u\n",
2441 i, invalid_table[i].expected_count, count);
2443 ok(GetLastError() == invalid_table[i].last_error,
2444 "[%d] Expected last error to be %u, got %u\n",
2445 i, invalid_table[i].last_error, GetLastError());
2448 count = 0xdeadbeef;
2449 ret = ReadConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2450 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2451 ok(count == 0, "Expected count to be 0, got %u\n", count);
2453 count = 0xdeadbeef;
2454 ret = ReadConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2455 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2456 ok(count == 0, "Expected count to be 0, got %u\n", count);
2458 count = 0xdeadbeef;
2459 ret = ReadConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2460 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2461 ok(count == 1, "Expected count to be 1, got %u\n", count);
2464 START_TEST(console)
2466 static const char font_name[] = "Lucida Console";
2467 HANDLE hConIn, hConOut;
2468 BOOL ret;
2469 CONSOLE_SCREEN_BUFFER_INFO sbi;
2470 LONG err;
2471 HKEY console_key;
2472 char old_font[LF_FACESIZE];
2473 BOOL delete = FALSE;
2474 DWORD size;
2476 init_function_pointers();
2478 /* be sure we have a clean console (and that's our own)
2479 * FIXME: this will make the test fail (currently) if we don't run
2480 * under X11
2481 * Another solution would be to rerun the test under wineconsole with
2482 * the curses backend
2485 /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
2486 * correctly for characters that don't have a glyph in the console font. So,
2487 * we first set the console font to Lucida Console (which has a wider
2488 * selection of glyphs available than the default raster fonts). We want
2489 * to be able to restore the original font afterwards, so don't change
2490 * if we can't read the original font.
2492 err = RegOpenKeyExA(HKEY_CURRENT_USER, "Console", 0,
2493 KEY_QUERY_VALUE | KEY_SET_VALUE, &console_key);
2494 if (err == ERROR_SUCCESS)
2496 size = sizeof(old_font);
2497 err = RegQueryValueExA(console_key, "FaceName", NULL, NULL,
2498 (LPBYTE) old_font, &size);
2499 if (err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND)
2501 delete = (err == ERROR_FILE_NOT_FOUND);
2502 err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
2503 (const BYTE *) font_name, sizeof(font_name));
2504 if (err != ERROR_SUCCESS)
2505 trace("Unable to change default console font, error %d\n", err);
2507 else
2509 trace("Unable to query default console font, error %d\n", err);
2510 RegCloseKey(console_key);
2511 console_key = NULL;
2514 else
2516 trace("Unable to open HKCU\\Console, error %d\n", err);
2517 console_key = NULL;
2520 /* Now detach and open a fresh console to play with */
2521 FreeConsole();
2522 ok(AllocConsole(), "Couldn't alloc console\n");
2524 /* Restore default console font if needed */
2525 if (console_key != NULL)
2527 if (delete)
2528 err = RegDeleteValueA(console_key, "FaceName");
2529 else
2530 err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
2531 (const BYTE *) old_font, strlen(old_font) + 1);
2532 ok(err == ERROR_SUCCESS, "Unable to restore default console font, error %d\n", err);
2534 hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2535 hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2537 /* now verify everything's ok */
2538 ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
2539 ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
2541 ret = GetConsoleScreenBufferInfo(hConOut, &sbi);
2542 ok(ret, "Getting sb info\n");
2543 if (!ret) return;
2545 /* Non interactive tests */
2546 testCursor(hConOut, sbi.dwSize);
2547 /* test parameters (FIXME: test functionality) */
2548 testCursorInfo(hConOut);
2549 /* will test wrapped (on/off) & processed (on/off) strings output */
2550 testWrite(hConOut, sbi.dwSize);
2551 /* will test line scrolling at the bottom of the screen */
2552 /* testBottomScroll(); */
2553 /* will test all the scrolling operations */
2554 testScroll(hConOut, sbi.dwSize);
2555 /* will test sb creation / modification / codepage handling */
2556 testScreenBuffer(hConOut);
2557 testCtrlHandler();
2558 /* still to be done: access rights & access on objects */
2560 if (!pGetConsoleInputExeNameA || !pSetConsoleInputExeNameA)
2561 win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
2562 else
2563 test_GetSetConsoleInputExeName();
2565 test_GetConsoleProcessList();
2566 test_OpenConsoleW();
2567 test_OpenCON();
2568 test_VerifyConsoleIoHandle(hConOut);
2569 test_GetSetStdHandle();
2570 test_GetNumberOfConsoleInputEvents(hConIn);
2571 test_WriteConsoleInputA(hConIn);
2572 test_WriteConsoleInputW(hConIn);
2573 test_WriteConsoleOutputCharacterA(hConOut);
2574 test_WriteConsoleOutputCharacterW(hConOut);
2575 test_WriteConsoleOutputAttribute(hConOut);
2576 test_FillConsoleOutputCharacterA(hConOut);
2577 test_FillConsoleOutputCharacterW(hConOut);
2578 test_FillConsoleOutputAttribute(hConOut);
2579 test_ReadConsoleOutputCharacterA(hConOut);
2580 test_ReadConsoleOutputCharacterW(hConOut);
2581 test_ReadConsoleOutputAttribute(hConOut);