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"
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); \
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); \
59 static void init_function_pointers(void)
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
)
81 WORD attr
= DEFAULT_ATTRIB
;
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
)
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());
106 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
111 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in lower-right\n");
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());
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());
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());
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
)
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);
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];
179 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
182 ok(WriteConsole(hCon
, NULL
, 0, &len
, NULL
) != 0 && len
== 0, "WriteConsole\n");
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. */
191 ok(!WriteConsole(hCon
, NULL
, 16, &len
, NULL
) && len
== -1, "WriteConsole\n");
194 /* Cursor advances for this call. */
196 ok(WriteConsole(hCon
, NULL
, 128, &len
, NULL
) != 0 && len
== 128, "WriteConsole\n");
200 ok(WriteConsole(hCon
, emptybuf
, 0, &len
, NULL
) != 0 && len
== 0, "WriteConsole\n");
203 /* WriteConsole does not halt on a null terminator and is happy to write
204 * memory contents beyond the actual size of the buffer. */
206 ok(WriteConsole(hCon
, emptybuf
, 16, &len
, NULL
) != 0 && len
== 16, "WriteConsole\n");
211 static void testWriteSimple(HANDLE hCon
)
215 const char* mytest
= "abcdefg";
216 const int mylen
= strlen(mytest
);
218 /* single line write */
220 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
222 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
224 for (c
.X
= 0; c
.X
< mylen
; c
.X
++)
226 okCHAR(hCon
, c
, mytest
[c
.X
], TEST_ATTRIB
);
230 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
233 static void testWriteNotWrappedNotProcessed(HANDLE hCon
, COORD sbSize
)
237 const char* mytest
= "123";
238 const int mylen
= strlen(mytest
);
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
);
252 for (p
= mylen
- 3; p
< mylen
; p
++)
254 c
.X
= sbSize
.X
- 3 + p
% 3;
255 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
259 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
261 p
= sbSize
.X
- 3 + mylen
% 3;
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
)
275 const char* mytest
= "abcd\nf\tg";
276 const int mylen
= strlen(mytest
);
277 const int mylen2
= strchr(mytest
, '\n') - mytest
;
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");
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");
303 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
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
);
311 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
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");
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
);
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
);
331 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
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");
341 for (p
= mylen2
- 3; p
< mylen2
; p
++)
343 c
.X
= sbSize
.X
- 3 + p
% 3;
344 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
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
);
352 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
357 static void testWriteWrappedNotProcessed(HANDLE hCon
, COORD sbSize
)
361 const char* mytest
= "abcd\nf\tg";
362 const int mylen
= strlen(mytest
);
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");
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
);
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");
390 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
393 static void testWriteWrappedProcessed(HANDLE hCon
, COORD sbSize
)
397 const char* mytest
= "abcd\nf\tg";
398 const int mylen
= strlen(mytest
);
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");
420 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
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
);
427 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
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
);
441 okCHAR(hCon
, c
, mytest
[3], TEST_ATTRIB
);
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");
447 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
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
);
455 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
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
;
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
);
494 scroll
.Right
= W
- 1;
496 scroll
.Bottom
= H
- 1;
499 ci
.Char
.UnicodeChar
= '#';
500 ci
.Attributes
= TEST_ATTRIB
;
503 clip
.Right
= sbSize
.X
- 1;
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
))
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
);
529 scroll
.Right
= W
- 1;
531 scroll
.Bottom
= H
- 1;
534 ci
.Char
.UnicodeChar
= '#';
535 ci
.Attributes
= TEST_ATTRIB
;
538 clip
.Right
= sbSize
.X
- 1;
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
)
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
);
563 scroll
.Right
= W
- 1;
565 scroll
.Bottom
= H
- 1;
568 ci
.Char
.UnicodeChar
= '#';
569 ci
.Attributes
= TEST_ATTRIB
;
572 clip
.Right
= min(W
+ W
/ 2, sbSize
.X
- 1);
574 clip
.Bottom
= min(H
+ H
/ 2, sbSize
.Y
- 1);
576 SetLastError(0xdeadbeef);
577 ret
= ScrollConsoleScreenBuffer(hCon
, &scroll
, &clip
, dst
, &ci
);
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
))
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
);
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
);
607 scroll
.Right
= W
- 1;
609 scroll
.Bottom
= H
- 1;
612 ci
.Char
.UnicodeChar
= '#';
613 ci
.Attributes
= TEST_ATTRIB
;
616 clip
.Right
= min(W
+ W
/ 2, sbSize
.X
- 1);
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
))
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
)
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
);
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
);
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.
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
;
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};
712 if (!IsValidCodePage(866))
714 skip("Codepage 866 not available\n");
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");
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 */
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 */
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());
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());
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 /* trying to write non-console handle */
784 SetLastError(0xdeadbeef);
785 ok(!WriteConsoleA(hFileOutRW
, test_str1
, lstrlenA(test_str1
), &len
, NULL
),
786 "Shouldn't succeed\n");
787 ok(GetLastError() == ERROR_INVALID_HANDLE
,
788 "GetLastError: expecting %u got %u\n",
789 ERROR_INVALID_HANDLE
, GetLastError());
791 SetLastError(0xdeadbeef);
792 ok(!WriteConsoleA(hFileOutRO
, test_str1
, lstrlenA(test_str1
), &len
, NULL
),
793 "Shouldn't succeed\n");
794 ok(GetLastError() == ERROR_INVALID_HANDLE
,
795 "GetLastError: expecting %u got %u\n",
796 ERROR_INVALID_HANDLE
, GetLastError());
798 SetLastError(0xdeadbeef);
799 ok(!WriteConsoleA(hFileOutWT
, test_str1
, lstrlenA(test_str1
), &len
, NULL
),
800 "Shouldn't succeed\n");
801 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
802 "GetLastError: expecting %u got %u\n",
803 ERROR_INVALID_HANDLE
, GetLastError());
805 CloseHandle(hFileOutRW
);
806 CloseHandle(hFileOutRO
);
807 CloseHandle(hFileOutWT
);
809 /* Trying to set SB handles with various access modes */
811 ok(!SetConsoleActiveScreenBuffer(hConOutRO
), "Shouldn't succeed\n");
812 ok(GetLastError() == ERROR_INVALID_HANDLE
,
813 "GetLastError: expecting %u got %u\n",
814 ERROR_INVALID_HANDLE
, GetLastError());
816 ok(SetConsoleActiveScreenBuffer(hConOutWT
), "Couldn't set new WriteOnly SB\n");
818 ok(SetConsoleActiveScreenBuffer(hConOutRW
), "Couldn't set new ReadWrite SB\n");
820 CloseHandle(hConOutWT
);
821 CloseHandle(hConOutRO
);
823 /* Now we have two ReadWrite SB, active must be hConOutRW */
824 /* Open current SB via CONOUT$ */
825 hConOutNew
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0,
826 NULL
, OPEN_EXISTING
, 0, 0);
827 ok(hConOutNew
!= INVALID_HANDLE_VALUE
, "CONOUT$ is not opened\n");
832 SetConsoleCursorPosition(hConOut
, c
);
834 SetConsoleCursorPosition(hConOutRW
, c
);
835 okCURSOR(hConOutNew
, c
);
837 okCURSOR(hConOut
, c
);
842 /* Write using hConOutNew... */
843 SetConsoleCursorPosition(hConOutNew
, c
);
844 ret
= WriteConsoleA(hConOutNew
, test_str2
, lstrlenA(test_str2
), &len
, NULL
);
845 ok (ret
&& len
== lstrlenA(test_str2
), "WriteConsoleA failed\n");
846 /* ... and read it back via hConOutRW */
847 ret
= ReadConsoleOutputCharacterA(hConOutRW
, str_buf
, lstrlenA(test_str2
), c
, &len
);
848 ok(ret
&& len
== lstrlenA(test_str2
), "ReadConsoleOutputCharacterA failed\n");
849 str_buf
[lstrlenA(test_str2
)] = 0;
850 ok(!lstrcmpA(str_buf
, test_str2
), "got '%s' expected '%s'\n", str_buf
, test_str2
);
853 /* Now test output codepage handling. Current is 866 as we set earlier. */
854 SetConsoleCursorPosition(hConOutRW
, c
);
855 ret
= WriteConsoleA(hConOutRW
, test_cp866
, lstrlenA(test_cp866
), &len
, NULL
);
856 ok(ret
&& len
== lstrlenA(test_cp866
), "WriteConsoleA failed\n");
857 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenA(test_cp866
), c
, &len
);
858 ok(ret
&& len
== lstrlenA(test_cp866
), "ReadConsoleOutputCharacterW failed\n");
859 str_wbuf
[lstrlenA(test_cp866
)] = 0;
860 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
863 * cp866 is OK, let's switch to cp1251.
864 * We expect that this codepage will be used in every SB - active and not.
866 ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n");
867 SetConsoleCursorPosition(hConOutRW
, c
);
868 ret
= WriteConsoleA(hConOutRW
, test_cp1251
, lstrlenA(test_cp1251
), &len
, NULL
);
869 ok(ret
&& len
== lstrlenA(test_cp1251
), "WriteConsoleA failed\n");
870 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenA(test_cp1251
), c
, &len
);
871 ok(ret
&& len
== lstrlenA(test_cp1251
), "ReadConsoleOutputCharacterW failed\n");
872 str_wbuf
[lstrlenA(test_cp1251
)] = 0;
873 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
875 /* Check what has happened to hConOut. */
876 SetConsoleCursorPosition(hConOut
, c
);
877 ret
= WriteConsoleA(hConOut
, test_cp1251
, lstrlenA(test_cp1251
), &len
, NULL
);
878 ok(ret
&& len
== lstrlenA(test_cp1251
), "WriteConsoleA failed\n");
879 ret
= ReadConsoleOutputCharacterW(hConOut
, str_wbuf
, lstrlenA(test_cp1251
), c
, &len
);
880 ok(ret
&& len
== lstrlenA(test_cp1251
), "ReadConsoleOutputCharacterW failed\n");
881 str_wbuf
[lstrlenA(test_cp1251
)] = 0;
882 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
884 /* Close all handles of current console SB */
885 CloseHandle(hConOutNew
);
886 CloseHandle(hConOutRW
);
888 /* Now active SB should be hConOut */
889 hConOutNew
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0,
890 NULL
, OPEN_EXISTING
, 0, 0);
891 ok(hConOutNew
!= INVALID_HANDLE_VALUE
, "CONOUT$ is not opened\n");
893 /* Write using hConOutNew... */
894 SetConsoleCursorPosition(hConOutNew
, c
);
895 ret
= WriteConsoleA(hConOutNew
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
896 ok (ret
&& len
== lstrlenA(test_str1
), "WriteConsoleA failed\n");
897 /* ... and read it back via hConOut */
898 ret
= ReadConsoleOutputCharacterA(hConOut
, str_buf
, lstrlenA(test_str1
), c
, &len
);
899 ok(ret
&& len
== lstrlenA(test_str1
), "ReadConsoleOutputCharacterA failed\n");
900 str_buf
[lstrlenA(test_str1
)] = 0;
901 todo_wine
ok(!lstrcmpA(str_buf
, test_str1
), "got '%s' expected '%s'\n", str_buf
, test_str1
);
902 CloseHandle(hConOutNew
);
904 /* This is not really needed under Windows */
905 SetConsoleActiveScreenBuffer(hConOut
);
907 /* restore codepage */
908 SetConsoleOutputCP(oldcp
);
911 static void test_GetSetConsoleInputExeName(void)
915 char buffer
[MAX_PATH
], module
[MAX_PATH
], *p
;
916 static char input_exe
[MAX_PATH
] = "winetest.exe";
918 SetLastError(0xdeadbeef);
919 ret
= pGetConsoleInputExeNameA(0, NULL
);
920 error
= GetLastError();
921 ok(ret
, "GetConsoleInputExeNameA failed\n");
922 ok(error
== ERROR_BUFFER_OVERFLOW
, "got %u expected ERROR_BUFFER_OVERFLOW\n", error
);
924 SetLastError(0xdeadbeef);
925 ret
= pGetConsoleInputExeNameA(0, buffer
);
926 error
= GetLastError();
927 ok(ret
, "GetConsoleInputExeNameA failed\n");
928 ok(error
== ERROR_BUFFER_OVERFLOW
, "got %u expected ERROR_BUFFER_OVERFLOW\n", error
);
930 GetModuleFileNameA(GetModuleHandle(NULL
), module
, sizeof(module
));
931 p
= strrchr(module
, '\\') + 1;
933 ret
= pGetConsoleInputExeNameA(sizeof(buffer
)/sizeof(buffer
[0]), buffer
);
934 ok(ret
, "GetConsoleInputExeNameA failed\n");
935 todo_wine
ok(!lstrcmpA(buffer
, p
), "got %s expected %s\n", buffer
, p
);
937 SetLastError(0xdeadbeef);
938 ret
= pSetConsoleInputExeNameA(NULL
);
939 error
= GetLastError();
940 ok(!ret
, "SetConsoleInputExeNameA failed\n");
941 ok(error
== ERROR_INVALID_PARAMETER
, "got %u expected ERROR_INVALID_PARAMETER\n", error
);
943 SetLastError(0xdeadbeef);
944 ret
= pSetConsoleInputExeNameA("");
945 error
= GetLastError();
946 ok(!ret
, "SetConsoleInputExeNameA failed\n");
947 ok(error
== ERROR_INVALID_PARAMETER
, "got %u expected ERROR_INVALID_PARAMETER\n", error
);
949 ret
= pSetConsoleInputExeNameA(input_exe
);
950 ok(ret
, "SetConsoleInputExeNameA failed\n");
952 ret
= pGetConsoleInputExeNameA(sizeof(buffer
)/sizeof(buffer
[0]), buffer
);
953 ok(ret
, "GetConsoleInputExeNameA failed\n");
954 ok(!lstrcmpA(buffer
, input_exe
), "got %s expected %s\n", buffer
, input_exe
);
957 static void test_GetConsoleProcessList(void)
959 DWORD ret
, *list
= NULL
;
961 if (!pGetConsoleProcessList
)
963 win_skip("GetConsoleProcessList is not available\n");
967 SetLastError(0xdeadbeef);
968 ret
= pGetConsoleProcessList(NULL
, 0);
969 ok(ret
== 0, "Expected failure\n");
970 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
971 "Expected ERROR_INVALID_PARAMETER, got %d\n",
974 SetLastError(0xdeadbeef);
975 ret
= pGetConsoleProcessList(NULL
, 1);
976 ok(ret
== 0, "Expected failure\n");
977 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
978 "Expected ERROR_INVALID_PARAMETER, got %d\n",
981 /* We should only have 1 process but only for these specific unit tests as
982 * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would
983 * give us two processes for example.
985 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD
));
987 SetLastError(0xdeadbeef);
988 ret
= pGetConsoleProcessList(list
, 0);
989 ok(ret
== 0, "Expected failure\n");
990 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
991 "Expected ERROR_INVALID_PARAMETER, got %d\n",
994 SetLastError(0xdeadbeef);
995 ret
= pGetConsoleProcessList(list
, 1);
997 ok(ret
== 1, "Expected 1, got %d\n", ret
);
999 HeapFree(GetProcessHeap(), 0, list
);
1001 list
= HeapAlloc(GetProcessHeap(), 0, ret
* sizeof(DWORD
));
1003 SetLastError(0xdeadbeef);
1004 ret
= pGetConsoleProcessList(list
, ret
);
1006 ok(ret
== 1, "Expected 1, got %d\n", ret
);
1010 DWORD pid
= GetCurrentProcessId();
1011 ok(list
[0] == pid
, "Expected %d, got %d\n", pid
, list
[0]);
1014 HeapFree(GetProcessHeap(), 0, list
);
1017 static void test_OpenCON(void)
1019 static const WCHAR conW
[] = {'C','O','N',0};
1020 static const DWORD accesses
[] = {CREATE_NEW
, CREATE_ALWAYS
, OPEN_EXISTING
,
1021 OPEN_ALWAYS
, TRUNCATE_EXISTING
};
1025 for (i
= 0; i
< sizeof(accesses
) / sizeof(accesses
[0]); i
++)
1027 h
= CreateFileW(conW
, GENERIC_WRITE
, 0, NULL
, accesses
[i
], 0, NULL
);
1028 ok(h
!= INVALID_HANDLE_VALUE
, "Expected to open the CON device on write (%x)\n", accesses
[i
]);
1031 h
= CreateFileW(conW
, GENERIC_READ
, 0, NULL
, accesses
[i
], 0, NULL
);
1032 /* Windows versions differ here:
1033 * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1034 * NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING
1035 * So don't test when disposition is TRUNCATE_EXISTING
1037 if (accesses
[i
] != TRUNCATE_EXISTING
)
1039 ok(h
!= INVALID_HANDLE_VALUE
, "Expected to open the CON device on read (%x)\n", accesses
[i
]);
1042 h
= CreateFileW(conW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, accesses
[i
], 0, NULL
);
1043 ok(h
== INVALID_HANDLE_VALUE
, "Expected not to open the CON device on read-write (%x)\n", accesses
[i
]);
1044 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "Unexpected error %x\n", GetLastError());
1048 static void test_OpenConsoleW(void)
1050 static const WCHAR coninW
[] = {'C','O','N','I','N','$',0};
1051 static const WCHAR conoutW
[] = {'C','O','N','O','U','T','$',0};
1052 static const WCHAR emptyW
[] = {0};
1053 static const WCHAR invalidW
[] = {'I','N','V','A','L','I','D',0};
1062 } invalid_table
[] = {
1063 {NULL
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1064 {NULL
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1065 {NULL
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1066 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1067 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1068 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
},
1069 {emptyW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1070 {emptyW
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1071 {emptyW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1072 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1073 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1074 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
},
1075 {invalidW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1076 {invalidW
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1077 {invalidW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1078 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1079 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1080 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
},
1081 {coninW
, 0, FALSE
, 0, ERROR_SHARING_VIOLATION
},
1082 {coninW
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1083 {coninW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1084 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_SHARING_VIOLATION
},
1085 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, ERROR_SHARING_VIOLATION
},
1086 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, ERROR_SHARING_VIOLATION
},
1087 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1088 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
, ERROR_INVALID_PARAMETER
},
1089 {conoutW
, 0, FALSE
, 0, ERROR_SHARING_VIOLATION
},
1090 {conoutW
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1091 {conoutW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1092 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_SHARING_VIOLATION
},
1093 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, ERROR_SHARING_VIOLATION
},
1094 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, ERROR_SHARING_VIOLATION
},
1095 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1096 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
, ERROR_INVALID_PARAMETER
},
1104 win_skip("OpenConsoleW is not available\n");
1108 for (index
= 0; index
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); index
++)
1110 SetLastError(0xdeadbeef);
1111 ret
= pOpenConsoleW(invalid_table
[index
].name
, invalid_table
[index
].access
,
1112 invalid_table
[index
].inherit
, invalid_table
[index
].creation
);
1113 ok(ret
== INVALID_HANDLE_VALUE
,
1114 "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1116 ok(GetLastError() == invalid_table
[index
].gle
,
1117 "Expected GetLastError() to return %u for index %d, got %u\n",
1118 invalid_table
[index
].gle
, index
, GetLastError());
1121 /* OpenConsoleW should not touch the last error on success. */
1122 SetLastError(0xdeadbeef);
1123 ret
= pOpenConsoleW(coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
);
1124 ok(ret
!= INVALID_HANDLE_VALUE
,
1125 "Expected OpenConsoleW to return a valid handle\n");
1126 ok(GetLastError() == 0xdeadbeef,
1127 "Expected the last error to be untouched, got %u\n", GetLastError());
1128 if (ret
!= INVALID_HANDLE_VALUE
)
1131 SetLastError(0xdeadbeef);
1132 ret
= pOpenConsoleW(conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
);
1133 ok(ret
!= INVALID_HANDLE_VALUE
,
1134 "Expected OpenConsoleW to return a valid handle\n");
1135 ok(GetLastError() == 0xdeadbeef,
1136 "Expected the last error to be untouched, got %u\n", GetLastError());
1137 if (ret
!= INVALID_HANDLE_VALUE
)
1141 static void test_CreateFileW(void)
1143 static const WCHAR coninW
[] = {'C','O','N','I','N','$',0};
1144 static const WCHAR conoutW
[] = {'C','O','N','O','U','T','$',0};
1155 {coninW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1156 {coninW
, 0, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1157 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1158 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, 0, FALSE
},
1159 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, 0, FALSE
},
1160 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1161 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
, 0, FALSE
},
1162 {conoutW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1163 {conoutW
, 0, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1164 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1165 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, 0, FALSE
},
1166 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, 0, FALSE
},
1167 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1168 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
, 0, FALSE
},
1173 SECURITY_ATTRIBUTES sa
;
1175 for (index
= 0; index
< sizeof(cf_table
)/sizeof(cf_table
[0]); index
++)
1177 SetLastError(0xdeadbeef);
1179 sa
.nLength
= sizeof(sa
);
1180 sa
.lpSecurityDescriptor
= NULL
;
1181 sa
.bInheritHandle
= cf_table
[index
].inherit
;
1183 ret
= CreateFileW(cf_table
[index
].name
, cf_table
[index
].access
,
1184 FILE_SHARE_READ
|FILE_SHARE_WRITE
, &sa
,
1185 cf_table
[index
].creation
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1186 if (ret
== INVALID_HANDLE_VALUE
)
1188 ok(cf_table
[index
].gle
,
1189 "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index
);
1190 ok(GetLastError() == cf_table
[index
].gle
,
1191 "Expected GetLastError() to return %u for index %d, got %u\n",
1192 cf_table
[index
].gle
, index
, GetLastError());
1196 ok(!cf_table
[index
].gle
|| broken(cf_table
[index
].is_broken
) /* Win7 */,
1197 "Expected CreateFileW to succeed for index %d\n", index
);
1203 static void test_VerifyConsoleIoHandle( HANDLE handle
)
1208 if (!pVerifyConsoleIoHandle
)
1210 win_skip("VerifyConsoleIoHandle is not available\n");
1214 /* invalid handle */
1215 SetLastError(0xdeadbeef);
1216 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee0);
1217 error
= GetLastError();
1218 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1219 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1221 /* invalid handle + 1 */
1222 SetLastError(0xdeadbeef);
1223 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee1);
1224 error
= GetLastError();
1225 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1226 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1228 /* invalid handle + 2 */
1229 SetLastError(0xdeadbeef);
1230 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee2);
1231 error
= GetLastError();
1232 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1233 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1235 /* invalid handle + 3 */
1236 SetLastError(0xdeadbeef);
1237 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee3);
1238 error
= GetLastError();
1239 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1240 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1243 SetLastError(0xdeadbeef);
1244 ret
= pVerifyConsoleIoHandle(handle
);
1245 error
= GetLastError();
1246 ok(ret
, "expected VerifyConsoleIoHandle to succeed\n");
1247 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1250 static void test_GetSetStdHandle(void)
1256 /* get invalid std handle */
1257 SetLastError(0xdeadbeef);
1258 handle
= GetStdHandle(42);
1259 error
= GetLastError();
1260 ok(error
== ERROR_INVALID_HANDLE
|| broken(error
== ERROR_INVALID_FUNCTION
)/* Win9x */,
1261 "wrong GetLastError() %d\n", error
);
1262 ok(handle
== INVALID_HANDLE_VALUE
, "expected INVALID_HANDLE_VALUE\n");
1265 SetLastError(0xdeadbeef);
1266 handle
= GetStdHandle(STD_INPUT_HANDLE
);
1267 error
= GetLastError();
1268 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1270 /* set invalid std handle */
1271 SetLastError(0xdeadbeef);
1272 ret
= SetStdHandle(42, handle
);
1273 error
= GetLastError();
1274 ok(!ret
, "expected SetStdHandle to fail\n");
1275 ok(error
== ERROR_INVALID_HANDLE
|| broken(error
== ERROR_INVALID_FUNCTION
)/* Win9x */,
1276 "wrong GetLastError() %d\n", error
);
1278 /* set valid (restore old value) */
1279 SetLastError(0xdeadbeef);
1280 ret
= SetStdHandle(STD_INPUT_HANDLE
, handle
);
1281 error
= GetLastError();
1282 ok(ret
, "expected SetStdHandle to succeed\n");
1283 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1286 static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle
)
1299 {NULL
, NULL
, ERROR_INVALID_HANDLE
},
1300 {NULL
, &count
, ERROR_INVALID_HANDLE
},
1301 {INVALID_HANDLE_VALUE
, NULL
, ERROR_INVALID_HANDLE
},
1302 {INVALID_HANDLE_VALUE
, &count
, ERROR_INVALID_HANDLE
},
1305 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
1307 SetLastError(0xdeadbeef);
1308 if (invalid_table
[i
].nrofevents
) count
= 0xdeadbeef;
1309 ret
= GetNumberOfConsoleInputEvents(invalid_table
[i
].handle
,
1310 invalid_table
[i
].nrofevents
);
1311 ok(!ret
, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i
, ret
);
1312 if (invalid_table
[i
].nrofevents
)
1314 ok(count
== 0xdeadbeef,
1315 "[%d] Expected output count to be unmodified, got %u\n", i
, count
);
1317 ok(GetLastError() == invalid_table
[i
].last_error
,
1318 "[%d] Expected last error to be %u, got %u\n",
1319 i
, invalid_table
[i
].last_error
, GetLastError());
1322 /* Test crashes on Windows 7. */
1325 SetLastError(0xdeadbeef);
1326 ret
= GetNumberOfConsoleInputEvents(input_handle
, NULL
);
1327 ok(!ret
, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret
);
1328 ok(GetLastError() == ERROR_INVALID_ACCESS
,
1329 "Expected last error to be ERROR_INVALID_ACCESS, got %u\n",
1334 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1335 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1336 ok(count
!= 0xdeadbeef, "Expected output count to initialized\n");
1339 static void test_WriteConsoleInputA(HANDLE input_handle
)
1342 INPUT_RECORD event_list
[5];
1343 MOUSE_EVENT_RECORD mouse_event
= { {0, 0}, 0, 0, MOUSE_MOVED
};
1344 KEY_EVENT_RECORD key_event
;
1345 DWORD count
, console_mode
;
1352 const INPUT_RECORD
*buffer
;
1355 DWORD expected_count
;
1360 {NULL
, NULL
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1361 {NULL
, NULL
, 0, &count
, 0, ERROR_INVALID_HANDLE
},
1362 {NULL
, NULL
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1363 {NULL
, NULL
, 1, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1364 {NULL
, &event
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1365 {NULL
, &event
, 0, &count
, 0, ERROR_INVALID_HANDLE
},
1366 {NULL
, &event
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1367 {NULL
, &event
, 1, &count
, 0, ERROR_INVALID_HANDLE
},
1368 {INVALID_HANDLE_VALUE
, NULL
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1369 {INVALID_HANDLE_VALUE
, NULL
, 0, &count
, 0, ERROR_INVALID_HANDLE
},
1370 {INVALID_HANDLE_VALUE
, NULL
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1371 {INVALID_HANDLE_VALUE
, NULL
, 1, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1372 {INVALID_HANDLE_VALUE
, &event
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1373 {INVALID_HANDLE_VALUE
, &event
, 0, &count
, 0, ERROR_INVALID_HANDLE
},
1374 {INVALID_HANDLE_VALUE
, &event
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1375 {INVALID_HANDLE_VALUE
, &event
, 1, &count
, 0, ERROR_INVALID_HANDLE
},
1376 {input_handle
, NULL
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1377 {input_handle
, NULL
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1378 {input_handle
, NULL
, 1, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1379 {input_handle
, &event
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1380 {input_handle
, &event
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1383 /* Suppress external sources of input events for the duration of the test. */
1384 ret
= GetConsoleMode(input_handle
, &console_mode
);
1385 ok(ret
== TRUE
, "Expected GetConsoleMode to return TRUE, got %d\n", ret
);
1388 skip("GetConsoleMode failed with last error %u\n", GetLastError());
1392 ret
= SetConsoleMode(input_handle
, console_mode
& ~(ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
));
1393 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
1396 skip("SetConsoleMode failed with last error %u\n", GetLastError());
1400 /* Discard any events queued before the tests. */
1401 ret
= FlushConsoleInputBuffer(input_handle
);
1402 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1404 event
.EventType
= MOUSE_EVENT
;
1405 event
.Event
.MouseEvent
= mouse_event
;
1407 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
1409 if (invalid_table
[i
].win7_crash
)
1412 SetLastError(0xdeadbeef);
1413 if (invalid_table
[i
].written
) count
= 0xdeadbeef;
1414 ret
= WriteConsoleInputA(invalid_table
[i
].handle
,
1415 invalid_table
[i
].buffer
,
1416 invalid_table
[i
].count
,
1417 invalid_table
[i
].written
);
1418 ok(!ret
, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i
, ret
);
1419 if (invalid_table
[i
].written
)
1421 ok(count
== invalid_table
[i
].expected_count
,
1422 "[%d] Expected output count to be %u, got %u\n",
1423 i
, invalid_table
[i
].expected_count
, count
);
1425 ok(GetLastError() == invalid_table
[i
].last_error
,
1426 "[%d] Expected last error to be %u, got %u\n",
1427 i
, invalid_table
[i
].last_error
, GetLastError());
1431 ret
= WriteConsoleInputA(input_handle
, NULL
, 0, &count
);
1432 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1433 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1436 ret
= WriteConsoleInputA(input_handle
, &event
, 0, &count
);
1437 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1438 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1441 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1442 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1443 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1445 ret
= FlushConsoleInputBuffer(input_handle
);
1446 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1448 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1449 event
.EventType
= MOUSE_EVENT
;
1450 event
.Event
.MouseEvent
= mouse_event
;
1452 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1453 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1454 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1456 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1457 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1458 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1460 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1461 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1462 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1464 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1465 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1467 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1469 ret
= FlushConsoleInputBuffer(input_handle
);
1470 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1472 for (i
= 0; i
< sizeof(event_list
)/sizeof(event_list
[0]); i
++)
1474 event_list
[i
].EventType
= MOUSE_EVENT
;
1475 event_list
[i
].Event
.MouseEvent
= mouse_event
;
1478 /* Writing consecutive chunks of mouse events appears to work. */
1479 ret
= WriteConsoleInputA(input_handle
, event_list
, sizeof(event_list
)/sizeof(event_list
[0]), &count
);
1480 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1481 ok(count
== sizeof(event_list
)/sizeof(event_list
[0]),
1482 "Expected count to be event list length, got %u\n", count
);
1484 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1485 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1486 ok(count
== sizeof(event_list
)/sizeof(event_list
[0]),
1487 "Expected count to be event list length, got %u\n", count
);
1489 ret
= WriteConsoleInputA(input_handle
, event_list
, sizeof(event_list
)/sizeof(event_list
[0]), &count
);
1490 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1491 ok(count
== sizeof(event_list
)/sizeof(event_list
[0]),
1492 "Expected count to be event list length, got %u\n", count
);
1494 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1495 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1496 ok(count
== 2*sizeof(event_list
)/sizeof(event_list
[0]),
1497 "Expected count to be twice event list length, got %u\n", count
);
1499 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1500 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1501 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1502 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1504 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1505 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1507 ok(count
== 2*sizeof(event_list
)/sizeof(event_list
[0]),
1508 "Expected count to be twice event list length, got %u\n", count
);
1510 ret
= FlushConsoleInputBuffer(input_handle
);
1511 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1513 key_event
.bKeyDown
= FALSE
;
1514 key_event
.wRepeatCount
= 0;
1515 key_event
.wVirtualKeyCode
= VK_SPACE
;
1516 key_event
.wVirtualScanCode
= VK_SPACE
;
1517 key_event
.uChar
.AsciiChar
= ' ';
1518 key_event
.dwControlKeyState
= 0;
1520 event
.EventType
= KEY_EVENT
;
1521 event
.Event
.KeyEvent
= key_event
;
1523 /* Key events don't exhibit the same behavior as mouse events. */
1524 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1525 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1526 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1528 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1529 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1530 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1532 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1533 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1534 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1536 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1537 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1538 ok(count
== 2, "Expected count to be 2, got %u\n", count
);
1540 ret
= FlushConsoleInputBuffer(input_handle
);
1541 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1543 /* Try interleaving mouse and key events. */
1544 event
.EventType
= MOUSE_EVENT
;
1545 event
.Event
.MouseEvent
= mouse_event
;
1547 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1548 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1549 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1551 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1552 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1553 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1555 event
.EventType
= KEY_EVENT
;
1556 event
.Event
.KeyEvent
= key_event
;
1558 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1559 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1560 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1562 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1563 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1564 ok(count
== 2, "Expected count to be 2, got %u\n", count
);
1566 event
.EventType
= MOUSE_EVENT
;
1567 event
.Event
.MouseEvent
= mouse_event
;
1569 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1570 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1571 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1573 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1574 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1575 ok(count
== 3, "Expected count to be 3, got %u\n", count
);
1577 /* Restore the old console mode. */
1578 ret
= SetConsoleMode(input_handle
, console_mode
);
1579 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
1582 static void test_WriteConsoleInputW(HANDLE input_handle
)
1585 INPUT_RECORD event_list
[5];
1586 MOUSE_EVENT_RECORD mouse_event
= { {0, 0}, 0, 0, MOUSE_MOVED
};
1587 KEY_EVENT_RECORD key_event
;
1588 DWORD count
, console_mode
;
1595 const INPUT_RECORD
*buffer
;
1598 DWORD expected_count
;
1603 {NULL
, NULL
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1604 {NULL
, NULL
, 0, &count
, 0, ERROR_INVALID_HANDLE
},
1605 {NULL
, NULL
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1606 {NULL
, NULL
, 1, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1607 {NULL
, &event
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1608 {NULL
, &event
, 0, &count
, 0, ERROR_INVALID_HANDLE
},
1609 {NULL
, &event
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1610 {NULL
, &event
, 1, &count
, 0, ERROR_INVALID_HANDLE
},
1611 {INVALID_HANDLE_VALUE
, NULL
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1612 {INVALID_HANDLE_VALUE
, NULL
, 0, &count
, 0, ERROR_INVALID_HANDLE
},
1613 {INVALID_HANDLE_VALUE
, NULL
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1614 {INVALID_HANDLE_VALUE
, NULL
, 1, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1615 {INVALID_HANDLE_VALUE
, &event
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1616 {INVALID_HANDLE_VALUE
, &event
, 0, &count
, 0, ERROR_INVALID_HANDLE
},
1617 {INVALID_HANDLE_VALUE
, &event
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1618 {INVALID_HANDLE_VALUE
, &event
, 1, &count
, 0, ERROR_INVALID_HANDLE
},
1619 {input_handle
, NULL
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1620 {input_handle
, NULL
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1621 {input_handle
, NULL
, 1, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
},
1622 {input_handle
, &event
, 0, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1623 {input_handle
, &event
, 1, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1626 /* Suppress external sources of input events for the duration of the test. */
1627 ret
= GetConsoleMode(input_handle
, &console_mode
);
1628 ok(ret
== TRUE
, "Expected GetConsoleMode to return TRUE, got %d\n", ret
);
1631 skip("GetConsoleMode failed with last error %u\n", GetLastError());
1635 ret
= SetConsoleMode(input_handle
, console_mode
& ~(ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
));
1636 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
1639 skip("SetConsoleMode failed with last error %u\n", GetLastError());
1643 /* Discard any events queued before the tests. */
1644 ret
= FlushConsoleInputBuffer(input_handle
);
1645 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1647 event
.EventType
= MOUSE_EVENT
;
1648 event
.Event
.MouseEvent
= mouse_event
;
1650 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
1652 if (invalid_table
[i
].win7_crash
)
1655 SetLastError(0xdeadbeef);
1656 if (invalid_table
[i
].written
) count
= 0xdeadbeef;
1657 ret
= WriteConsoleInputW(invalid_table
[i
].handle
,
1658 invalid_table
[i
].buffer
,
1659 invalid_table
[i
].count
,
1660 invalid_table
[i
].written
);
1661 ok(!ret
, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i
, ret
);
1662 if (invalid_table
[i
].written
)
1664 ok(count
== invalid_table
[i
].expected_count
,
1665 "[%d] Expected output count to be %u, got %u\n",
1666 i
, invalid_table
[i
].expected_count
, count
);
1668 ok(GetLastError() == invalid_table
[i
].last_error
,
1669 "[%d] Expected last error to be %u, got %u\n",
1670 i
, invalid_table
[i
].last_error
, GetLastError());
1674 ret
= WriteConsoleInputW(input_handle
, NULL
, 0, &count
);
1675 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1676 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1679 ret
= WriteConsoleInputW(input_handle
, &event
, 0, &count
);
1680 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1681 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1684 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1685 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1686 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1688 ret
= FlushConsoleInputBuffer(input_handle
);
1689 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1691 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1692 event
.EventType
= MOUSE_EVENT
;
1693 event
.Event
.MouseEvent
= mouse_event
;
1695 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1696 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1697 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1699 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1700 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1701 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1703 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1704 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1705 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1707 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1708 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1710 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1712 ret
= FlushConsoleInputBuffer(input_handle
);
1713 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1715 for (i
= 0; i
< sizeof(event_list
)/sizeof(event_list
[0]); i
++)
1717 event_list
[i
].EventType
= MOUSE_EVENT
;
1718 event_list
[i
].Event
.MouseEvent
= mouse_event
;
1721 /* Writing consecutive chunks of mouse events appears to work. */
1722 ret
= WriteConsoleInputW(input_handle
, event_list
, sizeof(event_list
)/sizeof(event_list
[0]), &count
);
1723 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1724 ok(count
== sizeof(event_list
)/sizeof(event_list
[0]),
1725 "Expected count to be event list length, got %u\n", count
);
1727 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1728 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1729 ok(count
== sizeof(event_list
)/sizeof(event_list
[0]),
1730 "Expected count to be event list length, got %u\n", count
);
1732 ret
= WriteConsoleInputW(input_handle
, event_list
, sizeof(event_list
)/sizeof(event_list
[0]), &count
);
1733 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1734 ok(count
== sizeof(event_list
)/sizeof(event_list
[0]),
1735 "Expected count to be event list length, got %u\n", count
);
1737 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1738 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1739 ok(count
== 2*sizeof(event_list
)/sizeof(event_list
[0]),
1740 "Expected count to be twice event list length, got %u\n", count
);
1742 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1743 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1744 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1745 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1747 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1748 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1750 ok(count
== 2*sizeof(event_list
)/sizeof(event_list
[0]),
1751 "Expected count to be twice event list length, got %u\n", count
);
1753 ret
= FlushConsoleInputBuffer(input_handle
);
1754 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1756 key_event
.bKeyDown
= FALSE
;
1757 key_event
.wRepeatCount
= 0;
1758 key_event
.wVirtualKeyCode
= VK_SPACE
;
1759 key_event
.wVirtualScanCode
= VK_SPACE
;
1760 key_event
.uChar
.UnicodeChar
= ' ';
1761 key_event
.dwControlKeyState
= 0;
1763 event
.EventType
= KEY_EVENT
;
1764 event
.Event
.KeyEvent
= key_event
;
1766 /* Key events don't exhibit the same behavior as mouse events. */
1767 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1768 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1769 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1771 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1772 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1773 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1775 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1776 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1777 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1779 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1780 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1781 ok(count
== 2, "Expected count to be 2, got %u\n", count
);
1783 ret
= FlushConsoleInputBuffer(input_handle
);
1784 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1786 /* Try interleaving mouse and key events. */
1787 event
.EventType
= MOUSE_EVENT
;
1788 event
.Event
.MouseEvent
= mouse_event
;
1790 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1791 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1792 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1794 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1795 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1796 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1798 event
.EventType
= KEY_EVENT
;
1799 event
.Event
.KeyEvent
= key_event
;
1801 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1802 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1803 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1805 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1806 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1807 ok(count
== 2, "Expected count to be 2, got %u\n", count
);
1809 event
.EventType
= MOUSE_EVENT
;
1810 event
.Event
.MouseEvent
= mouse_event
;
1812 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1813 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1814 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1816 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1817 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1818 ok(count
== 3, "Expected count to be 3, got %u\n", count
);
1820 /* Restore the old console mode. */
1821 ret
= SetConsoleMode(input_handle
, console_mode
);
1822 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
1825 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle
)
1827 static const char output
[] = {'a', 0};
1829 COORD origin
= {0, 0};
1836 HANDLE hConsoleOutput
;
1840 LPDWORD lpNumCharsWritten
;
1841 DWORD expected_count
;
1846 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1847 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1848 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1849 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1850 {NULL
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1851 {NULL
, output
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1852 {NULL
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1853 {NULL
, output
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1854 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1855 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1856 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1857 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1858 {INVALID_HANDLE_VALUE
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1859 {INVALID_HANDLE_VALUE
, output
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1860 {INVALID_HANDLE_VALUE
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1861 {INVALID_HANDLE_VALUE
, output
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1862 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1863 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1864 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1865 {output_handle
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1866 {output_handle
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1869 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
1871 if (invalid_table
[i
].win7_crash
)
1874 SetLastError(0xdeadbeef);
1875 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
1876 ret
= WriteConsoleOutputCharacterA(invalid_table
[i
].hConsoleOutput
,
1877 invalid_table
[i
].str
,
1878 invalid_table
[i
].length
,
1879 invalid_table
[i
].coord
,
1880 invalid_table
[i
].lpNumCharsWritten
);
1881 ok(!ret
, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i
, ret
);
1882 if (invalid_table
[i
].lpNumCharsWritten
)
1884 ok(count
== invalid_table
[i
].expected_count
,
1885 "[%d] Expected count to be %u, got %u\n",
1886 i
, invalid_table
[i
].expected_count
, count
);
1888 ok(GetLastError() == invalid_table
[i
].last_error
,
1889 "[%d] Expected last error to be %u, got %u\n",
1890 i
, invalid_table
[i
].last_error
, GetLastError());
1894 ret
= WriteConsoleOutputCharacterA(output_handle
, NULL
, 0, origin
, &count
);
1895 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
1896 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1899 ret
= WriteConsoleOutputCharacterA(output_handle
, output
, 0, origin
, &count
);
1900 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
1901 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1904 ret
= WriteConsoleOutputCharacterA(output_handle
, output
, 1, origin
, &count
);
1905 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
1906 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1909 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle
)
1911 static const WCHAR outputW
[] = {'a',0};
1913 COORD origin
= {0, 0};
1920 HANDLE hConsoleOutput
;
1924 LPDWORD lpNumCharsWritten
;
1925 DWORD expected_count
;
1930 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1931 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1932 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1933 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1934 {NULL
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1935 {NULL
, outputW
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1936 {NULL
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1937 {NULL
, outputW
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1938 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1939 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1940 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1941 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1942 {INVALID_HANDLE_VALUE
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1943 {INVALID_HANDLE_VALUE
, outputW
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1944 {INVALID_HANDLE_VALUE
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1945 {INVALID_HANDLE_VALUE
, outputW
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
1946 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1947 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1948 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1949 {output_handle
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1950 {output_handle
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
1953 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
1955 if (invalid_table
[i
].win7_crash
)
1958 SetLastError(0xdeadbeef);
1959 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
1960 ret
= WriteConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
1961 invalid_table
[i
].str
,
1962 invalid_table
[i
].length
,
1963 invalid_table
[i
].coord
,
1964 invalid_table
[i
].lpNumCharsWritten
);
1965 ok(!ret
, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
1966 if (invalid_table
[i
].lpNumCharsWritten
)
1968 ok(count
== invalid_table
[i
].expected_count
,
1969 "[%d] Expected count to be %u, got %u\n",
1970 i
, invalid_table
[i
].expected_count
, count
);
1972 ok(GetLastError() == invalid_table
[i
].last_error
,
1973 "[%d] Expected last error to be %u, got %u\n",
1974 i
, invalid_table
[i
].last_error
, GetLastError());
1978 ret
= WriteConsoleOutputCharacterW(output_handle
, NULL
, 0, origin
, &count
);
1979 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
1980 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1983 ret
= WriteConsoleOutputCharacterW(output_handle
, outputW
, 0, origin
, &count
);
1984 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
1985 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1988 ret
= WriteConsoleOutputCharacterW(output_handle
, outputW
, 1, origin
, &count
);
1989 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
1990 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1993 static void test_WriteConsoleOutputAttribute(HANDLE output_handle
)
1995 WORD attr
= FOREGROUND_BLUE
;
1996 COORD origin
= {0, 0};
2003 HANDLE hConsoleOutput
;
2007 LPDWORD lpNumAttrsWritten
;
2008 DWORD expected_count
;
2013 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2014 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2015 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2016 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2017 {NULL
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2018 {NULL
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2019 {NULL
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2020 {NULL
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2021 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2022 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2023 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2024 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2025 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2026 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2027 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2028 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2029 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2030 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2031 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2032 {output_handle
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2033 {output_handle
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2036 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
2038 if (invalid_table
[i
].win7_crash
)
2041 SetLastError(0xdeadbeef);
2042 if (invalid_table
[i
].lpNumAttrsWritten
) count
= 0xdeadbeef;
2043 ret
= WriteConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
2044 invalid_table
[i
].attr
,
2045 invalid_table
[i
].length
,
2046 invalid_table
[i
].coord
,
2047 invalid_table
[i
].lpNumAttrsWritten
);
2048 ok(!ret
, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
2049 if (invalid_table
[i
].lpNumAttrsWritten
)
2051 ok(count
== invalid_table
[i
].expected_count
,
2052 "[%d] Expected count to be %u, got %u\n",
2053 i
, invalid_table
[i
].expected_count
, count
);
2055 ok(GetLastError() == invalid_table
[i
].last_error
,
2056 "[%d] Expected last error to be %u, got %u\n",
2057 i
, invalid_table
[i
].last_error
, GetLastError());
2061 ret
= WriteConsoleOutputAttribute(output_handle
, NULL
, 0, origin
, &count
);
2062 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2063 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2066 ret
= WriteConsoleOutputAttribute(output_handle
, &attr
, 0, origin
, &count
);
2067 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2068 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2071 ret
= WriteConsoleOutputAttribute(output_handle
, &attr
, 1, origin
, &count
);
2072 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2073 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2076 static void test_FillConsoleOutputCharacterA(HANDLE output_handle
)
2078 COORD origin
= {0, 0};
2085 HANDLE hConsoleOutput
;
2089 LPDWORD lpNumCharsWritten
;
2090 DWORD expected_count
;
2095 {NULL
, 'a', 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2096 {NULL
, 'a', 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2097 {NULL
, 'a', 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2098 {NULL
, 'a', 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2099 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2100 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2101 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2102 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2103 {output_handle
, 'a', 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2104 {output_handle
, 'a', 1, {0, 0}, 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
)
2112 SetLastError(0xdeadbeef);
2113 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2114 ret
= FillConsoleOutputCharacterA(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 FillConsoleOutputCharacterA 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());
2132 ret
= FillConsoleOutputCharacterA(output_handle
, 'a', 0, origin
, &count
);
2133 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2134 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2137 ret
= FillConsoleOutputCharacterA(output_handle
, 'a', 1, origin
, &count
);
2138 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2139 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2142 static void test_FillConsoleOutputCharacterW(HANDLE output_handle
)
2144 COORD origin
= {0, 0};
2151 HANDLE hConsoleOutput
;
2155 LPDWORD lpNumCharsWritten
;
2156 DWORD expected_count
;
2161 {NULL
, 'a', 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2162 {NULL
, 'a', 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2163 {NULL
, 'a', 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2164 {NULL
, 'a', 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2165 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2166 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2167 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2168 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2169 {output_handle
, 'a', 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2170 {output_handle
, 'a', 1, {0, 0}, 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
)
2178 SetLastError(0xdeadbeef);
2179 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2180 ret
= FillConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
2181 invalid_table
[i
].ch
,
2182 invalid_table
[i
].length
,
2183 invalid_table
[i
].coord
,
2184 invalid_table
[i
].lpNumCharsWritten
);
2185 ok(!ret
, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
2186 if (invalid_table
[i
].lpNumCharsWritten
)
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());
2198 ret
= FillConsoleOutputCharacterW(output_handle
, 'a', 0, origin
, &count
);
2199 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2200 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2203 ret
= FillConsoleOutputCharacterW(output_handle
, 'a', 1, origin
, &count
);
2204 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2205 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2208 static void test_FillConsoleOutputAttribute(HANDLE output_handle
)
2210 COORD origin
= {0, 0};
2217 HANDLE hConsoleOutput
;
2221 LPDWORD lpNumAttrsWritten
;
2222 DWORD expected_count
;
2227 {NULL
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2228 {NULL
, FOREGROUND_BLUE
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2229 {NULL
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2230 {NULL
, FOREGROUND_BLUE
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2231 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2232 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2233 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2234 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2235 {output_handle
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2236 {output_handle
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2239 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
2241 if (invalid_table
[i
].win7_crash
)
2244 SetLastError(0xdeadbeef);
2245 if (invalid_table
[i
].lpNumAttrsWritten
) count
= 0xdeadbeef;
2246 ret
= FillConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
2247 invalid_table
[i
].attr
,
2248 invalid_table
[i
].length
,
2249 invalid_table
[i
].coord
,
2250 invalid_table
[i
].lpNumAttrsWritten
);
2251 ok(!ret
, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
2252 if (invalid_table
[i
].lpNumAttrsWritten
)
2254 ok(count
== invalid_table
[i
].expected_count
,
2255 "[%d] Expected count to be %u, got %u\n",
2256 i
, invalid_table
[i
].expected_count
, count
);
2258 ok(GetLastError() == invalid_table
[i
].last_error
,
2259 "[%d] Expected last error to be %u, got %u\n",
2260 i
, invalid_table
[i
].last_error
, GetLastError());
2264 ret
= FillConsoleOutputAttribute(output_handle
, FOREGROUND_BLUE
, 0, origin
, &count
);
2265 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2266 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2269 ret
= FillConsoleOutputAttribute(output_handle
, FOREGROUND_BLUE
, 1, origin
, &count
);
2270 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2271 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2274 ret
= FillConsoleOutputAttribute(output_handle
, ~0, 1, origin
, &count
);
2275 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2276 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2279 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle
)
2282 COORD origin
= {0, 0};
2289 HANDLE hConsoleOutput
;
2294 DWORD expected_count
;
2299 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2300 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2301 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2302 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2303 {NULL
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2304 {NULL
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2305 {NULL
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2306 {NULL
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2307 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2308 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2309 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2310 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2311 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2312 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2313 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2314 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2315 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2316 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2317 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
2318 {output_handle
, NULL
, 10, {0, 0}, &count
, 10, ERROR_INVALID_ACCESS
, 1},
2319 {output_handle
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2320 {output_handle
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2323 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
2325 if (invalid_table
[i
].win7_crash
)
2328 SetLastError(0xdeadbeef);
2329 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
2330 ret
= ReadConsoleOutputCharacterA(invalid_table
[i
].hConsoleOutput
,
2331 invalid_table
[i
].lpstr
,
2332 invalid_table
[i
].length
,
2333 invalid_table
[i
].coord
,
2334 invalid_table
[i
].read_count
);
2335 ok(!ret
, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i
, ret
);
2336 if (invalid_table
[i
].read_count
)
2338 ok(count
== invalid_table
[i
].expected_count
,
2339 "[%d] Expected count to be %u, got %u\n",
2340 i
, invalid_table
[i
].expected_count
, count
);
2342 ok(GetLastError() == invalid_table
[i
].last_error
,
2343 "[%d] Expected last error to be %u, got %u\n",
2344 i
, invalid_table
[i
].last_error
, GetLastError());
2348 ret
= ReadConsoleOutputCharacterA(output_handle
, NULL
, 0, origin
, &count
);
2349 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2350 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2353 ret
= ReadConsoleOutputCharacterA(output_handle
, &read
, 0, origin
, &count
);
2354 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2355 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2358 ret
= ReadConsoleOutputCharacterA(output_handle
, &read
, 1, origin
, &count
);
2359 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2360 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2363 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle
)
2366 COORD origin
= {0, 0};
2373 HANDLE hConsoleOutput
;
2378 DWORD expected_count
;
2383 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2384 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2385 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2386 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2387 {NULL
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2388 {NULL
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2389 {NULL
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2390 {NULL
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2391 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2392 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2393 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2394 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2395 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2396 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2397 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2398 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2399 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2400 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2401 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
2402 {output_handle
, NULL
, 10, {0, 0}, &count
, 10, ERROR_INVALID_ACCESS
, 1},
2403 {output_handle
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2404 {output_handle
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2407 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
2409 if (invalid_table
[i
].win7_crash
)
2412 SetLastError(0xdeadbeef);
2413 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
2414 ret
= ReadConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
2415 invalid_table
[i
].buffer
,
2416 invalid_table
[i
].length
,
2417 invalid_table
[i
].coord
,
2418 invalid_table
[i
].read_count
);
2419 ok(!ret
, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
2420 if (invalid_table
[i
].read_count
)
2422 ok(count
== invalid_table
[i
].expected_count
,
2423 "[%d] Expected count to be %u, got %u\n",
2424 i
, invalid_table
[i
].expected_count
, count
);
2426 ok(GetLastError() == invalid_table
[i
].last_error
,
2427 "[%d] Expected last error to be %u, got %u\n",
2428 i
, invalid_table
[i
].last_error
, GetLastError());
2432 ret
= ReadConsoleOutputCharacterW(output_handle
, NULL
, 0, origin
, &count
);
2433 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2434 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2437 ret
= ReadConsoleOutputCharacterW(output_handle
, &read
, 0, origin
, &count
);
2438 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2439 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2442 ret
= ReadConsoleOutputCharacterW(output_handle
, &read
, 1, origin
, &count
);
2443 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2444 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2447 static void test_ReadConsoleOutputAttribute(HANDLE output_handle
)
2450 COORD origin
= {0, 0};
2457 HANDLE hConsoleOutput
;
2462 DWORD expected_count
;
2467 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2468 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2469 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2470 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2471 {NULL
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2472 {NULL
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2473 {NULL
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2474 {NULL
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2475 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2476 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2477 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2478 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2479 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2480 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2481 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2482 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2483 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2484 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2485 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
2486 {output_handle
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2487 {output_handle
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2490 for (i
= 0; i
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); i
++)
2492 if (invalid_table
[i
].win7_crash
)
2495 SetLastError(0xdeadbeef);
2496 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
2497 ret
= ReadConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
2498 invalid_table
[i
].lpAttribute
,
2499 invalid_table
[i
].length
,
2500 invalid_table
[i
].coord
,
2501 invalid_table
[i
].read_count
);
2502 ok(!ret
, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
2503 if (invalid_table
[i
].read_count
)
2505 ok(count
== invalid_table
[i
].expected_count
,
2506 "[%d] Expected count to be %u, got %u\n",
2507 i
, invalid_table
[i
].expected_count
, count
);
2509 ok(GetLastError() == invalid_table
[i
].last_error
,
2510 "[%d] Expected last error to be %u, got %u\n",
2511 i
, invalid_table
[i
].last_error
, GetLastError());
2515 ret
= ReadConsoleOutputAttribute(output_handle
, NULL
, 0, origin
, &count
);
2516 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2517 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2520 ret
= ReadConsoleOutputAttribute(output_handle
, &attr
, 0, origin
, &count
);
2521 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2522 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2525 ret
= ReadConsoleOutputAttribute(output_handle
, &attr
, 1, origin
, &count
);
2526 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2527 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2532 static const char font_name
[] = "Lucida Console";
2533 HANDLE hConIn
, hConOut
;
2535 CONSOLE_SCREEN_BUFFER_INFO sbi
;
2538 char old_font
[LF_FACESIZE
];
2539 BOOL
delete = FALSE
;
2542 init_function_pointers();
2544 /* be sure we have a clean console (and that's our own)
2545 * FIXME: this will make the test fail (currently) if we don't run
2547 * Another solution would be to rerun the test under wineconsole with
2548 * the curses backend
2551 /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
2552 * correctly for characters that don't have a glyph in the console font. So,
2553 * we first set the console font to Lucida Console (which has a wider
2554 * selection of glyphs available than the default raster fonts). We want
2555 * to be able to restore the original font afterwards, so don't change
2556 * if we can't read the original font.
2558 err
= RegOpenKeyExA(HKEY_CURRENT_USER
, "Console", 0,
2559 KEY_QUERY_VALUE
| KEY_SET_VALUE
, &console_key
);
2560 if (err
== ERROR_SUCCESS
)
2562 size
= sizeof(old_font
);
2563 err
= RegQueryValueExA(console_key
, "FaceName", NULL
, NULL
,
2564 (LPBYTE
) old_font
, &size
);
2565 if (err
== ERROR_SUCCESS
|| err
== ERROR_FILE_NOT_FOUND
)
2567 delete = (err
== ERROR_FILE_NOT_FOUND
);
2568 err
= RegSetValueExA(console_key
, "FaceName", 0, REG_SZ
,
2569 (const BYTE
*) font_name
, sizeof(font_name
));
2570 if (err
!= ERROR_SUCCESS
)
2571 trace("Unable to change default console font, error %d\n", err
);
2575 trace("Unable to query default console font, error %d\n", err
);
2576 RegCloseKey(console_key
);
2582 trace("Unable to open HKCU\\Console, error %d\n", err
);
2586 /* Now detach and open a fresh console to play with */
2588 ok(AllocConsole(), "Couldn't alloc console\n");
2590 /* Restore default console font if needed */
2591 if (console_key
!= NULL
)
2594 err
= RegDeleteValueA(console_key
, "FaceName");
2596 err
= RegSetValueExA(console_key
, "FaceName", 0, REG_SZ
,
2597 (const BYTE
*) old_font
, strlen(old_font
) + 1);
2598 ok(err
== ERROR_SUCCESS
, "Unable to restore default console font, error %d\n", err
);
2600 hConIn
= CreateFileA("CONIN$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
2601 hConOut
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
2603 /* now verify everything's ok */
2604 ok(hConIn
!= INVALID_HANDLE_VALUE
, "Opening ConIn\n");
2605 ok(hConOut
!= INVALID_HANDLE_VALUE
, "Opening ConOut\n");
2607 ret
= GetConsoleScreenBufferInfo(hConOut
, &sbi
);
2608 ok(ret
, "Getting sb info\n");
2611 /* Non interactive tests */
2612 testCursor(hConOut
, sbi
.dwSize
);
2613 /* test parameters (FIXME: test functionality) */
2614 testCursorInfo(hConOut
);
2615 /* will test wrapped (on/off) & processed (on/off) strings output */
2616 testWrite(hConOut
, sbi
.dwSize
);
2617 /* will test line scrolling at the bottom of the screen */
2618 /* testBottomScroll(); */
2619 /* will test all the scrolling operations */
2620 testScroll(hConOut
, sbi
.dwSize
);
2621 /* will test sb creation / modification / codepage handling */
2622 testScreenBuffer(hConOut
);
2624 /* still to be done: access rights & access on objects */
2626 if (!pGetConsoleInputExeNameA
|| !pSetConsoleInputExeNameA
)
2627 win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
2629 test_GetSetConsoleInputExeName();
2631 test_GetConsoleProcessList();
2632 test_OpenConsoleW();
2635 test_VerifyConsoleIoHandle(hConOut
);
2636 test_GetSetStdHandle();
2637 test_GetNumberOfConsoleInputEvents(hConIn
);
2638 test_WriteConsoleInputA(hConIn
);
2639 test_WriteConsoleInputW(hConIn
);
2640 test_WriteConsoleOutputCharacterA(hConOut
);
2641 test_WriteConsoleOutputCharacterW(hConOut
);
2642 test_WriteConsoleOutputAttribute(hConOut
);
2643 test_FillConsoleOutputCharacterA(hConOut
);
2644 test_FillConsoleOutputCharacterW(hConOut
);
2645 test_FillConsoleOutputAttribute(hConOut
);
2646 test_ReadConsoleOutputCharacterA(hConOut
);
2647 test_ReadConsoleOutputCharacterW(hConOut
);
2648 test_ReadConsoleOutputAttribute(hConOut
);