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
23 #define WIN32_NO_STATUS
29 #include "wine/test.h"
31 static void (WINAPI
*pClosePseudoConsole
)(HPCON
);
32 static HRESULT (WINAPI
*pCreatePseudoConsole
)(COORD
,HANDLE
,HANDLE
,DWORD
,HPCON
*);
33 static BOOL (WINAPI
*pGetConsoleInputExeNameA
)(DWORD
, LPSTR
);
34 static DWORD (WINAPI
*pGetConsoleProcessList
)(LPDWORD
, DWORD
);
35 static HANDLE (WINAPI
*pOpenConsoleW
)(LPCWSTR
,DWORD
,BOOL
,DWORD
);
36 static BOOL (WINAPI
*pSetConsoleInputExeNameA
)(LPCSTR
);
37 static BOOL (WINAPI
*pVerifyConsoleIoHandle
)(HANDLE handle
);
41 /* DEFAULT_ATTRIB is used for all initial filling of the console.
42 * all modifications are made with TEST_ATTRIB so that we could check
43 * what has to be modified or not
45 #define TEST_ATTRIB (BACKGROUND_BLUE | FOREGROUND_GREEN)
46 #define DEFAULT_ATTRIB (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED)
47 /* when filling the screen with non-blank chars, this macro defines
48 * what character should be at position 'c'
50 #define CONTENT(c) ('A' + (((c).Y * 17 + (c).X) % 23))
52 #define okCURSOR(hCon, c) do { \
53 CONSOLE_SCREEN_BUFFER_INFO __sbi; \
54 BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
55 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
56 ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
57 (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
60 #define okCHAR(hCon, c, ch, attr) do { \
61 char __ch; WORD __attr; DWORD __len; BOOL expect; \
62 expect = ReadConsoleOutputCharacterA((hCon), &__ch, 1, (c), &__len) == 1 && __len == 1 && __ch == (ch); \
63 ok(expect, "At (%d,%d): expecting char '%c'/%02x got '%c'/%02x\n", (c).X, (c).Y, (ch), (ch), __ch, __ch); \
64 expect = ReadConsoleOutputAttribute((hCon), &__attr, 1, (c), &__len) == 1 && __len == 1 && __attr == (attr); \
65 ok(expect, "At (%d,%d): expecting attr %04x got %04x\n", (c).X, (c).Y, (attr), __attr); \
68 static void init_function_pointers(void)
72 #define KERNEL32_GET_PROC(func) \
73 p##func = (void *)GetProcAddress(hKernel32, #func); \
74 if(!p##func) trace("GetProcAddress(hKernel32, '%s') failed\n", #func);
76 hKernel32
= GetModuleHandleA("kernel32.dll");
77 KERNEL32_GET_PROC(ClosePseudoConsole
);
78 KERNEL32_GET_PROC(CreatePseudoConsole
);
79 KERNEL32_GET_PROC(GetConsoleInputExeNameA
);
80 KERNEL32_GET_PROC(GetConsoleProcessList
);
81 KERNEL32_GET_PROC(OpenConsoleW
);
82 KERNEL32_GET_PROC(SetConsoleInputExeNameA
);
83 KERNEL32_GET_PROC(VerifyConsoleIoHandle
);
85 #undef KERNEL32_GET_PROC
88 static HANDLE
create_unbound_handle(BOOL output
, BOOL test_status
)
90 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
96 attr
.ObjectName
= &name
;
97 attr
.Attributes
= OBJ_INHERIT
;
98 RtlInitUnicodeString( &name
, output
? L
"\\Device\\ConDrv\\Output" : L
"\\Device\\ConDrv\\Input" );
99 status
= NtCreateFile( &handle
, FILE_READ_DATA
| FILE_WRITE_DATA
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
|
100 FILE_WRITE_ATTRIBUTES
, &attr
, &iosb
, NULL
, FILE_ATTRIBUTE_NORMAL
,
101 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
, FILE_CREATE
,
102 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
103 if (test_status
) ok(!status
, "NtCreateFile failed: %#x\n", status
);
104 return status
? NULL
: handle
;
107 /* FIXME: this could be optimized on a speed point of view */
108 static void resetContent(HANDLE hCon
, COORD sbSize
, BOOL content
)
111 WORD attr
= DEFAULT_ATTRIB
;
115 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
117 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
119 ch
= (content
) ? CONTENT(c
) : ' ';
120 WriteConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
121 WriteConsoleOutputCharacterA(hCon
, &ch
, 1, c
, &len
);
126 static void testCursor(HANDLE hCon
, COORD sbSize
)
131 ok(SetConsoleCursorPosition(0, c
) == 0, "No handle\n");
132 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %u\n",
133 ERROR_INVALID_HANDLE
, GetLastError());
136 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
141 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in lower-right\n");
146 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
147 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %u\n",
148 ERROR_INVALID_PARAMETER
, GetLastError());
152 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
153 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %u\n",
154 ERROR_INVALID_PARAMETER
, GetLastError());
158 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
159 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %u\n",
160 ERROR_INVALID_PARAMETER
, GetLastError());
164 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
165 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %u\n",
166 ERROR_INVALID_PARAMETER
, GetLastError());
169 static void testCursorInfo(HANDLE hCon
)
172 CONSOLE_CURSOR_INFO info
;
175 SetLastError(0xdeadbeef);
176 ret
= GetConsoleCursorInfo(NULL
, NULL
);
177 ok(!ret
, "Expected failure\n");
178 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %u\n",
179 ERROR_INVALID_HANDLE
, GetLastError());
181 SetLastError(0xdeadbeef);
183 ret
= GetConsoleCursorInfo(NULL
, &info
);
184 ok(!ret
, "Expected failure\n");
185 ok(info
.dwSize
== -1, "Expected no change for dwSize\n");
186 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %u\n",
187 ERROR_INVALID_HANDLE
, GetLastError());
189 /* Test the correct call first to distinguish between win9x and the rest */
190 SetLastError(0xdeadbeef);
191 ret
= GetConsoleCursorInfo(hCon
, &info
);
192 ok(ret
, "Expected success\n");
193 ok(info
.dwSize
== 25 ||
194 info
.dwSize
== 12 /* win9x */,
195 "Expected 12 or 25, got %d\n", info
.dwSize
);
196 ok(info
.bVisible
, "Expected the cursor to be visible\n");
197 ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %u\n",
198 0xdeadbeef, GetLastError());
200 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
202 ret
= GetConsoleCursorInfo(pipe1
, &info
);
203 ok(!ret
, "Expected failure\n");
204 ok(info
.dwSize
== -1, "Expected no change for dwSize\n");
205 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: %u\n", GetLastError());
209 /* Don't test NULL CONSOLE_CURSOR_INFO, it crashes on win9x and win7 */
212 static void testEmptyWrite(HANDLE hCon
)
214 static const char emptybuf
[16];
219 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
222 ok(WriteConsoleA(hCon
, NULL
, 0, &len
, NULL
) != 0 && len
== 0, "WriteConsole\n");
225 /* Passing a NULL lpBuffer with sufficiently large non-zero length succeeds
226 * on native Windows and result in memory-like contents being written to
227 * the console. Calling WriteConsoleW like this will crash on Wine. */
231 ok(!WriteConsoleA(hCon
, NULL
, 16, &len
, NULL
) && len
== -1, "WriteConsole\n");
234 /* Cursor advances for this call. */
236 ok(WriteConsoleA(hCon
, NULL
, 128, &len
, NULL
) != 0 && len
== 128, "WriteConsole\n");
240 ok(WriteConsoleA(hCon
, emptybuf
, 0, &len
, NULL
) != 0 && len
== 0, "WriteConsole\n");
243 /* WriteConsole does not halt on a null terminator and is happy to write
244 * memory contents beyond the actual size of the buffer. */
246 ok(WriteConsoleA(hCon
, emptybuf
, 16, &len
, NULL
) != 0 && len
== 16, "WriteConsole\n");
251 static void simple_write_console(HANDLE console
, const char *text
)
257 /* single line write */
259 ok(SetConsoleCursorPosition(console
, c
) != 0, "Cursor in upper-left\n");
261 ret
= WriteConsoleA(console
, text
, strlen(text
), &len
, NULL
);
262 ok(ret
, "WriteConsoleA failed: %u\n", GetLastError());
263 ok(len
== strlen(text
), "unexpected len %u\n", len
);
266 static void testWriteSimple(HANDLE hCon
)
268 const char* mytest
= "abcdefg";
269 int mylen
= strlen(mytest
);
274 simple_write_console(hCon
, mytest
);
276 for (c
.X
= 0; c
.X
< mylen
; c
.X
++)
278 okCHAR(hCon
, c
, mytest
[c
.X
], TEST_ATTRIB
);
282 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
284 ret
= WriteFile(hCon
, mytest
, mylen
, &len
, NULL
);
285 ok(ret
, "WriteFile failed: %u\n", GetLastError());
286 ok(len
== mylen
, "unexpected len = %u\n", len
);
288 for (c
.X
= 0; c
.X
< 2 * mylen
; c
.X
++)
290 okCHAR(hCon
, c
, mytest
[c
.X
% mylen
], TEST_ATTRIB
);
294 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
297 static void testWriteNotWrappedNotProcessed(HANDLE hCon
, COORD sbSize
)
301 const char* mytest
= "123";
302 const int mylen
= strlen(mytest
);
306 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, mode
& ~(ENABLE_PROCESSED_OUTPUT
|ENABLE_WRAP_AT_EOL_OUTPUT
)),
307 "clearing wrap at EOL & processed output\n");
309 /* write line, wrapping disabled, buffer exceeds sb width */
310 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
311 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
313 ret
= WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
);
314 ok(ret
!= 0 && len
== mylen
, "Couldn't write, ret = %d, len = %d\n", ret
, len
);
316 for (p
= mylen
- 3; p
< mylen
; p
++)
318 c
.X
= sbSize
.X
- 3 + p
% 3;
319 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
323 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
325 p
= sbSize
.X
- 3 + mylen
% 3;
328 /* write line, wrapping disabled, strings end on end of line */
329 c
.X
= sbSize
.X
- mylen
; c
.Y
= 0;
330 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
332 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
335 static void testWriteNotWrappedProcessed(HANDLE hCon
, COORD sbSize
)
339 const char* mytest
= "abcd\nf\tg";
340 const int mylen
= strlen(mytest
);
341 const int mylen2
= strchr(mytest
, '\n') - mytest
;
345 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, (mode
| ENABLE_PROCESSED_OUTPUT
) &
346 ~(ENABLE_WRAP_AT_EOL_OUTPUT
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
)),
347 "clearing wrap at EOL & setting processed output\n");
349 /* write line, wrapping disabled, buffer exceeds sb width */
350 c
.X
= sbSize
.X
- 5; c
.Y
= 0;
351 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-5\n");
353 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
355 for (c
.X
= sbSize
.X
- 5; c
.X
< sbSize
.X
- 1; c
.X
++)
357 okCHAR(hCon
, c
, mytest
[c
.X
- sbSize
.X
+ 5], TEST_ATTRIB
);
360 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
361 /* Win9x and WinMe change the attribs for '\n' up to 'f' */
362 if (attr
== TEST_ATTRIB
)
364 win_skip("Win9x/WinMe don't respect ~ENABLE_WRAP_AT_EOL_OUTPUT\n");
368 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
371 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
372 for (c
.X
= 1; c
.X
< 8; c
.X
++)
373 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
374 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
376 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
380 /* write line, wrapping disabled, strings end on end of line */
381 c
.X
= sbSize
.X
- 4; c
.Y
= 0;
382 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-4\n");
384 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
386 for (c
.X
= sbSize
.X
- 4; c
.X
< sbSize
.X
; c
.X
++)
388 okCHAR(hCon
, c
, mytest
[c
.X
- sbSize
.X
+ 4], TEST_ATTRIB
);
391 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
392 for (c
.X
= 1; c
.X
< 8; c
.X
++)
393 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
394 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
396 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
400 /* write line, wrapping disabled, strings end after end of line */
401 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
402 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-4\n");
404 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
406 for (p
= mylen2
- 3; p
< mylen2
; p
++)
408 c
.X
= sbSize
.X
- 3 + p
% 3;
409 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
412 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
413 for (c
.X
= 1; c
.X
< 8; c
.X
++)
414 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
415 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
417 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
422 static void testWriteWrappedNotProcessed(HANDLE hCon
, COORD sbSize
)
426 const char* mytest
= "abcd\nf\tg";
427 const int mylen
= strlen(mytest
);
430 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
,(mode
| ENABLE_WRAP_AT_EOL_OUTPUT
) & ~(ENABLE_PROCESSED_OUTPUT
)),
431 "setting wrap at EOL & clearing processed output\n");
433 /* write line, wrapping enabled, buffer doesn't exceed sb width */
434 c
.X
= sbSize
.X
- 9; c
.Y
= 0;
435 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-9\n");
437 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
439 for (p
= 0; p
< mylen
; p
++)
441 c
.X
= sbSize
.X
- 9 + p
;
442 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
444 c
.X
= sbSize
.X
- 9 + mylen
;
445 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
447 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
449 /* write line, wrapping enabled, buffer does exceed sb width */
450 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
451 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
455 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
458 static void testWriteWrappedProcessed(HANDLE hCon
, COORD sbSize
)
462 const char* mytest
= "abcd\nf\tg";
463 const int mylen
= strlen(mytest
);
467 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, mode
| (ENABLE_WRAP_AT_EOL_OUTPUT
|ENABLE_PROCESSED_OUTPUT
)),
468 "setting wrap at EOL & processed output\n");
470 /* write line, wrapping enabled, buffer doesn't exceed sb width */
471 c
.X
= sbSize
.X
- 9; c
.Y
= 0;
472 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-9\n");
474 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
475 for (p
= 0; p
< 4; p
++)
477 c
.X
= sbSize
.X
- 9 + p
;
478 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
480 c
.X
= sbSize
.X
- 9 + p
;
481 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
482 if (attr
== TEST_ATTRIB
)
483 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n");
485 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
487 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
488 for (c
.X
= 1; c
.X
< 8; c
.X
++)
489 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
490 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
492 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
495 /* write line, wrapping enabled, buffer does exceed sb width */
496 c
.X
= sbSize
.X
- 3; c
.Y
= 2;
497 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
499 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
500 for (p
= 0; p
< 3; p
++)
502 c
.X
= sbSize
.X
- 3 + p
;
503 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
506 okCHAR(hCon
, c
, mytest
[3], TEST_ATTRIB
);
508 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
509 if (attr
== TEST_ATTRIB
)
510 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n");
512 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
515 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
516 for (c
.X
= 1; c
.X
< 8; c
.X
++)
517 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
518 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
520 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
524 static void testWrite(HANDLE hCon
, COORD sbSize
)
526 /* FIXME: should in fact ensure that the sb is at least 10 characters wide */
527 ok(SetConsoleTextAttribute(hCon
, TEST_ATTRIB
), "Setting default text color\n");
528 resetContent(hCon
, sbSize
, FALSE
);
529 testEmptyWrite(hCon
);
530 resetContent(hCon
, sbSize
, FALSE
);
531 testWriteSimple(hCon
);
532 resetContent(hCon
, sbSize
, FALSE
);
533 testWriteNotWrappedNotProcessed(hCon
, sbSize
);
534 resetContent(hCon
, sbSize
, FALSE
);
535 testWriteNotWrappedProcessed(hCon
, sbSize
);
536 resetContent(hCon
, sbSize
, FALSE
);
537 testWriteWrappedNotProcessed(hCon
, sbSize
);
538 resetContent(hCon
, sbSize
, FALSE
);
539 testWriteWrappedProcessed(hCon
, sbSize
);
542 static void testScroll(HANDLE hCon
, COORD sbSize
)
544 SMALL_RECT scroll
, clip
;
552 #define IN_SRECT(r,c) ((r).Left <= (c).X && (c).X <= (r).Right && (r).Top <= (c).Y && (c).Y <= (r).Bottom)
553 #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)
555 /* no clipping, src & dst rect don't overlap */
556 resetContent(hCon
, sbSize
, TRUE
);
559 scroll
.Right
= W
- 1;
561 scroll
.Bottom
= H
- 1;
564 ci
.Char
.UnicodeChar
= '#';
565 ci
.Attributes
= TEST_ATTRIB
;
568 clip
.Right
= sbSize
.X
- 1;
570 clip
.Bottom
= sbSize
.Y
- 1;
572 ok(ScrollConsoleScreenBufferA(hCon
, &scroll
, NULL
, dst
, &ci
), "Scrolling SB\n");
574 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
576 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
578 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
582 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
584 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
585 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
586 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
590 /* no clipping, src & dst rect do overlap */
591 resetContent(hCon
, sbSize
, TRUE
);
594 scroll
.Right
= W
- 1;
596 scroll
.Bottom
= H
- 1;
599 ci
.Char
.UnicodeChar
= '#';
600 ci
.Attributes
= TEST_ATTRIB
;
603 clip
.Right
= sbSize
.X
- 1;
605 clip
.Bottom
= sbSize
.Y
- 1;
607 ok(ScrollConsoleScreenBufferA(hCon
, &scroll
, NULL
, dst
, &ci
), "Scrolling SB\n");
609 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
611 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
613 if (dst
.X
<= c
.X
&& c
.X
< dst
.X
+ W
&& dst
.Y
<= c
.Y
&& c
.Y
< dst
.Y
+ H
)
617 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
619 else if (c
.X
< W
&& c
.Y
< H
) okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
620 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
624 /* clipping, src & dst rect don't overlap */
625 resetContent(hCon
, sbSize
, TRUE
);
628 scroll
.Right
= W
- 1;
630 scroll
.Bottom
= H
- 1;
633 ci
.Char
.UnicodeChar
= '#';
634 ci
.Attributes
= TEST_ATTRIB
;
637 clip
.Right
= min(W
+ W
/ 2, sbSize
.X
- 1);
639 clip
.Bottom
= min(H
+ H
/ 2, sbSize
.Y
- 1);
641 SetLastError(0xdeadbeef);
642 ret
= ScrollConsoleScreenBufferA(hCon
, &scroll
, &clip
, dst
, &ci
);
645 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
647 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
649 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
653 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
655 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
656 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
657 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
663 /* Win9x will fail, Only accept ERROR_NOT_ENOUGH_MEMORY */
664 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
,
665 "Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
668 /* clipping, src & dst rect do overlap */
669 resetContent(hCon
, sbSize
, TRUE
);
672 scroll
.Right
= W
- 1;
674 scroll
.Bottom
= H
- 1;
677 ci
.Char
.UnicodeChar
= '#';
678 ci
.Attributes
= TEST_ATTRIB
;
681 clip
.Right
= min(W
+ W
/ 2, sbSize
.X
- 1);
683 clip
.Bottom
= min(H
+ H
/ 2, sbSize
.Y
- 1);
685 ret
= ScrollConsoleScreenBufferA(hCon
, &scroll
, &clip
, dst
, &ci
);
686 ok(ret
, "ScrollConsoleScreenBufferA failed: %u\n", GetLastError());
688 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
690 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
692 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
696 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
698 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
699 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
700 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
705 static int mch_count
;
706 /* we need the event as Wine console event generation isn't synchronous
707 * (ie GenerateConsoleCtrlEvent returns before all ctrl-handlers in all
708 * processes have been called).
710 static HANDLE mch_event
;
711 static BOOL WINAPI
mch(DWORD event
)
718 static void testCtrlHandler(void)
720 ok(!SetConsoleCtrlHandler(mch
, FALSE
), "Shouldn't succeed\n");
721 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Bad error %u\n", GetLastError());
722 ok(SetConsoleCtrlHandler(mch
, TRUE
), "Couldn't set handler\n");
723 /* wine requires the event for the test, as we cannot ensure, so far, that
724 * events are processed synchronously in GenerateConsoleCtrlEvent()
726 mch_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
728 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT
, 0), "Couldn't send ctrl-c event\n");
729 /* FIXME: it isn't synchronous on wine but it can still happen before we test */
730 if (0) ok(mch_count
== 1, "Event isn't synchronous\n");
731 ok(WaitForSingleObject(mch_event
, 3000) == WAIT_OBJECT_0
, "event sending didn't work\n");
732 CloseHandle(mch_event
);
734 /* Turning off ctrl-c handling doesn't work on win9x such way ... */
735 ok(SetConsoleCtrlHandler(NULL
, TRUE
), "Couldn't turn off ctrl-c handling\n");
736 mch_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
738 if(!(GetVersion() & 0x80000000))
739 /* ... and next line leads to an unhandled exception on 9x. Avoid it on 9x. */
740 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT
, 0), "Couldn't send ctrl-c event\n");
741 ok(WaitForSingleObject(mch_event
, 3000) == WAIT_TIMEOUT
&& mch_count
== 0, "Event shouldn't have been sent\n");
742 CloseHandle(mch_event
);
743 ok(SetConsoleCtrlHandler(mch
, FALSE
), "Couldn't remove handler\n");
744 ok(!SetConsoleCtrlHandler(mch
, FALSE
), "Shouldn't succeed\n");
745 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Bad error %u\n", GetLastError());
749 * Test console screen buffer:
750 * 1) Try to set invalid handle.
751 * 2) Try to set non-console handles.
752 * 3) Use CONOUT$ file as active SB.
754 * 5) Test output codepage to show it is not a property of SB.
755 * 6) Test switching to old SB if we close all handles to current SB - works
756 * in Windows, TODO in wine.
758 * What is not tested but should be:
759 * 1) ScreenBufferInfo
761 static void testScreenBuffer(HANDLE hConOut
)
763 HANDLE hConOutRW
, hConOutRO
, hConOutWT
;
764 HANDLE hFileOutRW
, hFileOutRO
, hFileOutWT
;
766 char test_str1
[] = "Test for SB1";
767 char test_str2
[] = "Test for SB2";
768 char test_cp866
[] = {0xe2, 0xa5, 0xe1, 0xe2, 0};
769 char test_cp1251
[] = {0xf2, 0xe5, 0xf1, 0xf2, 0};
770 WCHAR test_unicode
[] = {0x0442, 0x0435, 0x0441, 0x0442, 0};
778 if (!IsValidCodePage(866))
780 skip("Codepage 866 not available\n");
784 /* In the beginning set output codepage to 866 */
785 oldcp
= GetConsoleOutputCP();
786 SetLastError(0xdeadbeef);
787 ret
= SetConsoleOutputCP(866);
788 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
790 win_skip("SetConsoleOutputCP is not implemented\n");
793 ok(ret
, "Cannot set output codepage to 866\n");
795 hConOutRW
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
796 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
797 CONSOLE_TEXTMODE_BUFFER
, NULL
);
798 ok(hConOutRW
!= INVALID_HANDLE_VALUE
,
799 "Cannot create a new screen buffer for ReadWrite\n");
800 hConOutRO
= CreateConsoleScreenBuffer(GENERIC_READ
,
801 FILE_SHARE_READ
, NULL
,
802 CONSOLE_TEXTMODE_BUFFER
, NULL
);
803 ok(hConOutRO
!= INVALID_HANDLE_VALUE
,
804 "Cannot create a new screen buffer for ReadOnly\n");
805 hConOutWT
= CreateConsoleScreenBuffer(GENERIC_WRITE
,
806 FILE_SHARE_WRITE
, NULL
,
807 CONSOLE_TEXTMODE_BUFFER
, NULL
);
808 ok(hConOutWT
!= INVALID_HANDLE_VALUE
,
809 "Cannot create a new screen buffer for WriteOnly\n");
811 hFileOutRW
= CreateFileA("NUL", GENERIC_READ
| GENERIC_WRITE
,
812 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
813 OPEN_EXISTING
, 0, NULL
);
814 ok(hFileOutRW
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for ReadWrite\n");
815 hFileOutRO
= CreateFileA("NUL", GENERIC_READ
, FILE_SHARE_READ
,
816 NULL
, OPEN_EXISTING
, 0, NULL
);
817 ok(hFileOutRO
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for ReadOnly\n");
818 hFileOutWT
= CreateFileA("NUL", GENERIC_WRITE
, FILE_SHARE_WRITE
,
819 NULL
, OPEN_EXISTING
, 0, NULL
);
820 ok(hFileOutWT
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for WriteOnly\n");
822 /* Trying to set invalid handle */
824 ok(!SetConsoleActiveScreenBuffer(INVALID_HANDLE_VALUE
),
825 "Shouldn't succeed\n");
826 ok(GetLastError() == ERROR_INVALID_HANDLE
,
827 "GetLastError: expecting %u got %u\n",
828 ERROR_INVALID_HANDLE
, GetLastError());
830 /* Trying to set non-console handles */
832 ok(!SetConsoleActiveScreenBuffer(hFileOutRW
), "Shouldn't succeed\n");
833 ok(GetLastError() == ERROR_INVALID_HANDLE
,
834 "GetLastError: expecting %u got %u\n",
835 ERROR_INVALID_HANDLE
, GetLastError());
838 ok(!SetConsoleActiveScreenBuffer(hFileOutRO
), "Shouldn't succeed\n");
839 ok(GetLastError() == ERROR_INVALID_HANDLE
,
840 "GetLastError: expecting %u got %u\n",
841 ERROR_INVALID_HANDLE
, GetLastError());
844 ok(!SetConsoleActiveScreenBuffer(hFileOutWT
), "Shouldn't succeed\n");
845 ok(GetLastError() == ERROR_INVALID_HANDLE
,
846 "GetLastError: expecting %u got %u\n",
847 ERROR_INVALID_HANDLE
, GetLastError());
849 /* trying to write non-console handle */
850 SetLastError(0xdeadbeef);
851 ret
= WriteConsoleA(hFileOutRW
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
852 error
= GetLastError();
853 ok(!ret
, "Shouldn't succeed\n");
854 ok(error
== ERROR_INVALID_HANDLE
|| error
== ERROR_INVALID_FUNCTION
,
855 "GetLastError: got %u\n", error
);
857 SetLastError(0xdeadbeef);
858 ret
= WriteConsoleA(hFileOutRO
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
859 error
= GetLastError();
860 ok(!ret
, "Shouldn't succeed\n");
861 ok(error
== ERROR_INVALID_HANDLE
|| error
== ERROR_INVALID_FUNCTION
,
862 "GetLastError: got %u\n", error
);
864 SetLastError(0xdeadbeef);
865 ret
= WriteConsoleA(hFileOutWT
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
866 error
= GetLastError();
867 ok(!ret
, "Shouldn't succeed\n");
868 ok(error
== ERROR_INVALID_HANDLE
|| error
== ERROR_INVALID_FUNCTION
,
869 "GetLastError: got %u\n", error
);
871 CloseHandle(hFileOutRW
);
872 CloseHandle(hFileOutRO
);
873 CloseHandle(hFileOutWT
);
875 /* Trying to set SB handles with various access modes */
877 ok(!SetConsoleActiveScreenBuffer(hConOutRO
), "Shouldn't succeed\n");
878 ok(GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_ACCESS_DENIED
) /* win10 1809 */,
879 "unexpected last error %u\n", GetLastError());
881 ok(SetConsoleActiveScreenBuffer(hConOutWT
), "Couldn't set new WriteOnly SB\n");
883 ok(SetConsoleActiveScreenBuffer(hConOutRW
), "Couldn't set new ReadWrite SB\n");
885 CloseHandle(hConOutWT
);
886 CloseHandle(hConOutRO
);
888 /* Now we have two ReadWrite SB, active must be hConOutRW */
889 /* Open current SB via CONOUT$ */
890 hConOutNew
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0,
891 NULL
, OPEN_EXISTING
, 0, 0);
892 ok(hConOutNew
!= INVALID_HANDLE_VALUE
, "CONOUT$ is not opened\n");
897 SetConsoleCursorPosition(hConOut
, c
);
899 SetConsoleCursorPosition(hConOutRW
, c
);
900 okCURSOR(hConOutNew
, c
);
902 okCURSOR(hConOut
, c
);
907 /* Write using hConOutNew... */
908 SetConsoleCursorPosition(hConOutNew
, c
);
909 ret
= WriteConsoleA(hConOutNew
, test_str2
, lstrlenA(test_str2
), &len
, NULL
);
910 ok (ret
&& len
== lstrlenA(test_str2
), "WriteConsoleA failed\n");
911 /* ... and read it back via hConOutRW */
912 ret
= ReadConsoleOutputCharacterA(hConOutRW
, str_buf
, lstrlenA(test_str2
), c
, &len
);
913 ok(ret
&& len
== lstrlenA(test_str2
), "ReadConsoleOutputCharacterA failed\n");
914 str_buf
[lstrlenA(test_str2
)] = 0;
915 ok(!lstrcmpA(str_buf
, test_str2
), "got '%s' expected '%s'\n", str_buf
, test_str2
);
918 /* Now test output codepage handling. Current is 866 as we set earlier. */
919 SetConsoleCursorPosition(hConOutRW
, c
);
920 ret
= WriteConsoleA(hConOutRW
, test_cp866
, lstrlenA(test_cp866
), &len
, NULL
);
921 ok(ret
&& len
== lstrlenA(test_cp866
), "WriteConsoleA failed\n");
922 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenA(test_cp866
), c
, &len
);
923 ok(ret
&& len
== lstrlenA(test_cp866
), "ReadConsoleOutputCharacterW failed\n");
924 str_wbuf
[lstrlenA(test_cp866
)] = 0;
925 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
928 * cp866 is OK, let's switch to cp1251.
929 * We expect that this codepage will be used in every SB - active and not.
931 ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n");
932 SetConsoleCursorPosition(hConOutRW
, c
);
933 ret
= WriteConsoleA(hConOutRW
, test_cp1251
, lstrlenA(test_cp1251
), &len
, NULL
);
934 ok(ret
&& len
== lstrlenA(test_cp1251
), "WriteConsoleA failed\n");
935 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenA(test_cp1251
), c
, &len
);
936 ok(ret
&& len
== lstrlenA(test_cp1251
), "ReadConsoleOutputCharacterW failed\n");
937 str_wbuf
[lstrlenA(test_cp1251
)] = 0;
938 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
940 /* Check what has happened to hConOut. */
941 SetConsoleCursorPosition(hConOut
, c
);
942 ret
= WriteConsoleA(hConOut
, test_cp1251
, lstrlenA(test_cp1251
), &len
, NULL
);
943 ok(ret
&& len
== lstrlenA(test_cp1251
), "WriteConsoleA failed\n");
944 ret
= ReadConsoleOutputCharacterW(hConOut
, str_wbuf
, lstrlenA(test_cp1251
), c
, &len
);
945 ok(ret
&& len
== lstrlenA(test_cp1251
), "ReadConsoleOutputCharacterW failed\n");
946 str_wbuf
[lstrlenA(test_cp1251
)] = 0;
947 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
949 /* Close all handles of current console SB */
950 CloseHandle(hConOutNew
);
951 CloseHandle(hConOutRW
);
953 /* Now active SB should be hConOut */
954 hConOutNew
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0,
955 NULL
, OPEN_EXISTING
, 0, 0);
956 ok(hConOutNew
!= INVALID_HANDLE_VALUE
, "CONOUT$ is not opened\n");
958 /* Write using hConOutNew... */
959 SetConsoleCursorPosition(hConOutNew
, c
);
960 ret
= WriteConsoleA(hConOutNew
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
961 ok (ret
&& len
== lstrlenA(test_str1
), "WriteConsoleA failed\n");
962 /* ... and read it back via hConOut */
963 ret
= ReadConsoleOutputCharacterA(hConOut
, str_buf
, lstrlenA(test_str1
), c
, &len
);
964 ok(ret
&& len
== lstrlenA(test_str1
), "ReadConsoleOutputCharacterA failed\n");
965 str_buf
[lstrlenA(test_str1
)] = 0;
966 todo_wine
ok(!lstrcmpA(str_buf
, test_str1
), "got '%s' expected '%s'\n", str_buf
, test_str1
);
967 CloseHandle(hConOutNew
);
969 /* This is not really needed under Windows */
970 SetConsoleActiveScreenBuffer(hConOut
);
972 /* restore codepage */
973 SetConsoleOutputCP(oldcp
);
976 static void CALLBACK
signaled_function(void *p
, BOOLEAN timeout
)
980 ok(!timeout
, "wait shouldn't have timed out\n");
983 static void testWaitForConsoleInput(HANDLE input_handle
)
986 HANDLE complete_event
;
988 DWORD events_written
;
992 complete_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
994 /* Test success case */
995 ret
= RegisterWaitForSingleObject(&wait_handle
, input_handle
, signaled_function
, complete_event
, INFINITE
, WT_EXECUTEONLYONCE
);
996 ok(ret
== TRUE
, "Expected RegisterWaitForSingleObject to return TRUE, got %d\n", ret
);
997 /* give worker thread a chance to start up */
999 record
.EventType
= KEY_EVENT
;
1000 record
.Event
.KeyEvent
.bKeyDown
= 1;
1001 record
.Event
.KeyEvent
.wRepeatCount
= 1;
1002 record
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1003 record
.Event
.KeyEvent
.wVirtualScanCode
= VK_RETURN
;
1004 record
.Event
.KeyEvent
.uChar
.UnicodeChar
= '\r';
1005 record
.Event
.KeyEvent
.dwControlKeyState
= 0;
1006 ret
= WriteConsoleInputW(input_handle
, &record
, 1, &events_written
);
1007 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1008 wait_ret
= WaitForSingleObject(complete_event
, INFINITE
);
1009 ok(wait_ret
== WAIT_OBJECT_0
, "Expected the handle to be signaled\n");
1010 ret
= UnregisterWait(wait_handle
);
1011 /* If the callback is still running, this fails with ERROR_IO_PENDING, but
1012 that's ok and expected. */
1013 ok(ret
!= 0 || GetLastError() == ERROR_IO_PENDING
,
1014 "UnregisterWait failed with error %d\n", GetLastError());
1016 /* Test timeout case */
1017 FlushConsoleInputBuffer(input_handle
);
1018 ret
= RegisterWaitForSingleObject(&wait_handle
, input_handle
, signaled_function
, complete_event
, INFINITE
, WT_EXECUTEONLYONCE
);
1019 wait_ret
= WaitForSingleObject(complete_event
, 100);
1020 ok(wait_ret
== WAIT_TIMEOUT
, "Expected the wait to time out\n");
1021 ret
= UnregisterWait(wait_handle
);
1022 ok(ret
, "UnregisterWait failed with error %d\n", GetLastError());
1025 CloseHandle(complete_event
);
1028 static void test_wait(HANDLE input
, HANDLE orig_output
)
1030 HANDLE output
, unbound_output
, unbound_input
;
1037 if (skip_nt
) return;
1039 memset(&ir
, 0, sizeof(ir
));
1040 ir
.EventType
= MOUSE_EVENT
;
1041 ir
.Event
.MouseEvent
.dwEventFlags
= MOUSE_MOVED
;
1044 output
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
1045 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
1046 CONSOLE_TEXTMODE_BUFFER
, NULL
);
1047 ok(output
!= INVALID_HANDLE_VALUE
, "CreateConsoleScreenBuffer failed: %u\n", GetLastError());
1049 ret
= SetConsoleActiveScreenBuffer(output
);
1050 ok(ret
, "SetConsoleActiveScreenBuffer failed: %u\n", GetLastError());
1051 FlushConsoleInputBuffer(input
);
1053 unbound_output
= create_unbound_handle(TRUE
, TRUE
);
1054 unbound_input
= create_unbound_handle(FALSE
, TRUE
);
1056 res
= WaitForSingleObject(input
, 0);
1057 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %x\n", res
);
1058 res
= WaitForSingleObject(output
, 0);
1059 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %x\n", res
);
1060 res
= WaitForSingleObject(orig_output
, 0);
1061 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %x\n", res
);
1062 res
= WaitForSingleObject(unbound_output
, 0);
1063 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %x\n", res
);
1064 res
= WaitForSingleObject(unbound_input
, 0);
1065 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %x\n", res
);
1066 status
= NtWaitForSingleObject(input
, FALSE
, &zero
);
1067 ok(status
== STATUS_TIMEOUT
|| broken(status
== STATUS_ACCESS_DENIED
/* win2k8 */),
1068 "NtWaitForSingleObject returned %x\n", status
);
1069 status
= NtWaitForSingleObject(output
, FALSE
, &zero
);
1070 ok(status
== STATUS_TIMEOUT
|| broken(status
== STATUS_ACCESS_DENIED
/* win2k8 */),
1071 "NtWaitForSingleObject returned %x\n", status
);
1073 ret
= WriteConsoleInputW(input
, &ir
, 1, &count
);
1074 ok(ret
, "WriteConsoleInputW failed: %u\n", GetLastError());
1076 res
= WaitForSingleObject(input
, 0);
1077 ok(!res
, "WaitForSingleObject returned %x\n", res
);
1078 res
= WaitForSingleObject(output
, 0);
1079 ok(!res
, "WaitForSingleObject returned %x\n", res
);
1080 res
= WaitForSingleObject(orig_output
, 0);
1081 ok(!res
, "WaitForSingleObject returned %x\n", res
);
1082 res
= WaitForSingleObject(unbound_output
, 0);
1083 ok(!res
, "WaitForSingleObject returned %x\n", res
);
1084 res
= WaitForSingleObject(unbound_input
, 0);
1085 ok(!res
, "WaitForSingleObject returned %x\n", res
);
1086 status
= NtWaitForSingleObject(input
, FALSE
, &zero
);
1087 ok(!status
|| broken(status
== STATUS_ACCESS_DENIED
/* win2k8 */),
1088 "NtWaitForSingleObject returned %x\n", status
);
1089 status
= NtWaitForSingleObject(output
, FALSE
, &zero
);
1090 ok(!status
|| broken(status
== STATUS_ACCESS_DENIED
/* win2k8 */),
1091 "NtWaitForSingleObject returned %x\n", status
);
1093 ret
= SetConsoleActiveScreenBuffer(orig_output
);
1094 ok(ret
, "SetConsoleActiveScreenBuffer failed: %u\n", GetLastError());
1096 CloseHandle(unbound_input
);
1097 CloseHandle(unbound_output
);
1098 CloseHandle(output
);
1101 static void test_GetSetConsoleInputExeName(void)
1105 char buffer
[MAX_PATH
], module
[MAX_PATH
], *p
;
1106 static char input_exe
[MAX_PATH
] = "winetest.exe";
1108 SetLastError(0xdeadbeef);
1109 ret
= pGetConsoleInputExeNameA(0, NULL
);
1110 error
= GetLastError();
1111 ok(ret
, "GetConsoleInputExeNameA failed\n");
1112 ok(error
== ERROR_BUFFER_OVERFLOW
, "got %u expected ERROR_BUFFER_OVERFLOW\n", error
);
1114 SetLastError(0xdeadbeef);
1115 ret
= pGetConsoleInputExeNameA(0, buffer
);
1116 error
= GetLastError();
1117 ok(ret
, "GetConsoleInputExeNameA failed\n");
1118 ok(error
== ERROR_BUFFER_OVERFLOW
, "got %u expected ERROR_BUFFER_OVERFLOW\n", error
);
1120 GetModuleFileNameA(GetModuleHandleA(NULL
), module
, sizeof(module
));
1121 p
= strrchr(module
, '\\') + 1;
1123 ret
= pGetConsoleInputExeNameA(ARRAY_SIZE(buffer
), buffer
);
1124 ok(ret
, "GetConsoleInputExeNameA failed\n");
1125 todo_wine
ok(!lstrcmpA(buffer
, p
), "got %s expected %s\n", buffer
, p
);
1127 SetLastError(0xdeadbeef);
1128 ret
= pSetConsoleInputExeNameA(NULL
);
1129 error
= GetLastError();
1130 ok(!ret
, "SetConsoleInputExeNameA failed\n");
1131 ok(error
== ERROR_INVALID_PARAMETER
, "got %u expected ERROR_INVALID_PARAMETER\n", error
);
1133 SetLastError(0xdeadbeef);
1134 ret
= pSetConsoleInputExeNameA("");
1135 error
= GetLastError();
1136 ok(!ret
, "SetConsoleInputExeNameA failed\n");
1137 ok(error
== ERROR_INVALID_PARAMETER
, "got %u expected ERROR_INVALID_PARAMETER\n", error
);
1139 ret
= pSetConsoleInputExeNameA(input_exe
);
1140 ok(ret
, "SetConsoleInputExeNameA failed\n");
1142 ret
= pGetConsoleInputExeNameA(ARRAY_SIZE(buffer
), buffer
);
1143 ok(ret
, "GetConsoleInputExeNameA failed\n");
1144 ok(!lstrcmpA(buffer
, input_exe
), "got %s expected %s\n", buffer
, input_exe
);
1147 static void test_GetConsoleProcessList(void)
1149 DWORD ret
, *list
= NULL
;
1151 if (!pGetConsoleProcessList
)
1153 win_skip("GetConsoleProcessList is not available\n");
1157 SetLastError(0xdeadbeef);
1158 ret
= pGetConsoleProcessList(NULL
, 0);
1159 ok(ret
== 0, "Expected failure\n");
1160 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1161 "Expected ERROR_INVALID_PARAMETER, got %d\n",
1164 SetLastError(0xdeadbeef);
1165 ret
= pGetConsoleProcessList(NULL
, 1);
1166 ok(ret
== 0, "Expected failure\n");
1167 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1168 "Expected ERROR_INVALID_PARAMETER, got %d\n",
1171 /* We should only have 1 process but only for these specific unit tests as
1172 * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would
1173 * give us two processes for example.
1175 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD
));
1177 SetLastError(0xdeadbeef);
1178 ret
= pGetConsoleProcessList(list
, 0);
1179 ok(ret
== 0, "Expected failure\n");
1180 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1181 "Expected ERROR_INVALID_PARAMETER, got %d\n",
1184 SetLastError(0xdeadbeef);
1185 ret
= pGetConsoleProcessList(list
, 1);
1187 ok(ret
== 1, "Expected 1, got %d\n", ret
);
1189 HeapFree(GetProcessHeap(), 0, list
);
1191 list
= HeapAlloc(GetProcessHeap(), 0, ret
* sizeof(DWORD
));
1193 SetLastError(0xdeadbeef);
1194 ret
= pGetConsoleProcessList(list
, ret
);
1196 ok(ret
== 1, "Expected 1, got %d\n", ret
);
1200 DWORD pid
= GetCurrentProcessId();
1201 ok(list
[0] == pid
, "Expected %d, got %d\n", pid
, list
[0]);
1204 HeapFree(GetProcessHeap(), 0, list
);
1207 static void test_OpenCON(void)
1209 static const WCHAR conW
[] = {'C','O','N',0};
1210 static const DWORD accesses
[] = {CREATE_NEW
, CREATE_ALWAYS
, OPEN_EXISTING
,
1211 OPEN_ALWAYS
, TRUNCATE_EXISTING
};
1215 for (i
= 0; i
< ARRAY_SIZE(accesses
); i
++)
1217 h
= CreateFileW(conW
, GENERIC_WRITE
, 0, NULL
, accesses
[i
], 0, NULL
);
1218 ok(h
!= INVALID_HANDLE_VALUE
|| broken(accesses
[i
] == TRUNCATE_EXISTING
/* Win8 */),
1219 "Expected to open the CON device on write (%x)\n", accesses
[i
]);
1222 h
= CreateFileW(conW
, GENERIC_READ
, 0, NULL
, accesses
[i
], 0, NULL
);
1223 /* Windows versions differ here:
1224 * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1225 * NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING
1226 * So don't test when disposition is TRUNCATE_EXISTING
1228 ok(h
!= INVALID_HANDLE_VALUE
|| broken(accesses
[i
] == TRUNCATE_EXISTING
/* Win7+ */),
1229 "Expected to open the CON device on read (%x)\n", accesses
[i
]);
1231 h
= CreateFileW(conW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, accesses
[i
], 0, NULL
);
1232 ok(h
== INVALID_HANDLE_VALUE
, "Expected not to open the CON device on read-write (%x)\n", accesses
[i
]);
1233 ok(GetLastError() == ERROR_FILE_NOT_FOUND
|| GetLastError() == ERROR_INVALID_PARAMETER
,
1234 "Unexpected error %x\n", GetLastError());
1238 static void test_OpenConsoleW(void)
1240 static const WCHAR coninW
[] = {'C','O','N','I','N','$',0};
1241 static const WCHAR conoutW
[] = {'C','O','N','O','U','T','$',0};
1242 static const WCHAR emptyW
[] = {0};
1243 static const WCHAR invalidW
[] = {'I','N','V','A','L','I','D',0};
1253 } invalid_table
[] = {
1254 {NULL
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1255 {NULL
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1256 {NULL
, 0xdeadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1257 {NULL
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1258 {NULL
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1259 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1260 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1261 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1262 {emptyW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1263 {emptyW
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1264 {emptyW
, 0xdeadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1265 {emptyW
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1266 {emptyW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1267 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1268 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1269 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1270 {invalidW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1271 {invalidW
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1272 {invalidW
, 0xdeadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1273 {invalidW
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1274 {invalidW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1275 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1276 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1277 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1278 {coninW
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1279 {coninW
, 0xdeadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_ACCESS_DENIED
},
1280 {coninW
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1281 {conoutW
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1282 {conoutW
, 0xceadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_ACCESS_DENIED
},
1283 {conoutW
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1292 {coninW
, 0, FALSE
, 0 },
1293 {coninW
, 0, TRUE
, 0 },
1294 {coninW
, GENERIC_EXECUTE
, TRUE
, 0 },
1295 {coninW
, GENERIC_ALL
, TRUE
, 0 },
1296 {coninW
, 0, FALSE
, OPEN_ALWAYS
},
1297 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0 },
1298 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
},
1299 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
},
1300 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
},
1301 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
},
1302 {conoutW
, 0, FALSE
, 0 },
1303 {conoutW
, 0, FALSE
, OPEN_ALWAYS
},
1304 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0 },
1305 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, },
1306 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
},
1307 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
},
1308 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
},
1316 win_skip("OpenConsoleW is not available\n");
1320 for (index
= 0; index
< ARRAY_SIZE(invalid_table
); index
++)
1322 SetLastError(0xdeadbeef);
1323 ret
= pOpenConsoleW(invalid_table
[index
].name
, invalid_table
[index
].access
,
1324 invalid_table
[index
].inherit
, invalid_table
[index
].creation
);
1325 gle
= GetLastError();
1326 ok(ret
== INVALID_HANDLE_VALUE
,
1327 "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1329 ok(gle
== invalid_table
[index
].gle
|| (gle
!= 0 && gle
== invalid_table
[index
].gle2
),
1330 "Expected GetLastError() to return %u/%u for index %d, got %u\n",
1331 invalid_table
[index
].gle
, invalid_table
[index
].gle2
, index
, gle
);
1334 for (index
= 0; index
< ARRAY_SIZE(valid_table
); index
++)
1336 ret
= pOpenConsoleW(valid_table
[index
].name
, valid_table
[index
].access
,
1337 valid_table
[index
].inherit
, valid_table
[index
].creation
);
1339 ok(ret
!= INVALID_HANDLE_VALUE
|| broken(ret
== INVALID_HANDLE_VALUE
/* until Win7 */),
1340 "Expected OpenConsoleW to succeed for index %d, got %p\n", index
, ret
);
1341 if (ret
!= INVALID_HANDLE_VALUE
)
1345 ret
= pOpenConsoleW(coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
);
1346 ok(ret
!= INVALID_HANDLE_VALUE
, "Expected OpenConsoleW to return a valid handle\n");
1347 if (ret
!= INVALID_HANDLE_VALUE
)
1350 ret
= pOpenConsoleW(conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
);
1351 ok(ret
!= INVALID_HANDLE_VALUE
, "Expected OpenConsoleW to return a valid handle\n");
1352 if (ret
!= INVALID_HANDLE_VALUE
)
1356 static void test_CreateFileW(void)
1367 {TRUE
, 0, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1368 {TRUE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1369 {TRUE
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1370 {TRUE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, 0, FALSE
},
1371 {TRUE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, 0, FALSE
},
1372 {TRUE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1373 {FALSE
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1374 {FALSE
, 0, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1375 {FALSE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1376 {FALSE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, 0, FALSE
},
1377 {FALSE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, 0, FALSE
},
1378 {FALSE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1379 /* TRUNCATE_EXISTING is forbidden starting with Windows 8 */
1382 static const UINT nt_disposition
[5] =
1384 FILE_CREATE
, /* CREATE_NEW */
1385 FILE_OVERWRITE_IF
, /* CREATE_ALWAYS */
1386 FILE_OPEN
, /* OPEN_EXISTING */
1387 FILE_OPEN_IF
, /* OPEN_ALWAYS */
1388 FILE_OVERWRITE
/* TRUNCATE_EXISTING */
1393 SECURITY_ATTRIBUTES sa
;
1394 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
1395 UNICODE_STRING string
;
1396 IO_STATUS_BLOCK iosb
;
1399 for (index
= 0; index
< ARRAY_SIZE(cf_table
); index
++)
1401 SetLastError(0xdeadbeef);
1403 sa
.nLength
= sizeof(sa
);
1404 sa
.lpSecurityDescriptor
= NULL
;
1405 sa
.bInheritHandle
= cf_table
[index
].inherit
;
1407 ret
= CreateFileW(cf_table
[index
].input
? L
"CONIN$" : L
"CONOUT$", cf_table
[index
].access
,
1408 FILE_SHARE_READ
|FILE_SHARE_WRITE
, &sa
,
1409 cf_table
[index
].creation
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1410 if (ret
== INVALID_HANDLE_VALUE
)
1412 ok(cf_table
[index
].gle
,
1413 "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index
);
1414 ok(GetLastError() == cf_table
[index
].gle
,
1415 "Expected GetLastError() to return %u for index %d, got %u\n",
1416 cf_table
[index
].gle
, index
, GetLastError());
1420 ok(!cf_table
[index
].gle
|| broken(cf_table
[index
].is_broken
) /* Win7 */,
1421 "Expected CreateFileW to succeed for index %d\n", index
);
1425 if (skip_nt
) continue;
1427 SetLastError(0xdeadbeef);
1429 sa
.nLength
= sizeof(sa
);
1430 sa
.lpSecurityDescriptor
= NULL
;
1431 sa
.bInheritHandle
= cf_table
[index
].inherit
;
1433 ret
= CreateFileW(cf_table
[index
].input
? L
"\\??\\CONIN$" : L
"\\??\\CONOUT$", cf_table
[index
].access
,
1434 FILE_SHARE_READ
|FILE_SHARE_WRITE
, &sa
,
1435 cf_table
[index
].creation
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1436 if (cf_table
[index
].gle
)
1437 ok(ret
== INVALID_HANDLE_VALUE
&& GetLastError() == cf_table
[index
].gle
,
1438 "CreateFileW to returned %p %u for index %d\n", ret
, GetLastError(), index
);
1440 ok(ret
!= INVALID_HANDLE_VALUE
&& (!cf_table
[index
].gle
|| broken(cf_table
[index
].is_broken
) /* Win7 */),
1441 "CreateFileW to returned %p %u for index %d\n", ret
, GetLastError(), index
);
1442 if (ret
!= INVALID_HANDLE_VALUE
) CloseHandle(ret
);
1444 if (cf_table
[index
].gle
) continue;
1446 RtlInitUnicodeString(&string
, cf_table
[index
].input
1447 ? L
"\\Device\\ConDrv\\CurrentIn" : L
"\\Device\\ConDrv\\CurrentOut");
1448 attr
.ObjectName
= &string
;
1449 status
= NtCreateFile(&ret
, cf_table
[index
].access
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
, &attr
, &iosb
, NULL
,
1450 FILE_ATTRIBUTE_NORMAL
, 0, nt_disposition
[cf_table
[index
].creation
- CREATE_NEW
],
1451 FILE_NON_DIRECTORY_FILE
, NULL
, 0);
1452 ok(!status
, "NtCreateFile failed %x for %u\n", status
, index
);
1455 RtlInitUnicodeString(&string
, cf_table
[index
].input
? L
"\\??\\CONIN$" : L
"\\??\\CONOUT$");
1456 attr
.ObjectName
= &string
;
1457 status
= NtCreateFile(&ret
, cf_table
[index
].access
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
, &attr
, &iosb
, NULL
,
1458 FILE_ATTRIBUTE_NORMAL
, 0, nt_disposition
[cf_table
[index
].creation
- CREATE_NEW
],
1459 FILE_NON_DIRECTORY_FILE
, NULL
, 0);
1460 ok(!status
, "NtCreateFile failed %x for %u\n", status
, index
);
1465 static void test_VerifyConsoleIoHandle( HANDLE handle
)
1470 if (!pVerifyConsoleIoHandle
)
1472 win_skip("VerifyConsoleIoHandle is not available\n");
1476 /* invalid handle */
1477 SetLastError(0xdeadbeef);
1478 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee0);
1479 error
= GetLastError();
1480 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1481 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1483 /* invalid handle + 1 */
1484 SetLastError(0xdeadbeef);
1485 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee1);
1486 error
= GetLastError();
1487 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1488 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1490 /* invalid handle + 2 */
1491 SetLastError(0xdeadbeef);
1492 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee2);
1493 error
= GetLastError();
1494 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1495 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1497 /* invalid handle + 3 */
1498 SetLastError(0xdeadbeef);
1499 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee3);
1500 error
= GetLastError();
1501 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1502 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1505 SetLastError(0xdeadbeef);
1506 ret
= pVerifyConsoleIoHandle(handle
);
1507 error
= GetLastError();
1509 broken(!ret
), /* Windows 8 and 10 */
1510 "expected VerifyConsoleIoHandle to succeed\n");
1511 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1514 static void test_GetSetStdHandle(void)
1520 /* get invalid std handle */
1521 SetLastError(0xdeadbeef);
1522 handle
= GetStdHandle(42);
1523 error
= GetLastError();
1524 ok(error
== ERROR_INVALID_HANDLE
|| broken(error
== ERROR_INVALID_FUNCTION
)/* Win9x */,
1525 "wrong GetLastError() %d\n", error
);
1526 ok(handle
== INVALID_HANDLE_VALUE
, "expected INVALID_HANDLE_VALUE\n");
1529 SetLastError(0xdeadbeef);
1530 handle
= GetStdHandle(STD_INPUT_HANDLE
);
1531 error
= GetLastError();
1532 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1534 /* set invalid std handle */
1535 SetLastError(0xdeadbeef);
1536 ret
= SetStdHandle(42, handle
);
1537 error
= GetLastError();
1538 ok(!ret
, "expected SetStdHandle to fail\n");
1539 ok(error
== ERROR_INVALID_HANDLE
|| broken(error
== ERROR_INVALID_FUNCTION
)/* Win9x */,
1540 "wrong GetLastError() %d\n", error
);
1542 /* set valid (restore old value) */
1543 SetLastError(0xdeadbeef);
1544 ret
= SetStdHandle(STD_INPUT_HANDLE
, handle
);
1545 error
= GetLastError();
1546 ok(ret
, "expected SetStdHandle to succeed\n");
1547 ok(error
== 0xdeadbeef, "wrong GetLastError() %d\n", error
);
1550 static void test_DuplicateConsoleHandle(void)
1552 HANDLE handle
, event
;
1555 if (skip_nt
) return;
1557 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1559 /* duplicate an event handle with DuplicateConsoleHandle */
1560 handle
= DuplicateConsoleHandle(event
, 0, FALSE
, DUPLICATE_SAME_ACCESS
);
1561 ok(handle
!= NULL
, "DuplicateConsoleHandle failed: %u\n", GetLastError());
1563 ret
= SetEvent(handle
);
1564 ok(ret
, "SetEvent failed: %u\n", GetLastError());
1566 ret
= CloseConsoleHandle(handle
);
1567 ok(ret
, "CloseConsoleHandle failed: %u\n", GetLastError());
1568 ret
= CloseConsoleHandle(event
);
1569 ok(ret
, "CloseConsoleHandle failed: %u\n", GetLastError());
1571 handle
= DuplicateConsoleHandle((HANDLE
)0xdeadbeef, 0, FALSE
, DUPLICATE_SAME_ACCESS
);
1572 ok(handle
== INVALID_HANDLE_VALUE
, "DuplicateConsoleHandle failed: %u\n", GetLastError());
1573 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error = %u\n", GetLastError());
1576 static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle
)
1589 {NULL
, NULL
, ERROR_INVALID_HANDLE
},
1590 {NULL
, &count
, ERROR_INVALID_HANDLE
},
1591 {INVALID_HANDLE_VALUE
, NULL
, ERROR_INVALID_HANDLE
},
1592 {INVALID_HANDLE_VALUE
, &count
, ERROR_INVALID_HANDLE
},
1595 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
1597 SetLastError(0xdeadbeef);
1598 if (invalid_table
[i
].nrofevents
) count
= 0xdeadbeef;
1599 ret
= GetNumberOfConsoleInputEvents(invalid_table
[i
].handle
,
1600 invalid_table
[i
].nrofevents
);
1601 ok(!ret
, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i
, ret
);
1602 if (invalid_table
[i
].nrofevents
)
1604 ok(count
== 0xdeadbeef,
1605 "[%d] Expected output count to be unmodified, got %u\n", i
, count
);
1607 ok(GetLastError() == invalid_table
[i
].last_error
,
1608 "[%d] Expected last error to be %u, got %u\n",
1609 i
, invalid_table
[i
].last_error
, GetLastError());
1612 /* Test crashes on Windows 7. */
1615 SetLastError(0xdeadbeef);
1616 ret
= GetNumberOfConsoleInputEvents(input_handle
, NULL
);
1617 ok(!ret
, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret
);
1618 ok(GetLastError() == ERROR_INVALID_ACCESS
,
1619 "Expected last error to be ERROR_INVALID_ACCESS, got %u\n",
1624 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1625 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1626 ok(count
!= 0xdeadbeef, "Expected output count to initialized\n");
1629 static void test_WriteConsoleInputA(HANDLE input_handle
)
1632 INPUT_RECORD event_list
[5];
1633 MOUSE_EVENT_RECORD mouse_event
= { {0, 0}, 0, 0, MOUSE_MOVED
};
1634 KEY_EVENT_RECORD key_event
;
1635 DWORD count
, console_mode
, gle
;
1642 const INPUT_RECORD
*buffer
;
1649 {NULL
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1650 {NULL
, NULL
, 0, &count
,ERROR_INVALID_HANDLE
},
1651 {NULL
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1652 {NULL
, NULL
, 1, &count
, ERROR_NOACCESS
, ERROR_INVALID_ACCESS
},
1653 {NULL
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1654 {NULL
, &event
, 0, &count
, ERROR_INVALID_HANDLE
},
1655 {NULL
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1656 {NULL
, &event
, 1, &count
, ERROR_INVALID_HANDLE
},
1657 {INVALID_HANDLE_VALUE
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1658 {INVALID_HANDLE_VALUE
, NULL
, 0, &count
, ERROR_INVALID_HANDLE
},
1659 {INVALID_HANDLE_VALUE
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1660 {INVALID_HANDLE_VALUE
, NULL
, 1, &count
, ERROR_INVALID_HANDLE
, ERROR_INVALID_ACCESS
},
1661 {INVALID_HANDLE_VALUE
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1662 {INVALID_HANDLE_VALUE
, &event
, 0, &count
, ERROR_INVALID_HANDLE
},
1663 {INVALID_HANDLE_VALUE
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1664 {INVALID_HANDLE_VALUE
, &event
, 1, &count
, ERROR_INVALID_HANDLE
},
1665 {input_handle
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1666 {input_handle
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1667 {input_handle
, NULL
, 1, &count
, ERROR_NOACCESS
, ERROR_INVALID_ACCESS
},
1668 {input_handle
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1669 {input_handle
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1672 /* Suppress external sources of input events for the duration of the test. */
1673 ret
= GetConsoleMode(input_handle
, &console_mode
);
1674 ok(ret
== TRUE
, "Expected GetConsoleMode to return TRUE, got %d\n", ret
);
1677 skip("GetConsoleMode failed with last error %u\n", GetLastError());
1681 ret
= SetConsoleMode(input_handle
, console_mode
& ~(ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
));
1682 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
1685 skip("SetConsoleMode failed with last error %u\n", GetLastError());
1689 /* Discard any events queued before the tests. */
1690 ret
= FlushConsoleInputBuffer(input_handle
);
1691 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1693 event
.EventType
= MOUSE_EVENT
;
1694 event
.Event
.MouseEvent
= mouse_event
;
1696 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
1698 if (invalid_table
[i
].win_crash
)
1701 SetLastError(0xdeadbeef);
1702 if (invalid_table
[i
].written
) count
= 0xdeadbeef;
1703 ret
= WriteConsoleInputA(invalid_table
[i
].handle
,
1704 invalid_table
[i
].buffer
,
1705 invalid_table
[i
].count
,
1706 invalid_table
[i
].written
);
1707 ok(!ret
, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i
, ret
);
1708 gle
= GetLastError();
1709 ok(gle
== invalid_table
[i
].gle
|| (gle
!= 0 && gle
== invalid_table
[i
].gle2
),
1710 "[%d] Expected last error to be %u or %u, got %u\n",
1711 i
, invalid_table
[i
].gle
, invalid_table
[i
].gle2
, gle
);
1715 ret
= WriteConsoleInputA(input_handle
, NULL
, 0, &count
);
1716 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1717 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1720 ret
= WriteConsoleInputA(input_handle
, &event
, 0, &count
);
1721 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1722 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1725 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1726 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1727 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1729 ret
= FlushConsoleInputBuffer(input_handle
);
1730 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1732 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1733 event
.EventType
= MOUSE_EVENT
;
1734 event
.Event
.MouseEvent
= mouse_event
;
1736 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1737 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1738 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1740 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1741 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1742 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1744 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1745 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1746 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1748 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1749 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1751 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1753 ret
= FlushConsoleInputBuffer(input_handle
);
1754 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1756 for (i
= 0; i
< ARRAY_SIZE(event_list
); i
++)
1758 event_list
[i
].EventType
= MOUSE_EVENT
;
1759 event_list
[i
].Event
.MouseEvent
= mouse_event
;
1762 /* Writing consecutive chunks of mouse events appears to work. */
1763 ret
= WriteConsoleInputA(input_handle
, event_list
, ARRAY_SIZE(event_list
), &count
);
1764 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1765 ok(count
== ARRAY_SIZE(event_list
),
1766 "Expected count to be event list length, got %u\n", count
);
1768 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1769 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1770 ok(count
== ARRAY_SIZE(event_list
),
1771 "Expected count to be event list length, got %u\n", count
);
1773 ret
= WriteConsoleInputA(input_handle
, event_list
, ARRAY_SIZE(event_list
), &count
);
1774 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1775 ok(count
== ARRAY_SIZE(event_list
),
1776 "Expected count to be event list length, got %u\n", count
);
1778 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1779 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1780 ok(count
== 2*ARRAY_SIZE(event_list
),
1781 "Expected count to be twice event list length, got %u\n", count
);
1783 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1784 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1785 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1786 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1788 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1789 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1791 ok(count
== 2*ARRAY_SIZE(event_list
),
1792 "Expected count to be twice event list length, got %u\n", count
);
1794 ret
= FlushConsoleInputBuffer(input_handle
);
1795 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1797 key_event
.bKeyDown
= FALSE
;
1798 key_event
.wRepeatCount
= 0;
1799 key_event
.wVirtualKeyCode
= VK_SPACE
;
1800 key_event
.wVirtualScanCode
= VK_SPACE
;
1801 key_event
.uChar
.AsciiChar
= ' ';
1802 key_event
.dwControlKeyState
= 0;
1804 event
.EventType
= KEY_EVENT
;
1805 event
.Event
.KeyEvent
= key_event
;
1807 /* Key events don't exhibit the same behavior as mouse events. */
1808 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1809 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1810 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1812 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1813 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1814 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1816 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1817 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1818 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1820 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1821 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1822 ok(count
== 2, "Expected count to be 2, got %u\n", count
);
1824 ret
= FlushConsoleInputBuffer(input_handle
);
1825 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1827 /* Try interleaving mouse and key events. */
1828 event
.EventType
= MOUSE_EVENT
;
1829 event
.Event
.MouseEvent
= mouse_event
;
1831 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1832 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1833 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1835 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1836 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1837 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1839 event
.EventType
= KEY_EVENT
;
1840 event
.Event
.KeyEvent
= key_event
;
1842 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1843 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1844 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1846 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1847 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1848 ok(count
== 2, "Expected count to be 2, got %u\n", count
);
1850 event
.EventType
= MOUSE_EVENT
;
1851 event
.Event
.MouseEvent
= mouse_event
;
1853 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1854 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1855 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1857 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1858 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1859 ok(count
== 3, "Expected count to be 3, got %u\n", count
);
1861 /* Restore the old console mode. */
1862 ret
= SetConsoleMode(input_handle
, console_mode
);
1863 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
1866 static void test_WriteConsoleInputW(HANDLE input_handle
)
1869 INPUT_RECORD event_list
[5];
1870 MOUSE_EVENT_RECORD mouse_event
= { {0, 0}, 0, 0, MOUSE_MOVED
};
1871 KEY_EVENT_RECORD key_event
;
1872 DWORD count
, console_mode
, gle
;
1879 const INPUT_RECORD
*buffer
;
1886 {NULL
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1887 {NULL
, NULL
, 0, &count
, ERROR_INVALID_HANDLE
},
1888 {NULL
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1889 {NULL
, NULL
, 1, &count
, ERROR_NOACCESS
, ERROR_INVALID_ACCESS
},
1890 {NULL
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1891 {NULL
, &event
, 0, &count
, ERROR_INVALID_HANDLE
},
1892 {NULL
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1893 {NULL
, &event
, 1, &count
, ERROR_INVALID_HANDLE
},
1894 {INVALID_HANDLE_VALUE
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1895 {INVALID_HANDLE_VALUE
, NULL
, 0, &count
, ERROR_INVALID_HANDLE
},
1896 {INVALID_HANDLE_VALUE
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1897 {INVALID_HANDLE_VALUE
, NULL
, 1, &count
, ERROR_INVALID_HANDLE
, ERROR_INVALID_ACCESS
},
1898 {INVALID_HANDLE_VALUE
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1899 {INVALID_HANDLE_VALUE
, &event
, 0, &count
, ERROR_INVALID_HANDLE
},
1900 {INVALID_HANDLE_VALUE
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1901 {INVALID_HANDLE_VALUE
, &event
, 1, &count
, ERROR_INVALID_HANDLE
},
1902 {input_handle
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1903 {input_handle
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1904 {input_handle
, NULL
, 1, &count
, ERROR_NOACCESS
, ERROR_INVALID_ACCESS
},
1905 {input_handle
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1906 {input_handle
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1909 /* Suppress external sources of input events for the duration of the test. */
1910 ret
= GetConsoleMode(input_handle
, &console_mode
);
1911 ok(ret
== TRUE
, "Expected GetConsoleMode to return TRUE, got %d\n", ret
);
1914 skip("GetConsoleMode failed with last error %u\n", GetLastError());
1918 ret
= SetConsoleMode(input_handle
, console_mode
& ~(ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
));
1919 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
1922 skip("SetConsoleMode failed with last error %u\n", GetLastError());
1926 /* Discard any events queued before the tests. */
1927 ret
= FlushConsoleInputBuffer(input_handle
);
1928 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1930 event
.EventType
= MOUSE_EVENT
;
1931 event
.Event
.MouseEvent
= mouse_event
;
1933 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
1935 if (invalid_table
[i
].win_crash
)
1938 SetLastError(0xdeadbeef);
1939 if (invalid_table
[i
].written
) count
= 0xdeadbeef;
1940 ret
= WriteConsoleInputW(invalid_table
[i
].handle
,
1941 invalid_table
[i
].buffer
,
1942 invalid_table
[i
].count
,
1943 invalid_table
[i
].written
);
1944 ok(!ret
, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i
, ret
);
1945 gle
= GetLastError();
1946 ok(gle
== invalid_table
[i
].gle
|| (gle
!= 0 && gle
== invalid_table
[i
].gle2
),
1947 "[%d] Expected last error to be %u or %u, got %u\n",
1948 i
, invalid_table
[i
].gle
, invalid_table
[i
].gle2
, gle
);
1952 ret
= WriteConsoleInputW(input_handle
, NULL
, 0, &count
);
1953 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1954 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1957 ret
= WriteConsoleInputW(input_handle
, &event
, 0, &count
);
1958 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1959 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
1962 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1963 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1964 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1966 ret
= FlushConsoleInputBuffer(input_handle
);
1967 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1969 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1970 event
.EventType
= MOUSE_EVENT
;
1971 event
.Event
.MouseEvent
= mouse_event
;
1973 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1974 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1975 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1977 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1978 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1979 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1981 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
1982 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1983 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1985 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1986 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1988 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
1990 ret
= FlushConsoleInputBuffer(input_handle
);
1991 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1993 for (i
= 0; i
< ARRAY_SIZE(event_list
); i
++)
1995 event_list
[i
].EventType
= MOUSE_EVENT
;
1996 event_list
[i
].Event
.MouseEvent
= mouse_event
;
1999 /* Writing consecutive chunks of mouse events appears to work. */
2000 ret
= WriteConsoleInputW(input_handle
, event_list
, ARRAY_SIZE(event_list
), &count
);
2001 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2002 ok(count
== ARRAY_SIZE(event_list
),
2003 "Expected count to be event list length, got %u\n", count
);
2005 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2006 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2007 ok(count
== ARRAY_SIZE(event_list
),
2008 "Expected count to be event list length, got %u\n", count
);
2010 ret
= WriteConsoleInputW(input_handle
, event_list
, ARRAY_SIZE(event_list
), &count
);
2011 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2012 ok(count
== ARRAY_SIZE(event_list
),
2013 "Expected count to be event list length, got %u\n", count
);
2015 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2016 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2017 ok(count
== 2*ARRAY_SIZE(event_list
),
2018 "Expected count to be twice event list length, got %u\n", count
);
2020 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
2021 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2022 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2023 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2025 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2026 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2028 ok(count
== 2*ARRAY_SIZE(event_list
),
2029 "Expected count to be twice event list length, got %u\n", count
);
2031 ret
= FlushConsoleInputBuffer(input_handle
);
2032 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2034 key_event
.bKeyDown
= FALSE
;
2035 key_event
.wRepeatCount
= 0;
2036 key_event
.wVirtualKeyCode
= VK_SPACE
;
2037 key_event
.wVirtualScanCode
= VK_SPACE
;
2038 key_event
.uChar
.UnicodeChar
= ' ';
2039 key_event
.dwControlKeyState
= 0;
2041 event
.EventType
= KEY_EVENT
;
2042 event
.Event
.KeyEvent
= key_event
;
2044 /* Key events don't exhibit the same behavior as mouse events. */
2045 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2046 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2047 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2049 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2050 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2051 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2053 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2054 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2055 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2057 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2058 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2059 ok(count
== 2, "Expected count to be 2, got %u\n", count
);
2061 ret
= FlushConsoleInputBuffer(input_handle
);
2062 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2064 /* Try interleaving mouse and key events. */
2065 event
.EventType
= MOUSE_EVENT
;
2066 event
.Event
.MouseEvent
= mouse_event
;
2068 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2069 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2070 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2072 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2073 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2074 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2076 event
.EventType
= KEY_EVENT
;
2077 event
.Event
.KeyEvent
= key_event
;
2079 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2080 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2081 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2083 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2084 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2085 ok(count
== 2, "Expected count to be 2, got %u\n", count
);
2087 event
.EventType
= MOUSE_EVENT
;
2088 event
.Event
.MouseEvent
= mouse_event
;
2090 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2091 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2092 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2094 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2095 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2096 ok(count
== 3, "Expected count to be 3, got %u\n", count
);
2098 /* Restore the old console mode. */
2099 ret
= SetConsoleMode(input_handle
, console_mode
);
2100 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
2103 static void test_FlushConsoleInputBuffer(HANDLE input
, HANDLE output
)
2105 INPUT_RECORD record
;
2109 ret
= FlushConsoleInputBuffer(input
);
2110 ok(ret
, "FlushConsoleInputBuffer failed: %u\n", GetLastError());
2112 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2113 ok(ret
, "GetNumberOfConsoleInputEvents failed: %u\n", GetLastError());
2114 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2116 record
.EventType
= KEY_EVENT
;
2117 record
.Event
.KeyEvent
.bKeyDown
= 1;
2118 record
.Event
.KeyEvent
.wRepeatCount
= 1;
2119 record
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
2120 record
.Event
.KeyEvent
.wVirtualScanCode
= VK_RETURN
;
2121 record
.Event
.KeyEvent
.uChar
.UnicodeChar
= '\r';
2122 record
.Event
.KeyEvent
.dwControlKeyState
= 0;
2123 ret
= WriteConsoleInputW(input
, &record
, 1, &count
);
2124 ok(ret
, "WriteConsoleInputW failed: %u\n", GetLastError());
2126 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2127 ok(ret
, "GetNumberOfConsoleInputEvents failed: %u\n", GetLastError());
2128 ok(count
== 1, "Expected count to be 0, got %u\n", count
);
2130 ret
= FlushConsoleInputBuffer(input
);
2131 ok(ret
, "FlushConsoleInputBuffer failed: %u\n", GetLastError());
2133 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2134 ok(ret
, "GetNumberOfConsoleInputEvents failed: %u\n", GetLastError());
2135 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2137 ret
= WriteConsoleInputW(input
, &record
, 1, &count
);
2138 ok(ret
, "WriteConsoleInputW failed: %u\n", GetLastError());
2140 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2141 ok(ret
, "GetNumberOfConsoleInputEvents failed: %u\n", GetLastError());
2142 ok(count
== 1, "Expected count to be 0, got %u\n", count
);
2144 ret
= FlushFileBuffers(input
);
2145 ok(ret
, "FlushFileBuffers failed: %u\n", GetLastError());
2147 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2148 ok(ret
, "GetNumberOfConsoleInputEvents failed: %u\n", GetLastError());
2149 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2151 ret
= FlushConsoleInputBuffer(output
);
2152 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "FlushConsoleInputBuffer returned: %x(%u)\n",
2153 ret
, GetLastError());
2155 ret
= FlushFileBuffers(output
);
2156 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "FlushFileBuffers returned: %x(%u)\n",
2157 ret
, GetLastError());
2160 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle
)
2162 static const char output
[] = {'a', 0};
2164 COORD origin
= {0, 0};
2171 HANDLE hConsoleOutput
;
2175 LPDWORD lpNumCharsWritten
;
2176 DWORD expected_count
;
2181 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2182 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2183 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2184 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2185 {NULL
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2186 {NULL
, output
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2187 {NULL
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2188 {NULL
, output
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2189 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2190 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2191 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2192 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2193 {INVALID_HANDLE_VALUE
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2194 {INVALID_HANDLE_VALUE
, output
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2195 {INVALID_HANDLE_VALUE
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2196 {INVALID_HANDLE_VALUE
, output
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2197 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2198 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2199 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2200 {output_handle
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2201 {output_handle
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2204 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2206 if (invalid_table
[i
].win7_crash
)
2209 SetLastError(0xdeadbeef);
2210 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2211 ret
= WriteConsoleOutputCharacterA(invalid_table
[i
].hConsoleOutput
,
2212 invalid_table
[i
].str
,
2213 invalid_table
[i
].length
,
2214 invalid_table
[i
].coord
,
2215 invalid_table
[i
].lpNumCharsWritten
);
2216 ok(!ret
, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i
, ret
);
2217 if (invalid_table
[i
].lpNumCharsWritten
)
2219 ok(count
== invalid_table
[i
].expected_count
,
2220 "[%d] Expected count to be %u, got %u\n",
2221 i
, invalid_table
[i
].expected_count
, count
);
2223 ok(GetLastError() == invalid_table
[i
].last_error
,
2224 "[%d] Expected last error to be %u, got %u\n",
2225 i
, invalid_table
[i
].last_error
, GetLastError());
2229 ret
= WriteConsoleOutputCharacterA(output_handle
, NULL
, 0, origin
, &count
);
2230 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2231 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2234 ret
= WriteConsoleOutputCharacterA(output_handle
, output
, 0, origin
, &count
);
2235 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2236 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2239 ret
= WriteConsoleOutputCharacterA(output_handle
, output
, 1, origin
, &count
);
2240 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2241 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2245 ret
= WriteConsoleOutputCharacterA(output_handle
, output
, 0, origin
, &count
);
2246 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2247 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2250 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle
)
2252 static const WCHAR outputW
[] = {'a',0};
2254 COORD origin
= {0, 0};
2261 HANDLE hConsoleOutput
;
2265 LPDWORD lpNumCharsWritten
;
2266 DWORD expected_count
;
2271 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2272 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2273 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2274 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2275 {NULL
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2276 {NULL
, outputW
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2277 {NULL
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2278 {NULL
, outputW
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2279 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2280 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2281 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2282 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2283 {INVALID_HANDLE_VALUE
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2284 {INVALID_HANDLE_VALUE
, outputW
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2285 {INVALID_HANDLE_VALUE
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2286 {INVALID_HANDLE_VALUE
, outputW
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2287 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2288 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2289 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2290 {output_handle
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2291 {output_handle
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2294 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2296 if (invalid_table
[i
].win7_crash
)
2299 SetLastError(0xdeadbeef);
2300 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2301 ret
= WriteConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
2302 invalid_table
[i
].str
,
2303 invalid_table
[i
].length
,
2304 invalid_table
[i
].coord
,
2305 invalid_table
[i
].lpNumCharsWritten
);
2306 ok(!ret
, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
2307 if (invalid_table
[i
].lpNumCharsWritten
)
2309 ok(count
== invalid_table
[i
].expected_count
,
2310 "[%d] Expected count to be %u, got %u\n",
2311 i
, invalid_table
[i
].expected_count
, count
);
2313 ok(GetLastError() == invalid_table
[i
].last_error
,
2314 "[%d] Expected last error to be %u, got %u\n",
2315 i
, invalid_table
[i
].last_error
, GetLastError());
2319 ret
= WriteConsoleOutputCharacterW(output_handle
, NULL
, 0, origin
, &count
);
2320 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2321 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2324 ret
= WriteConsoleOutputCharacterW(output_handle
, outputW
, 0, origin
, &count
);
2325 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2326 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2329 ret
= WriteConsoleOutputCharacterW(output_handle
, outputW
, 1, origin
, &count
);
2330 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2331 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2335 ret
= WriteConsoleOutputCharacterW(output_handle
, outputW
, 0, origin
, &count
);
2336 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2337 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2341 static void test_WriteConsoleOutputAttribute(HANDLE output_handle
)
2343 WORD attr
= FOREGROUND_BLUE
;
2344 COORD origin
= {0, 0};
2351 HANDLE hConsoleOutput
;
2355 LPDWORD lpNumAttrsWritten
;
2356 DWORD expected_count
;
2361 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2362 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2363 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2364 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2365 {NULL
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2366 {NULL
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2367 {NULL
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2368 {NULL
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2369 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2370 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2371 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2372 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2373 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2374 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2375 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2376 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2377 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2378 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2379 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2380 {output_handle
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2381 {output_handle
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2384 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2386 if (invalid_table
[i
].win7_crash
)
2389 SetLastError(0xdeadbeef);
2390 if (invalid_table
[i
].lpNumAttrsWritten
) count
= 0xdeadbeef;
2391 ret
= WriteConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
2392 invalid_table
[i
].attr
,
2393 invalid_table
[i
].length
,
2394 invalid_table
[i
].coord
,
2395 invalid_table
[i
].lpNumAttrsWritten
);
2396 ok(!ret
, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
2397 if (invalid_table
[i
].lpNumAttrsWritten
)
2399 ok(count
== invalid_table
[i
].expected_count
,
2400 "[%d] Expected count to be %u, got %u\n",
2401 i
, invalid_table
[i
].expected_count
, count
);
2403 ok(GetLastError() == invalid_table
[i
].last_error
,
2404 "[%d] Expected last error to be %u, got %u\n",
2405 i
, invalid_table
[i
].last_error
, GetLastError());
2409 ret
= WriteConsoleOutputAttribute(output_handle
, NULL
, 0, origin
, &count
);
2410 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2411 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2414 ret
= WriteConsoleOutputAttribute(output_handle
, &attr
, 0, origin
, &count
);
2415 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2416 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2419 ret
= WriteConsoleOutputAttribute(output_handle
, &attr
, 1, origin
, &count
);
2420 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2421 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2425 ret
= WriteConsoleOutputAttribute(output_handle
, &attr
, 0, origin
, &count
);
2426 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2427 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2430 static void set_region(SMALL_RECT
*region
, unsigned int left
, unsigned int top
, unsigned int right
, unsigned int bottom
)
2432 region
->Left
= left
;
2434 region
->Right
= right
;
2435 region
->Bottom
= bottom
;
2438 #define check_region(a,b,c,d,e) check_region_(__LINE__,a,b,c,d,e)
2439 static void check_region_(unsigned int line
, const SMALL_RECT
*region
, unsigned int left
, unsigned int top
, int right
, int bottom
)
2441 ok_(__FILE__
,line
)(region
->Left
== left
, "Left = %u, expected %u\n", region
->Left
, left
);
2442 ok_(__FILE__
,line
)(region
->Top
== top
, "Top = %u, expected %u\n", region
->Top
, top
);
2443 /* In multiple places returned region depends on Windows versions: some return right < left, others leave it untouched */
2445 ok_(__FILE__
,line
)(region
->Right
== right
, "Right = %u, expected %u\n", region
->Right
, right
);
2447 ok_(__FILE__
,line
)(region
->Right
== -right
|| region
->Right
== region
->Left
- 1,
2448 "Right = %u, expected %d\n", region
->Right
, right
);
2450 ok_(__FILE__
,line
)(region
->Bottom
== bottom
, "Bottom = %u, expected %u\n", region
->Bottom
, bottom
);
2451 else if (bottom
< 0)
2452 ok_(__FILE__
,line
)(region
->Bottom
== -bottom
|| region
->Bottom
== region
->Top
- 1,
2453 "Bottom = %u, expected %d\n", region
->Bottom
, bottom
);
2456 static void test_WriteConsoleOutput(HANDLE console
)
2458 CONSOLE_SCREEN_BUFFER_INFO info
;
2459 CHAR_INFO char_info_buf
[2048];
2465 for (i
= 0; i
< ARRAY_SIZE(char_info_buf
); i
++)
2467 char_info_buf
[i
].Char
.UnicodeChar
= '0' + i
% 10;
2468 char_info_buf
[i
].Attributes
= 0;
2471 ret
= GetConsoleScreenBufferInfo(console
, &info
);
2472 ok(ret
, "GetConsoleScreenBufferInfo failed: %u\n", GetLastError());
2478 set_region(®ion
, 10, 7, 15, 11);
2479 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2480 ok(ret
, "WriteConsoleOutputW failed: %u\n", GetLastError());
2481 check_region(®ion
, 10, 7, 15, 11);
2487 set_region(®ion
, 200, 7, 15, 211);
2488 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2489 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
2490 check_region(®ion
, 200, 7, 15, 211);
2496 set_region(®ion
, 200, 7, 211, 8);
2497 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2498 ok(ret
, "WriteConsoleOutputW failed: %u\n", GetLastError());
2499 check_region(®ion
, 200, 7, 211, 8);
2505 set_region(®ion
, 10, 7, 9, 11);
2506 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2507 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
2508 check_region(®ion
, 10, 7, 9, 11);
2514 set_region(®ion
, 10, 7, 11, 6);
2515 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2516 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
2517 check_region(®ion
, 10, 7, 11, 6);
2523 set_region(®ion
, 10, 7, 15, 11);
2524 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2525 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
2526 check_region(®ion
, 10, 7, 15, 11);
2532 set_region(®ion
, 10, 7, 15, 11);
2533 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2534 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
2535 check_region(®ion
, 10, 7, 15, 11);
2541 set_region(®ion
, 10, 7, 15, 11);
2542 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2543 ok(ret
, "WriteConsoleOutputW failed: %u\n", GetLastError());
2544 check_region(®ion
, 10, 7, 13, 11);
2550 set_region(®ion
, 10, 7, 15, 11);
2551 ret
= WriteConsoleOutputW((HANDLE
)0xdeadbeef, char_info_buf
, size
, coord
, ®ion
);
2552 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "WriteConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
2553 if (!skip_nt
) check_region(®ion
, 10, 7, 13, 11);
2559 set_region(®ion
, 10, 7, 15, 11);
2560 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2561 ok(ret
, "WriteConsoleOutputW failed: %u\n", GetLastError());
2562 check_region(®ion
, 10, 7, 15, 10);
2568 set_region(®ion
, info
.dwSize
.X
- 2, 7, info
.dwSize
.X
+ 2, 7);
2569 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2570 ok(ret
, "WriteConsoleOutputW failed: %u\n", GetLastError());
2571 check_region(®ion
, info
.dwSize
.X
- 2, 7, info
.dwSize
.X
- 1, 7);
2574 static void test_FillConsoleOutputCharacterA(HANDLE output_handle
)
2576 COORD origin
= {0, 0};
2583 HANDLE hConsoleOutput
;
2587 LPDWORD lpNumCharsWritten
;
2592 {NULL
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2593 {NULL
, 'a', 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2594 {NULL
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2595 {NULL
, 'a', 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2596 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2597 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2598 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2599 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2600 {output_handle
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2601 {output_handle
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2604 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2606 if (invalid_table
[i
].win7_crash
)
2609 SetLastError(0xdeadbeef);
2610 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2611 ret
= FillConsoleOutputCharacterA(invalid_table
[i
].hConsoleOutput
,
2612 invalid_table
[i
].ch
,
2613 invalid_table
[i
].length
,
2614 invalid_table
[i
].coord
,
2615 invalid_table
[i
].lpNumCharsWritten
);
2616 ok(!ret
, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i
, ret
);
2617 ok(GetLastError() == invalid_table
[i
].last_error
,
2618 "[%d] Expected last error to be %u, got %u\n",
2619 i
, invalid_table
[i
].last_error
, GetLastError());
2623 ret
= FillConsoleOutputCharacterA(output_handle
, 'a', 0, origin
, &count
);
2624 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2625 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2628 ret
= FillConsoleOutputCharacterA(output_handle
, 'a', 1, origin
, &count
);
2629 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2630 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2633 static void test_FillConsoleOutputCharacterW(HANDLE output_handle
)
2635 COORD origin
= {0, 0};
2642 HANDLE hConsoleOutput
;
2646 LPDWORD lpNumCharsWritten
;
2651 {NULL
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2652 {NULL
, 'a', 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2653 {NULL
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2654 {NULL
, 'a', 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2655 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2656 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2657 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2658 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2659 {output_handle
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2660 {output_handle
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2663 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2665 if (invalid_table
[i
].win7_crash
)
2668 SetLastError(0xdeadbeef);
2669 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2670 ret
= FillConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
2671 invalid_table
[i
].ch
,
2672 invalid_table
[i
].length
,
2673 invalid_table
[i
].coord
,
2674 invalid_table
[i
].lpNumCharsWritten
);
2675 ok(!ret
, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
2676 ok(GetLastError() == invalid_table
[i
].last_error
,
2677 "[%d] Expected last error to be %u, got %u\n",
2678 i
, invalid_table
[i
].last_error
, GetLastError());
2682 ret
= FillConsoleOutputCharacterW(output_handle
, 'a', 0, origin
, &count
);
2683 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2684 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2687 ret
= FillConsoleOutputCharacterW(output_handle
, 'a', 1, origin
, &count
);
2688 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2689 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2692 static void test_FillConsoleOutputAttribute(HANDLE output_handle
)
2694 COORD origin
= {0, 0};
2701 HANDLE hConsoleOutput
;
2705 LPDWORD lpNumAttrsWritten
;
2710 {NULL
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2711 {NULL
, FOREGROUND_BLUE
, 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2712 {NULL
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2713 {NULL
, FOREGROUND_BLUE
, 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2714 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2715 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2716 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2717 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2718 {output_handle
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2719 {output_handle
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2722 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2724 if (invalid_table
[i
].win7_crash
)
2727 SetLastError(0xdeadbeef);
2728 if (invalid_table
[i
].lpNumAttrsWritten
) count
= 0xdeadbeef;
2729 ret
= FillConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
2730 invalid_table
[i
].attr
,
2731 invalid_table
[i
].length
,
2732 invalid_table
[i
].coord
,
2733 invalid_table
[i
].lpNumAttrsWritten
);
2734 ok(!ret
, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
2735 ok(GetLastError() == invalid_table
[i
].last_error
,
2736 "[%d] Expected last error to be %u, got %u\n",
2737 i
, invalid_table
[i
].last_error
, GetLastError());
2741 ret
= FillConsoleOutputAttribute(output_handle
, FOREGROUND_BLUE
, 0, origin
, &count
);
2742 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2743 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2746 ret
= FillConsoleOutputAttribute(output_handle
, FOREGROUND_BLUE
, 1, origin
, &count
);
2747 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2748 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2751 ret
= FillConsoleOutputAttribute(output_handle
, ~0, 1, origin
, &count
);
2752 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2753 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2756 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle
)
2759 COORD origin
= {0, 0};
2766 HANDLE hConsoleOutput
;
2771 DWORD expected_count
;
2776 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2777 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2778 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2779 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2780 {NULL
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2781 {NULL
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2782 {NULL
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2783 {NULL
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2784 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2785 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2786 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2787 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2788 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2789 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2790 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2791 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2792 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2793 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2794 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
2795 {output_handle
, NULL
, 10, {0, 0}, &count
, 10, ERROR_INVALID_ACCESS
, 1},
2796 {output_handle
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2797 {output_handle
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2800 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2802 if (invalid_table
[i
].win7_crash
)
2805 SetLastError(0xdeadbeef);
2806 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
2807 ret
= ReadConsoleOutputCharacterA(invalid_table
[i
].hConsoleOutput
,
2808 invalid_table
[i
].lpstr
,
2809 invalid_table
[i
].length
,
2810 invalid_table
[i
].coord
,
2811 invalid_table
[i
].read_count
);
2812 ok(!ret
, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i
, ret
);
2813 if (invalid_table
[i
].read_count
)
2815 ok(count
== invalid_table
[i
].expected_count
,
2816 "[%d] Expected count to be %u, got %u\n",
2817 i
, invalid_table
[i
].expected_count
, count
);
2819 ok(GetLastError() == invalid_table
[i
].last_error
,
2820 "[%d] Expected last error to be %u, got %u\n",
2821 i
, invalid_table
[i
].last_error
, GetLastError());
2825 ret
= ReadConsoleOutputCharacterA(output_handle
, NULL
, 0, origin
, &count
);
2826 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2827 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2830 ret
= ReadConsoleOutputCharacterA(output_handle
, &read
, 0, origin
, &count
);
2831 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2832 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2835 ret
= ReadConsoleOutputCharacterA(output_handle
, &read
, 1, origin
, &count
);
2836 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2837 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2841 ret
= ReadConsoleOutputCharacterA(output_handle
, &read
, 1, origin
, &count
);
2842 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2843 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2846 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle
)
2849 COORD origin
= {0, 0};
2856 HANDLE hConsoleOutput
;
2861 DWORD expected_count
;
2866 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2867 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2868 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2869 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2870 {NULL
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2871 {NULL
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2872 {NULL
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2873 {NULL
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2874 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2875 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2876 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2877 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2878 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2879 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2880 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2881 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2882 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2883 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2884 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
2885 {output_handle
, NULL
, 10, {0, 0}, &count
, 10, ERROR_INVALID_ACCESS
, 1},
2886 {output_handle
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2887 {output_handle
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2890 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2892 if (invalid_table
[i
].win7_crash
)
2895 SetLastError(0xdeadbeef);
2896 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
2897 ret
= ReadConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
2898 invalid_table
[i
].buffer
,
2899 invalid_table
[i
].length
,
2900 invalid_table
[i
].coord
,
2901 invalid_table
[i
].read_count
);
2902 ok(!ret
, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
2903 if (invalid_table
[i
].read_count
)
2905 ok(count
== invalid_table
[i
].expected_count
,
2906 "[%d] Expected count to be %u, got %u\n",
2907 i
, invalid_table
[i
].expected_count
, count
);
2909 ok(GetLastError() == invalid_table
[i
].last_error
,
2910 "[%d] Expected last error to be %u, got %u\n",
2911 i
, invalid_table
[i
].last_error
, GetLastError());
2915 ret
= ReadConsoleOutputCharacterW(output_handle
, NULL
, 0, origin
, &count
);
2916 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2917 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2920 ret
= ReadConsoleOutputCharacterW(output_handle
, &read
, 0, origin
, &count
);
2921 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2922 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2925 ret
= ReadConsoleOutputCharacterW(output_handle
, &read
, 1, origin
, &count
);
2926 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2927 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
2931 ret
= ReadConsoleOutputCharacterW(output_handle
, &read
, 1, origin
, &count
);
2932 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2933 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
2936 static void test_ReadConsoleOutputAttribute(HANDLE output_handle
)
2939 COORD origin
= {0, 0};
2946 HANDLE hConsoleOutput
;
2951 DWORD expected_count
;
2956 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2957 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2958 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2959 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2960 {NULL
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2961 {NULL
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2962 {NULL
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2963 {NULL
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2964 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2965 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2966 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2967 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
2968 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2969 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2970 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2971 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2972 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2973 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2974 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
2975 {output_handle
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2976 {output_handle
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2979 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2981 if (invalid_table
[i
].win7_crash
)
2984 SetLastError(0xdeadbeef);
2985 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
2986 ret
= ReadConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
2987 invalid_table
[i
].lpAttribute
,
2988 invalid_table
[i
].length
,
2989 invalid_table
[i
].coord
,
2990 invalid_table
[i
].read_count
);
2991 ok(!ret
, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
2992 if (invalid_table
[i
].read_count
)
2994 ok(count
== invalid_table
[i
].expected_count
,
2995 "[%d] Expected count to be %u, got %u\n",
2996 i
, invalid_table
[i
].expected_count
, count
);
2998 ok(GetLastError() == invalid_table
[i
].last_error
,
2999 "[%d] Expected last error to be %u, got %u\n",
3000 i
, invalid_table
[i
].last_error
, GetLastError());
3004 ret
= ReadConsoleOutputAttribute(output_handle
, NULL
, 0, origin
, &count
);
3005 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
3006 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
3009 ret
= ReadConsoleOutputAttribute(output_handle
, &attr
, 0, origin
, &count
);
3010 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
3011 ok(count
== 0, "Expected count to be 0, got %u\n", count
);
3014 ret
= ReadConsoleOutputAttribute(output_handle
, &attr
, 1, origin
, &count
);
3015 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
3016 ok(count
== 1, "Expected count to be 1, got %u\n", count
);
3020 ret
= ReadConsoleOutputAttribute(output_handle
, &attr
, 1, origin
, &count
);
3021 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
3022 ok(count
== 0, "Expected count to be 1, got %u\n", count
);
3025 static void test_ReadConsoleOutput(HANDLE console
)
3027 CONSOLE_SCREEN_BUFFER_INFO info
;
3028 CHAR_INFO char_info_buf
[2048];
3035 if (skip_nt
) return;
3037 ret
= GetConsoleScreenBufferInfo(console
, &info
);
3038 ok(ret
, "GetConsoleScreenBufferInfo failed: %u\n", GetLastError());
3044 set_region(®ion
, 10, 7, 15, 11);
3045 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3046 ok(ret
, "ReadConsoleOutputW failed: %u\n", GetLastError());
3047 check_region(®ion
, 10, 7, 15, 11);
3053 set_region(®ion
, 200, 7, 15, 211);
3054 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3055 ok(!ret
, "ReadConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
3056 check_region(®ion
, 200, 7, -15, 0);
3062 set_region(®ion
, 200, 7, 211, 8);
3063 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3064 ok((!ret
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_INVALID_FUNCTION
)) || broken(ret
/* win8 */),
3065 "ReadConsoleOutputW returned: %x %u\n", ret
, GetLastError());
3066 if (!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
) check_region(®ion
, 200, 7, -211, -8);
3072 set_region(®ion
, 10, 7, 9, 11);
3073 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3074 ok((!ret
&& (GetLastError() == ERROR_INVALID_FUNCTION
|| GetLastError() == ERROR_NOT_ENOUGH_MEMORY
)) || broken(ret
/* win8 */),
3075 "ReadConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
3076 check_region(®ion
, 10, 7, 9, -11);
3082 set_region(®ion
, 10, 7, 11, 6);
3083 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3084 ok((!ret
&& (GetLastError() == ERROR_INVALID_FUNCTION
|| GetLastError() == ERROR_NOT_ENOUGH_MEMORY
)) || broken(ret
/* win8 */),
3085 "ReadConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
3086 check_region(®ion
, 10, 7, -11, 6);
3092 set_region(®ion
, 10, 7, 15, 11);
3093 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3094 ok((!ret
&& (GetLastError() == ERROR_INVALID_FUNCTION
|| GetLastError() == ERROR_NOT_ENOUGH_MEMORY
)) || broken(ret
/* win8 */),
3095 "ReadConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
3096 check_region(®ion
, 10, 7, -15, -11);
3102 set_region(®ion
, 10, 7, 15, 11);
3103 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3104 ok((!ret
&& (GetLastError() == ERROR_INVALID_FUNCTION
|| GetLastError() == ERROR_NOT_ENOUGH_MEMORY
)) || broken(ret
/* win8 */),
3105 "ReadConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
3106 check_region(®ion
, 10, 7, -15, 6);
3112 set_region(®ion
, 10, 7, 15, 11);
3113 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3114 ok(ret
, "ReadConsoleOutputW failed: %u\n", GetLastError());
3115 check_region(®ion
, 10, 7, 13, 11);
3121 set_region(®ion
, 10, 7, 15, 11);
3122 ret
= ReadConsoleOutputW((HANDLE
)0xdeadbeef, char_info_buf
, size
, coord
, ®ion
);
3123 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "ReadConsoleOutputW returned: %x(%u)\n", ret
, GetLastError());
3124 if (!skip_nt
) check_region(®ion
, 10, 7, 13, 11);
3130 set_region(®ion
, 10, 7, 15, 11);
3131 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3132 ok(ret
, "ReadConsoleOutputW failed: %u\n", GetLastError());
3133 check_region(®ion
, 10, 7, 15, 10);
3139 set_region(®ion
, info
.dwSize
.X
- 2, 7, info
.dwSize
.X
+ 2, 7);
3140 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3141 ok(ret
|| GetLastError() == ERROR_INVALID_PARAMETER
, "ReadConsoleOutputW failed: %u\n", GetLastError());
3142 if (ret
) check_region(®ion
, info
.dwSize
.X
- 2, 7, info
.dwSize
.X
- 1, 7);
3146 ret
= WriteConsoleOutputCharacterW(console
, L
"xyz", 3, coord
, &count
);
3147 ok(ret
, "WriteConsoleOutputCharacterW failed: %u\n", GetLastError());
3148 ok(count
== 3, "count = %u\n", count
);
3150 memset(char_info_buf
, 0xc0, sizeof(char_info_buf
));
3155 set_region(®ion
, 2, 3, 5, 3);
3156 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3157 ok(ret
, "ReadConsoleOutputW failed: %u\n", GetLastError());
3158 check_region(®ion
, 2, 3, 5, 3);
3159 ch
= char_info_buf
[coord
.Y
* size
.X
+ coord
.X
].Char
.UnicodeChar
;
3160 ok(ch
== 'x', "unexpected char %c/%x\n", ch
, ch
);
3161 ch
= char_info_buf
[coord
.Y
* size
.X
+ coord
.X
+ 1].Char
.UnicodeChar
;
3162 ok(ch
== 'y', "unexpected char %c/%x\n", ch
, ch
);
3163 ch
= char_info_buf
[coord
.Y
* size
.X
+ coord
.X
+ 2].Char
.UnicodeChar
;
3164 ok(ch
== 'z', "unexpected char %c/%x\n", ch
, ch
);
3167 static void test_ReadConsole(HANDLE input
)
3173 SetLastError(0xdeadbeef);
3174 ret
= GetFileSize(input
, NULL
);
3175 ok(ret
== INVALID_FILE_SIZE
, "expected INVALID_FILE_SIZE, got %#x\n", ret
);
3176 ok(GetLastError() == ERROR_INVALID_HANDLE
||
3177 GetLastError() == ERROR_INVALID_FUNCTION
, /* Win 8, 10 */
3178 "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
3181 SetLastError(0xdeadbeef);
3182 ret
= ReadFile(input
, buf
, -128, &bytes
, NULL
);
3183 ok(!ret
, "expected 0, got %u\n", ret
);
3184 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
||
3185 GetLastError() == ERROR_NOACCESS
, /* Win 8, 10 */
3186 "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
3187 ok(!bytes
, "expected 0, got %u\n", bytes
);
3190 SetLastError(0xdeadbeef);
3191 ret
= ReadConsoleA(input
, buf
, -128, &bytes
, NULL
);
3192 ok(!ret
, "expected 0, got %u\n", ret
);
3193 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
||
3194 GetLastError() == ERROR_NOACCESS
, /* Win 8, 10 */
3195 "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
3196 ok(bytes
== 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes
);
3199 SetLastError(0xdeadbeef);
3200 ret
= ReadConsoleW(input
, buf
, -128, &bytes
, NULL
);
3201 ok(!ret
, "expected 0, got %u\n", ret
);
3202 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
||
3203 GetLastError() == ERROR_NOACCESS
, /* Win 8, 10 */
3204 "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
3205 ok(bytes
== 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes
);
3207 output
= CreateFileA("CONOUT$", GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3208 ok(output
!= INVALID_HANDLE_VALUE
, "Could not open console\n");
3210 ret
= ReadConsoleW(output
, buf
, sizeof(buf
) / sizeof(WCHAR
), &bytes
, NULL
);
3211 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3212 "ReadConsoleW returned %x(%u)\n", ret
, GetLastError());
3214 ret
= ReadConsoleA(output
, buf
, sizeof(buf
), &bytes
, NULL
);
3215 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3216 "ReadConsoleA returned %x(%u)\n", ret
, GetLastError());
3218 ret
= ReadFile(output
, buf
, sizeof(buf
), &bytes
, NULL
);
3219 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3220 "ReadFile returned %x(%u)\n", ret
, GetLastError());
3222 CloseHandle(output
);
3225 static void test_GetCurrentConsoleFont(HANDLE std_output
)
3228 CONSOLE_FONT_INFO cfi
;
3229 CONSOLE_SCREEN_BUFFER_INFO csbi
;
3230 short int width
, height
;
3231 HANDLE pipe1
, pipe2
;
3234 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3235 SetLastError(0xdeadbeef);
3236 ret
= GetCurrentConsoleFont(NULL
, FALSE
, &cfi
);
3237 ok(!ret
, "got %d, expected 0\n", ret
);
3238 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3239 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3240 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3242 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3243 SetLastError(0xdeadbeef);
3244 ret
= GetCurrentConsoleFont(NULL
, TRUE
, &cfi
);
3245 ok(!ret
, "got %d, expected 0\n", ret
);
3246 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3247 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3248 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3250 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3251 SetLastError(0xdeadbeef);
3252 ret
= GetCurrentConsoleFont(GetStdHandle(STD_INPUT_HANDLE
), FALSE
, &cfi
);
3253 ok(!ret
, "got %d, expected 0\n", ret
);
3254 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3255 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3256 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3258 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3259 SetLastError(0xdeadbeef);
3260 ret
= GetCurrentConsoleFont(GetStdHandle(STD_INPUT_HANDLE
), TRUE
, &cfi
);
3261 ok(!ret
, "got %d, expected 0\n", ret
);
3262 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3263 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3264 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3266 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3267 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3268 SetLastError(0xdeadbeef);
3269 ret
= GetCurrentConsoleFont(pipe1
, TRUE
, &cfi
);
3270 ok(!ret
, "got %d, expected 0\n", ret
);
3271 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3272 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3273 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3277 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3278 SetLastError(0xdeadbeef);
3279 ret
= GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3280 ok(ret
, "got %d, expected non-zero\n", ret
);
3281 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3282 GetConsoleScreenBufferInfo(std_output
, &csbi
);
3283 width
= csbi
.srWindow
.Right
- csbi
.srWindow
.Left
+ 1;
3284 height
= csbi
.srWindow
.Bottom
- csbi
.srWindow
.Top
+ 1;
3285 c
= GetConsoleFontSize(std_output
, cfi
.nFont
);
3286 ok(cfi
.dwFontSize
.X
== width
|| cfi
.dwFontSize
.X
== c
.X
/* Vista and higher */,
3287 "got %d, expected %d\n", cfi
.dwFontSize
.X
, width
);
3288 ok(cfi
.dwFontSize
.Y
== height
|| cfi
.dwFontSize
.Y
== c
.Y
/* Vista and higher */,
3289 "got %d, expected %d\n", cfi
.dwFontSize
.Y
, height
);
3291 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3292 SetLastError(0xdeadbeef);
3293 ret
= GetCurrentConsoleFont(std_output
, TRUE
, &cfi
);
3294 ok(ret
, "got %d, expected non-zero\n", ret
);
3295 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3296 ok(cfi
.dwFontSize
.X
== csbi
.dwMaximumWindowSize
.X
,
3297 "got %d, expected %d\n", cfi
.dwFontSize
.X
, csbi
.dwMaximumWindowSize
.X
);
3298 ok(cfi
.dwFontSize
.Y
== csbi
.dwMaximumWindowSize
.Y
,
3299 "got %d, expected %d\n", cfi
.dwFontSize
.Y
, csbi
.dwMaximumWindowSize
.Y
);
3302 static void test_GetCurrentConsoleFontEx(HANDLE std_output
)
3305 BOOL (WINAPI
*pGetCurrentConsoleFontEx
)(HANDLE
, BOOL
, CONSOLE_FONT_INFOEX
*);
3306 CONSOLE_FONT_INFO cfi
;
3307 CONSOLE_FONT_INFOEX cfix
;
3309 HANDLE std_input
= GetStdHandle(STD_INPUT_HANDLE
);
3310 HANDLE pipe1
, pipe2
;
3312 hmod
= GetModuleHandleA("kernel32.dll");
3313 pGetCurrentConsoleFontEx
= (void *)GetProcAddress(hmod
, "GetCurrentConsoleFontEx");
3314 if (!pGetCurrentConsoleFontEx
)
3316 win_skip("GetCurrentConsoleFontEx is not available\n");
3320 SetLastError(0xdeadbeef);
3321 ret
= pGetCurrentConsoleFontEx(NULL
, FALSE
, &cfix
);
3322 ok(!ret
, "got %d, expected 0\n", ret
);
3323 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3325 SetLastError(0xdeadbeef);
3326 ret
= pGetCurrentConsoleFontEx(NULL
, TRUE
, &cfix
);
3327 ok(!ret
, "got %d, expected 0\n", ret
);
3328 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3330 SetLastError(0xdeadbeef);
3331 ret
= pGetCurrentConsoleFontEx(std_input
, FALSE
, &cfix
);
3332 ok(!ret
, "got %d, expected 0\n", ret
);
3333 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3335 SetLastError(0xdeadbeef);
3336 ret
= pGetCurrentConsoleFontEx(std_input
, TRUE
, &cfix
);
3337 ok(!ret
, "got %d, expected 0\n", ret
);
3338 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3340 SetLastError(0xdeadbeef);
3341 ret
= pGetCurrentConsoleFontEx(std_output
, FALSE
, &cfix
);
3342 ok(!ret
, "got %d, expected 0\n", ret
);
3343 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3345 SetLastError(0xdeadbeef);
3346 ret
= pGetCurrentConsoleFontEx(std_output
, TRUE
, &cfix
);
3347 ok(!ret
, "got %d, expected 0\n", ret
);
3348 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3350 cfix
.cbSize
= sizeof(CONSOLE_FONT_INFOEX
);
3352 SetLastError(0xdeadbeef);
3353 ret
= pGetCurrentConsoleFontEx(NULL
, FALSE
, &cfix
);
3354 ok(!ret
, "got %d, expected 0\n", ret
);
3355 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3357 SetLastError(0xdeadbeef);
3358 ret
= pGetCurrentConsoleFontEx(NULL
, TRUE
, &cfix
);
3359 ok(!ret
, "got %d, expected 0\n", ret
);
3360 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3362 SetLastError(0xdeadbeef);
3363 ret
= pGetCurrentConsoleFontEx(std_input
, FALSE
, &cfix
);
3364 ok(!ret
, "got %d, expected 0\n", ret
);
3365 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3367 SetLastError(0xdeadbeef);
3368 ret
= pGetCurrentConsoleFontEx(std_input
, TRUE
, &cfix
);
3369 ok(!ret
, "got %d, expected 0\n", ret
);
3370 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3372 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3373 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3374 SetLastError(0xdeadbeef);
3375 ret
= pGetCurrentConsoleFontEx(pipe1
, TRUE
, &cfix
);
3376 ok(!ret
, "got %d, expected 0\n", ret
);
3377 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3381 SetLastError(0xdeadbeef);
3382 ret
= pGetCurrentConsoleFontEx(std_output
, FALSE
, &cfix
);
3383 ok(ret
, "got %d, expected non-zero\n", ret
);
3384 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3386 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3387 SetLastError(0xdeadbeef);
3388 ret
= GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3389 ok(ret
, "got %d, expected non-zero\n", ret
);
3390 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3392 ok(cfix
.dwFontSize
.X
== cfi
.dwFontSize
.X
, "expected values to match\n");
3393 ok(cfix
.dwFontSize
.Y
== cfi
.dwFontSize
.Y
, "expected values to match\n");
3395 SetLastError(0xdeadbeef);
3396 ret
= pGetCurrentConsoleFontEx(std_output
, TRUE
, &cfix
);
3397 ok(ret
, "got %d, expected non-zero\n", ret
);
3398 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3400 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3401 SetLastError(0xdeadbeef);
3402 ret
= GetCurrentConsoleFont(std_output
, TRUE
, &cfi
);
3403 ok(ret
, "got %d, expected non-zero\n", ret
);
3404 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3406 ok(cfix
.dwFontSize
.X
== cfi
.dwFontSize
.X
, "expected values to match\n");
3407 ok(cfix
.dwFontSize
.Y
== cfi
.dwFontSize
.Y
, "expected values to match\n");
3410 static void test_GetConsoleFontSize(HANDLE std_output
)
3414 CONSOLE_FONT_INFO cfi
;
3416 CONSOLE_SCREEN_BUFFER_INFO csbi
;
3417 LONG font_width
, font_height
;
3419 DWORD (WINAPI
*pGetNumberOfConsoleFonts
)(void);
3420 HANDLE pipe1
, pipe2
;
3422 memset(&c
, 10, sizeof(COORD
));
3423 SetLastError(0xdeadbeef);
3424 c
= GetConsoleFontSize(NULL
, index
);
3425 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3426 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3427 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3429 memset(&c
, 10, sizeof(COORD
));
3430 SetLastError(0xdeadbeef);
3431 c
= GetConsoleFontSize(GetStdHandle(STD_INPUT_HANDLE
), index
);
3432 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3433 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3434 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3436 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3437 memset(&c
, 10, sizeof(COORD
));
3438 SetLastError(0xdeadbeef);
3439 c
= GetConsoleFontSize(pipe1
, index
);
3440 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3441 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3442 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3446 GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3447 memset(&c
, 10, sizeof(COORD
));
3448 SetLastError(0xdeadbeef);
3449 c
= GetConsoleFontSize(std_output
, cfi
.nFont
);
3450 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3451 GetClientRect(GetConsoleWindow(), &r
);
3452 GetConsoleScreenBufferInfo(std_output
, &csbi
);
3453 font_width
= (r
.right
- r
.left
+ 1) / csbi
.srWindow
.Right
;
3454 font_height
= (r
.bottom
- r
.top
+ 1) / csbi
.srWindow
.Bottom
;
3455 ok(c
.X
== font_width
, "got %d, expected %d\n", c
.X
, font_width
);
3456 ok(c
.Y
== font_height
, "got %d, expected %d\n", c
.Y
, font_height
);
3458 hmod
= GetModuleHandleA("kernel32.dll");
3459 pGetNumberOfConsoleFonts
= (void *)GetProcAddress(hmod
, "GetNumberOfConsoleFonts");
3460 if (!pGetNumberOfConsoleFonts
)
3462 win_skip("GetNumberOfConsoleFonts is not available\n");
3465 index
= pGetNumberOfConsoleFonts();
3467 memset(&c
, 10, sizeof(COORD
));
3468 SetLastError(0xdeadbeef);
3469 c
= GetConsoleFontSize(std_output
, index
);
3470 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef) /* win10 1809 */,
3471 "unexpected last error %u\n", GetLastError());
3472 if (GetLastError() == ERROR_INVALID_PARAMETER
)
3474 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3475 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3479 static void test_GetLargestConsoleWindowSize(HANDLE std_output
)
3483 LONG workarea_w
, workarea_h
, maxcon_w
, maxcon_h
;
3484 CONSOLE_SCREEN_BUFFER_INFO sbi
;
3485 CONSOLE_FONT_INFO cfi
;
3486 HANDLE pipe1
, pipe2
;
3490 DWORD (WINAPI
*pGetNumberOfConsoleFonts
)(void);
3491 BOOL (WINAPI
*pSetConsoleFont
)(HANDLE
, DWORD
);
3493 memset(&c
, 10, sizeof(COORD
));
3494 SetLastError(0xdeadbeef);
3495 c
= GetLargestConsoleWindowSize(NULL
);
3496 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3497 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3498 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3500 memset(&c
, 10, sizeof(COORD
));
3501 SetLastError(0xdeadbeef);
3502 c
= GetLargestConsoleWindowSize(GetStdHandle(STD_INPUT_HANDLE
));
3503 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3504 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3505 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3507 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3508 memset(&c
, 10, sizeof(COORD
));
3509 SetLastError(0xdeadbeef);
3510 c
= GetLargestConsoleWindowSize(pipe1
);
3511 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3512 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3513 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3517 SystemParametersInfoW(SPI_GETWORKAREA
, 0, &r
, 0);
3518 workarea_w
= r
.right
- r
.left
;
3519 workarea_h
= r
.bottom
- r
.top
- GetSystemMetrics(SM_CYCAPTION
);
3521 GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3522 index
= cfi
.nFont
; /* save current font index */
3524 hmod
= GetModuleHandleA("kernel32.dll");
3525 pGetNumberOfConsoleFonts
= (void *)GetProcAddress(hmod
, "GetNumberOfConsoleFonts");
3526 if (!pGetNumberOfConsoleFonts
)
3528 win_skip("GetNumberOfConsoleFonts is not available\n");
3531 pSetConsoleFont
= (void *)GetProcAddress(hmod
, "SetConsoleFont");
3532 if (!pSetConsoleFont
)
3534 win_skip("SetConsoleFont is not available\n");
3538 for (i
= 0; i
< pGetNumberOfConsoleFonts(); i
++)
3540 pSetConsoleFont(std_output
, i
);
3541 memset(&c
, 10, sizeof(COORD
));
3542 SetLastError(0xdeadbeef);
3543 c
= GetLargestConsoleWindowSize(std_output
);
3544 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3545 GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3546 font
= GetConsoleFontSize(std_output
, cfi
.nFont
);
3547 maxcon_w
= workarea_w
/ font
.X
;
3548 maxcon_h
= workarea_h
/ font
.Y
;
3549 ok(c
.X
== maxcon_w
|| c
.X
== maxcon_w
- 1 /* Win10 */, "got %d, expected %d\n", c
.X
, maxcon_w
);
3550 ok(c
.Y
== maxcon_h
|| c
.Y
== maxcon_h
- 1 /* Win10 */, "got %d, expected %d\n", c
.Y
, maxcon_h
);
3552 ret
= GetConsoleScreenBufferInfo(std_output
, &sbi
);
3553 ok(ret
, "GetConsoleScreenBufferInfo failed %u\n", GetLastError());
3554 ok(sbi
.dwMaximumWindowSize
.X
== min(c
.X
, sbi
.dwSize
.X
), "got %d, expected %d\n",
3555 sbi
.dwMaximumWindowSize
.X
, min(c
.X
, sbi
.dwSize
.X
));
3556 ok(sbi
.dwMaximumWindowSize
.Y
== min(c
.Y
, sbi
.dwSize
.Y
), "got %d, expected %d\n",
3557 sbi
.dwMaximumWindowSize
.Y
, min(c
.Y
, sbi
.dwSize
.Y
));
3559 pSetConsoleFont(std_output
, index
); /* restore original font size */
3562 static void test_GetConsoleFontInfo(HANDLE std_output
)
3565 BOOL (WINAPI
*pGetConsoleFontInfo
)(HANDLE
, BOOL
, DWORD
, CONSOLE_FONT_INFO
*);
3566 DWORD (WINAPI
*pGetNumberOfConsoleFonts
)(void);
3567 DWORD num_fonts
, index
, i
;
3568 int memsize
, win_width
, win_height
, tmp_w
, tmp_h
;
3569 CONSOLE_FONT_INFO
*cfi
;
3571 CONSOLE_SCREEN_BUFFER_INFO csbi
;
3572 COORD orig_sb_size
, tmp_sb_size
, orig_font
, tmp_font
;
3574 hmod
= GetModuleHandleA("kernel32.dll");
3575 pGetConsoleFontInfo
= (void *)GetProcAddress(hmod
, "GetConsoleFontInfo");
3576 if (!pGetConsoleFontInfo
)
3578 win_skip("GetConsoleFontInfo is not available\n");
3582 pGetNumberOfConsoleFonts
= (void *)GetProcAddress(hmod
, "GetNumberOfConsoleFonts");
3583 if (!pGetNumberOfConsoleFonts
)
3585 skip("GetNumberOfConsoleFonts is not available\n");
3589 num_fonts
= pGetNumberOfConsoleFonts();
3590 memsize
= num_fonts
* sizeof(CONSOLE_FONT_INFO
);
3591 cfi
= HeapAlloc(GetProcessHeap(), 0, memsize
);
3592 memset(cfi
, 0, memsize
);
3594 GetConsoleScreenBufferInfo(std_output
, &csbi
);
3595 orig_sb_size
= csbi
.dwSize
;
3596 tmp_sb_size
.X
= csbi
.dwSize
.X
+ 3;
3597 tmp_sb_size
.Y
= csbi
.dwSize
.Y
+ 5;
3598 SetConsoleScreenBufferSize(std_output
, tmp_sb_size
);
3600 SetLastError(0xdeadbeef);
3601 ret
= pGetConsoleFontInfo(NULL
, FALSE
, 0, cfi
);
3602 ok(!ret
, "got %d, expected zero\n", ret
);
3603 if (GetLastError() == LOWORD(E_NOTIMPL
) /* win10 1709+ */ ||
3604 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win10 1607 */)
3606 skip("GetConsoleFontInfo is not implemented\n");
3607 SetConsoleScreenBufferSize(std_output
, orig_sb_size
);
3608 HeapFree(GetProcessHeap(), 0, cfi
);
3611 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3613 SetLastError(0xdeadbeef);
3614 ret
= pGetConsoleFontInfo(GetStdHandle(STD_INPUT_HANDLE
), FALSE
, 0, cfi
);
3615 ok(!ret
, "got %d, expected zero\n", ret
);
3616 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3618 SetLastError(0xdeadbeef);
3619 ret
= pGetConsoleFontInfo(std_output
, FALSE
, 0, cfi
);
3620 ok(!ret
, "got %d, expected zero\n", ret
);
3621 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3623 GetConsoleScreenBufferInfo(std_output
, &csbi
);
3624 win_width
= csbi
.srWindow
.Right
- csbi
.srWindow
.Left
+ 1;
3625 win_height
= csbi
.srWindow
.Bottom
- csbi
.srWindow
.Top
+ 1;
3627 GetCurrentConsoleFont(std_output
, FALSE
, &cfi
[0]);
3628 index
= cfi
[0].nFont
;
3629 orig_font
= GetConsoleFontSize(std_output
, index
);
3631 memset(cfi
, 0, memsize
);
3632 ret
= pGetConsoleFontInfo(std_output
, FALSE
, num_fonts
, cfi
);
3633 ok(ret
, "got %d, expected non-zero\n", ret
);
3634 ok(cfi
[index
].dwFontSize
.X
== win_width
, "got %d, expected %d\n",
3635 cfi
[index
].dwFontSize
.X
, win_width
);
3636 ok(cfi
[index
].dwFontSize
.Y
== win_height
, "got %d, expected %d\n",
3637 cfi
[index
].dwFontSize
.Y
, win_height
);
3639 for (i
= 0; i
< num_fonts
; i
++)
3641 ok(cfi
[i
].nFont
== i
, "element out of order, got nFont %d, expected %d\n", cfi
[i
].nFont
, i
);
3642 tmp_font
= GetConsoleFontSize(std_output
, cfi
[i
].nFont
);
3643 tmp_w
= (double)orig_font
.X
/ tmp_font
.X
* win_width
;
3644 tmp_h
= (double)orig_font
.Y
/ tmp_font
.Y
* win_height
;
3645 ok(cfi
[i
].dwFontSize
.X
== tmp_w
, "got %d, expected %d\n", cfi
[i
].dwFontSize
.X
, tmp_w
);
3646 ok(cfi
[i
].dwFontSize
.Y
== tmp_h
, "got %d, expected %d\n", cfi
[i
].dwFontSize
.Y
, tmp_h
);
3649 SetLastError(0xdeadbeef);
3650 ret
= pGetConsoleFontInfo(NULL
, TRUE
, 0, cfi
);
3651 ok(!ret
, "got %d, expected zero\n", ret
);
3652 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3654 SetLastError(0xdeadbeef);
3655 ret
= pGetConsoleFontInfo(GetStdHandle(STD_INPUT_HANDLE
), TRUE
, 0, cfi
);
3656 ok(!ret
, "got %d, expected zero\n", ret
);
3657 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3659 SetLastError(0xdeadbeef);
3660 ret
= pGetConsoleFontInfo(std_output
, TRUE
, 0, cfi
);
3661 ok(!ret
, "got %d, expected zero\n", ret
);
3662 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3664 memset(cfi
, 0, memsize
);
3665 ret
= pGetConsoleFontInfo(std_output
, TRUE
, num_fonts
, cfi
);
3666 ok(ret
, "got %d, expected non-zero\n", ret
);
3667 ok(cfi
[index
].dwFontSize
.X
== csbi
.dwMaximumWindowSize
.X
, "got %d, expected %d\n",
3668 cfi
[index
].dwFontSize
.X
, csbi
.dwMaximumWindowSize
.X
);
3669 ok(cfi
[index
].dwFontSize
.Y
== csbi
.dwMaximumWindowSize
.Y
, "got %d, expected %d\n",
3670 cfi
[index
].dwFontSize
.Y
, csbi
.dwMaximumWindowSize
.Y
);
3672 for (i
= 0; i
< num_fonts
; i
++)
3674 ok(cfi
[i
].nFont
== i
, "element out of order, got nFont %d, expected %d\n", cfi
[i
].nFont
, i
);
3675 tmp_font
= GetConsoleFontSize(std_output
, cfi
[i
].nFont
);
3676 tmp_w
= (double)orig_font
.X
/ tmp_font
.X
* csbi
.dwMaximumWindowSize
.X
;
3677 tmp_h
= (double)orig_font
.Y
/ tmp_font
.Y
* csbi
.dwMaximumWindowSize
.Y
;
3678 ok(cfi
[i
].dwFontSize
.X
== tmp_w
, "got %d, expected %d\n", cfi
[i
].dwFontSize
.X
, tmp_w
);
3679 ok(cfi
[i
].dwFontSize
.Y
== tmp_h
, "got %d, expected %d\n", cfi
[i
].dwFontSize
.Y
, tmp_h
);
3682 HeapFree(GetProcessHeap(), 0, cfi
);
3683 SetConsoleScreenBufferSize(std_output
, orig_sb_size
);
3686 static void test_SetConsoleFont(HANDLE std_output
)
3689 BOOL (WINAPI
*pSetConsoleFont
)(HANDLE
, DWORD
);
3691 DWORD (WINAPI
*pGetNumberOfConsoleFonts
)(void);
3694 hmod
= GetModuleHandleA("kernel32.dll");
3695 pSetConsoleFont
= (void *)GetProcAddress(hmod
, "SetConsoleFont");
3696 if (!pSetConsoleFont
)
3698 win_skip("SetConsoleFont is not available\n");
3702 SetLastError(0xdeadbeef);
3703 ret
= pSetConsoleFont(NULL
, 0);
3704 ok(!ret
, "got %d, expected zero\n", ret
);
3705 if (GetLastError() == LOWORD(E_NOTIMPL
) /* win10 1709+ */ ||
3706 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win10 1607 */)
3708 skip("SetConsoleFont is not implemented\n");
3711 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3713 SetLastError(0xdeadbeef);
3714 ret
= pSetConsoleFont(GetStdHandle(STD_INPUT_HANDLE
), 0);
3715 ok(!ret
, "got %d, expected zero\n", ret
);
3716 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3718 pGetNumberOfConsoleFonts
= (void *)GetProcAddress(hmod
, "GetNumberOfConsoleFonts");
3719 if (!pGetNumberOfConsoleFonts
)
3721 win_skip("GetNumberOfConsoleFonts is not available\n");
3725 num_fonts
= pGetNumberOfConsoleFonts();
3727 SetLastError(0xdeadbeef);
3728 ret
= pSetConsoleFont(std_output
, num_fonts
);
3729 ok(!ret
, "got %d, expected zero\n", ret
);
3730 todo_wine
ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3733 static void test_GetConsoleScreenBufferInfoEx(HANDLE std_output
)
3736 BOOL (WINAPI
*pGetConsoleScreenBufferInfoEx
)(HANDLE
, CONSOLE_SCREEN_BUFFER_INFOEX
*);
3737 CONSOLE_SCREEN_BUFFER_INFOEX csbix
;
3738 HANDLE pipe1
, pipe2
;
3740 HANDLE std_input
= GetStdHandle(STD_INPUT_HANDLE
);
3742 hmod
= GetModuleHandleA("kernel32.dll");
3743 pGetConsoleScreenBufferInfoEx
= (void *)GetProcAddress(hmod
, "GetConsoleScreenBufferInfoEx");
3744 if (!pGetConsoleScreenBufferInfoEx
)
3746 win_skip("GetConsoleScreenBufferInfoEx is not available\n");
3750 SetLastError(0xdeadbeef);
3751 ret
= pGetConsoleScreenBufferInfoEx(NULL
, &csbix
);
3752 ok(!ret
, "got %d, expected zero\n", ret
);
3753 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3755 SetLastError(0xdeadbeef);
3756 ret
= pGetConsoleScreenBufferInfoEx(std_input
, &csbix
);
3757 ok(!ret
, "got %d, expected zero\n", ret
);
3758 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3760 SetLastError(0xdeadbeef);
3761 ret
= pGetConsoleScreenBufferInfoEx(std_output
, &csbix
);
3762 ok(!ret
, "got %d, expected zero\n", ret
);
3763 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3765 csbix
.cbSize
= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
);
3767 SetLastError(0xdeadbeef);
3768 ret
= pGetConsoleScreenBufferInfoEx(NULL
, &csbix
);
3769 ok(!ret
, "got %d, expected zero\n", ret
);
3770 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3772 SetLastError(0xdeadbeef);
3773 ret
= pGetConsoleScreenBufferInfoEx(std_input
, &csbix
);
3774 ok(!ret
, "got %d, expected zero\n", ret
);
3775 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3777 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3778 SetLastError(0xdeadbeef);
3779 ret
= pGetConsoleScreenBufferInfoEx(std_input
, &csbix
);
3780 ok(!ret
, "got %d, expected zero\n", ret
);
3781 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3785 SetLastError(0xdeadbeef);
3786 ret
= pGetConsoleScreenBufferInfoEx(std_output
, &csbix
);
3787 ok(ret
, "got %d, expected non-zero\n", ret
);
3788 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3791 static void test_FreeConsole(void)
3793 HANDLE handle
, unbound_output
= NULL
, unbound_input
= NULL
;
3794 DWORD size
, mode
, type
;
3801 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
!= NULL
, "ConsoleHandle is NULL\n");
3804 unbound_input
= create_unbound_handle(FALSE
, TRUE
);
3805 unbound_output
= create_unbound_handle(TRUE
, TRUE
);
3808 ret
= FreeConsole();
3809 ok(ret
, "FreeConsole failed: %u\n", GetLastError());
3811 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
== NULL
, "ConsoleHandle = %p\n",
3812 RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
);
3814 handle
= CreateFileA("CONOUT$", GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3815 ok(handle
== INVALID_HANDLE_VALUE
&&
3816 (GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_ACCESS_DENIED
/* winxp */)),
3817 "CreateFileA failed: %u\n", GetLastError());
3819 handle
= CreateFileA("CONIN$", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3820 ok(handle
== INVALID_HANDLE_VALUE
&&
3821 (GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_ACCESS_DENIED
/* winxp */)),
3822 "CreateFileA failed: %u\n", GetLastError());
3824 handle
= CreateFileA("CON", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3825 ok(handle
== INVALID_HANDLE_VALUE
&&
3826 (GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_ACCESS_DENIED
/* winxp */)),
3827 "CreateFileA failed: %u\n", GetLastError());
3829 handle
= CreateFileA("CON", GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3830 ok(handle
== INVALID_HANDLE_VALUE
&&
3831 (GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_FILE_NOT_FOUND
/* winxp */)),
3832 "CreateFileA failed: %u\n", GetLastError());
3834 handle
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
3835 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
3836 CONSOLE_TEXTMODE_BUFFER
, NULL
);
3837 ok(handle
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_INVALID_HANDLE
,
3838 "CreateConsoleScreenBuffer returned: %p (%u)\n", handle
, GetLastError());
3840 SetLastError(0xdeadbeef);
3841 cp
= GetConsoleCP();
3842 ok(!cp
, "cp = %x\n", cp
);
3843 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error %u\n", GetLastError());
3845 SetLastError(0xdeadbeef);
3846 cp
= GetConsoleOutputCP();
3847 ok(!cp
, "cp = %x\n", cp
);
3848 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error %u\n", GetLastError());
3850 SetLastError(0xdeadbeef);
3851 ret
= SetConsoleCP(GetOEMCP());
3852 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "SetConsoleCP returned %x(%u)\n", ret
, GetLastError());
3854 SetLastError(0xdeadbeef);
3855 ret
= SetConsoleOutputCP(GetOEMCP());
3856 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "SetConsoleCP returned %x(%u)\n", ret
, GetLastError());
3858 if (skip_nt
) return;
3860 SetLastError(0xdeadbeef);
3861 memset( title
, 0xc0, sizeof(title
) );
3862 size
= GetConsoleTitleW( title
, ARRAY_SIZE(title
) );
3863 ok(!size
, "GetConsoleTitleW returned %u\n", size
);
3864 ok(title
[0] == 0xc0c0, "title byffer changed\n");
3865 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error %u\n", GetLastError());
3867 SetLastError(0xdeadbeef);
3868 ret
= SetConsoleTitleW( L
"test" );
3869 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "SetConsoleTitleW returned %x(%u)\n", ret
, GetLastError());
3871 SetLastError(0xdeadbeef);
3872 hwnd
= GetConsoleWindow();
3873 ok(!hwnd
, "hwnd = %p\n", hwnd
);
3874 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error %u\n", GetLastError());
3876 ret
= GenerateConsoleCtrlEvent(CTRL_C_EVENT
, 0);
3877 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "GenerateConsoleCtrlEvent returned %x(%u)\n",
3878 ret
, GetLastError());
3880 SetStdHandle( STD_INPUT_HANDLE
, (HANDLE
)0xdeadbeef );
3881 handle
= GetConsoleInputWaitHandle();
3882 ok(handle
== (HANDLE
)0xdeadbeef, "GetConsoleInputWaitHandle returned %p\n", handle
);
3883 SetStdHandle( STD_INPUT_HANDLE
, NULL
);
3884 handle
= GetConsoleInputWaitHandle();
3885 ok(!handle
, "GetConsoleInputWaitHandle returned %p\n", handle
);
3887 ret
= ReadFile(unbound_input
, buf
, sizeof(buf
), &size
, NULL
);
3888 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3889 "ReadFile returned %x %u\n", ret
, GetLastError());
3891 ret
= FlushFileBuffers(unbound_input
);
3892 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3893 "ReadFile returned %x %u\n", ret
, GetLastError());
3895 ret
= WriteFile(unbound_input
, "test", 4, &size
, NULL
);
3896 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3897 "ReadFile returned %x %u\n", ret
, GetLastError());
3899 ret
= GetConsoleMode(unbound_input
, &mode
);
3900 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3901 "GetConsoleMode returned %x %u\n", ret
, GetLastError());
3902 ret
= GetConsoleMode(unbound_output
, &mode
);
3903 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3904 "GetConsoleMode returned %x %u\n", ret
, GetLastError());
3906 type
= GetFileType(unbound_input
);
3907 ok(type
== FILE_TYPE_CHAR
, "GetFileType returned %u\n", type
);
3908 type
= GetFileType(unbound_output
);
3909 ok(type
== FILE_TYPE_CHAR
, "GetFileType returned %u\n", type
);
3911 CloseHandle(unbound_input
);
3912 CloseHandle(unbound_output
);
3915 static void test_SetConsoleScreenBufferInfoEx(HANDLE std_output
)
3919 HANDLE std_input
= CreateFileA("CONIN$", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3920 BOOL (WINAPI
*pSetConsoleScreenBufferInfoEx
)(HANDLE
, CONSOLE_SCREEN_BUFFER_INFOEX
*);
3921 BOOL (WINAPI
*pGetConsoleScreenBufferInfoEx
)(HANDLE
, CONSOLE_SCREEN_BUFFER_INFOEX
*);
3922 CONSOLE_SCREEN_BUFFER_INFOEX info
;
3924 hmod
= GetModuleHandleA("kernel32.dll");
3925 pSetConsoleScreenBufferInfoEx
= (void *)GetProcAddress(hmod
, "SetConsoleScreenBufferInfoEx");
3926 pGetConsoleScreenBufferInfoEx
= (void *)GetProcAddress(hmod
, "GetConsoleScreenBufferInfoEx");
3927 if (!pSetConsoleScreenBufferInfoEx
|| !pGetConsoleScreenBufferInfoEx
)
3929 win_skip("SetConsoleScreenBufferInfoEx is not available\n");
3933 memset(&info
, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
));
3934 info
.cbSize
= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
);
3935 pGetConsoleScreenBufferInfoEx(std_output
, &info
);
3937 SetLastError(0xdeadbeef);
3938 ret
= pSetConsoleScreenBufferInfoEx(NULL
, &info
);
3939 ok(!ret
, "got %d, expected zero\n", ret
);
3940 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %u, expected 6\n", GetLastError());
3942 SetLastError(0xdeadbeef);
3943 ret
= pSetConsoleScreenBufferInfoEx(std_output
, &info
);
3944 ok(ret
, "got %d, expected one\n", ret
);
3945 ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3947 SetLastError(0xdeadbeef);
3948 ret
= pSetConsoleScreenBufferInfoEx(std_input
, &info
);
3949 ok(!ret
, "got %d, expected zero\n", ret
);
3950 ok(GetLastError() == ERROR_INVALID_HANDLE
|| GetLastError() == ERROR_ACCESS_DENIED
,
3951 "got %u, expected 5 or 6\n", GetLastError());
3954 SetLastError(0xdeadbeef);
3955 ret
= pSetConsoleScreenBufferInfoEx(std_output
, &info
);
3956 ok(!ret
, "got %d, expected zero\n", ret
);
3957 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %u, expected 87\n", GetLastError());
3959 CloseHandle(std_input
);
3962 static void test_console_title(void)
3967 ret
= SetConsoleTitleW(L
"test");
3968 ok(ret
, "SetConsoleTitleW failed: %u\n", GetLastError());
3970 ret
= GetConsoleTitleW(buf
, ARRAY_SIZE(buf
));
3971 ok(ret
, "GetConsoleTitleW failed: %u\n", GetLastError());
3972 ok(!wcscmp(buf
, L
"test"), "title = %s\n", wine_dbgstr_w(buf
));
3976 ret
= GetConsoleTitleW(buf
, 2);
3977 ok(ret
, "GetConsoleTitleW failed: %u\n", GetLastError());
3978 ok(!wcscmp(buf
, L
"t"), "title = %s\n", wine_dbgstr_w(buf
));
3980 ret
= GetConsoleTitleW(buf
, 4);
3981 ok(ret
, "GetConsoleTitleW failed: %u\n", GetLastError());
3982 ok(!wcscmp(buf
, L
"tes"), "title = %s\n", wine_dbgstr_w(buf
));
3986 static void test_file_info(HANDLE input
, HANDLE output
)
3988 FILE_STANDARD_INFORMATION std_info
;
3989 FILE_FS_DEVICE_INFORMATION fs_info
;
3996 if (skip_nt
) return;
3998 status
= NtQueryInformationFile(input
, &io
, &std_info
, sizeof(std_info
), FileStandardInformation
);
3999 ok(status
== STATUS_INVALID_DEVICE_REQUEST
, "NtQueryInformationFile returned: %#x\n", status
);
4001 status
= NtQueryInformationFile(output
, &io
, &std_info
, sizeof(std_info
), FileStandardInformation
);
4002 ok(status
== STATUS_INVALID_DEVICE_REQUEST
, "NtQueryInformationFile returned: %#x\n", status
);
4004 ret
= GetFileSizeEx(input
, &size
);
4005 ok(!ret
&& GetLastError() == ERROR_INVALID_FUNCTION
,
4006 "GetFileSizeEx returned %x(%u)\n", ret
, GetLastError());
4008 ret
= GetFileSizeEx(output
, &size
);
4009 ok(!ret
&& GetLastError() == ERROR_INVALID_FUNCTION
,
4010 "GetFileSizeEx returned %x(%u)\n", ret
, GetLastError());
4012 status
= NtQueryVolumeInformationFile(input
, &io
, &fs_info
, sizeof(fs_info
), FileFsDeviceInformation
);
4013 ok(!status
, "NtQueryVolumeInformationFile failed: %#x\n", status
);
4014 ok(fs_info
.DeviceType
== FILE_DEVICE_CONSOLE
, "DeviceType = %u\n", fs_info
.DeviceType
);
4015 ok(fs_info
.Characteristics
== FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
,
4016 "Characteristics = %x\n", fs_info
.Characteristics
);
4018 status
= NtQueryVolumeInformationFile(output
, &io
, &fs_info
, sizeof(fs_info
), FileFsDeviceInformation
);
4019 ok(!status
, "NtQueryVolumeInformationFile failed: %#x\n", status
);
4020 ok(fs_info
.DeviceType
== FILE_DEVICE_CONSOLE
, "DeviceType = %u\n", fs_info
.DeviceType
);
4021 ok(fs_info
.Characteristics
== FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
,
4022 "Characteristics = %x\n", fs_info
.Characteristics
);
4024 type
= GetFileType(input
);
4025 ok(type
== FILE_TYPE_CHAR
, "GetFileType returned %u\n", type
);
4026 type
= GetFileType(output
);
4027 ok(type
== FILE_TYPE_CHAR
, "GetFileType returned %u\n", type
);
4030 static void test_AttachConsole_child(DWORD console_pid
)
4032 HANDLE pipe_in
, pipe_out
;
4039 res
= CreatePipe(&pipe_in
, &pipe_out
, NULL
, 0);
4040 ok(res
, "CreatePipe failed: %u\n", GetLastError());
4042 res
= AttachConsole(console_pid
);
4043 ok(!res
&& GetLastError() == ERROR_ACCESS_DENIED
,
4044 "AttachConsole returned: %x(%u)\n", res
, GetLastError());
4046 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
!= NULL
, "ConsoleHandle is NULL\n");
4047 res
= FreeConsole();
4048 ok(res
, "FreeConsole failed: %u\n", GetLastError());
4049 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
== NULL
, "ConsoleHandle = %p\n",
4050 RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
);
4052 SetStdHandle(STD_ERROR_HANDLE
, pipe_out
);
4054 res
= AttachConsole(console_pid
);
4055 ok(res
, "AttachConsole failed: %u\n", GetLastError());
4057 ok(pipe_out
!= GetStdHandle(STD_ERROR_HANDLE
), "std handle not set to console\n");
4058 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
!= NULL
, "ConsoleHandle is NULL\n");
4060 console
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4061 ok(console
!= INVALID_HANDLE_VALUE
, "Could not open console\n");
4063 res
= ReadConsoleOutputCharacterA(console
, buf
, 6, c
, &len
);
4064 ok(res
, "ReadConsoleOutputCharacterA failed: %u\n", GetLastError());
4065 ok(len
== 6, "len = %u\n", len
);
4066 ok(!memcmp(buf
, "Parent", 6), "Unexpected console output\n");
4068 res
= FreeConsole();
4069 ok(res
, "FreeConsole failed: %u\n", GetLastError());
4071 SetStdHandle(STD_INPUT_HANDLE
, pipe_in
);
4072 SetStdHandle(STD_OUTPUT_HANDLE
, pipe_out
);
4074 res
= AttachConsole(ATTACH_PARENT_PROCESS
);
4075 ok(res
, "AttachConsole failed: %u\n", GetLastError());
4077 ok(pipe_in
!= GetStdHandle(STD_INPUT_HANDLE
), "std handle not set to console\n");
4078 ok(pipe_out
!= GetStdHandle(STD_OUTPUT_HANDLE
), "std handle not set to console\n");
4080 console
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4081 ok(console
!= INVALID_HANDLE_VALUE
, "Could not open console\n");
4083 res
= ReadConsoleOutputCharacterA(console
, buf
, 6, c
, &len
);
4084 ok(res
, "ReadConsoleOutputCharacterA failed: %u\n", GetLastError());
4085 ok(len
== 6, "len = %u\n", len
);
4086 ok(!memcmp(buf
, "Parent", 6), "Unexpected console output\n");
4088 simple_write_console(console
, "Child");
4089 CloseHandle(console
);
4091 res
= FreeConsole();
4092 ok(res
, "FreeConsole failed: %u\n", GetLastError());
4094 res
= CloseHandle(pipe_in
);
4095 ok(res
, "pipe_in is no longer valid\n");
4096 res
= CloseHandle(pipe_out
);
4097 ok(res
, "pipe_out is no longer valid\n");
4100 static void test_AttachConsole(HANDLE console
)
4102 STARTUPINFOA si
= { sizeof(si
) };
4103 PROCESS_INFORMATION info
;
4104 char **argv
, buf
[MAX_PATH
];
4109 simple_write_console(console
, "Parent console");
4111 winetest_get_mainargs(&argv
);
4112 sprintf(buf
, "\"%s\" console attach_console %x", argv
[0], GetCurrentProcessId());
4113 res
= CreateProcessA(NULL
, buf
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &info
);
4114 ok(res
, "CreateProcess failed: %u\n", GetLastError());
4115 CloseHandle(info
.hThread
);
4117 wait_child_process(info
.hProcess
);
4118 CloseHandle(info
.hProcess
);
4120 res
= ReadConsoleOutputCharacterA(console
, buf
, 5, c
, &len
);
4121 ok(res
, "ReadConsoleOutputCharacterA failed: %u\n", GetLastError());
4122 ok(len
== 5, "len = %u\n", len
);
4123 ok(!memcmp(buf
, "Child", 5), "Unexpected console output\n");
4126 static void test_AllocConsole_child(void)
4128 HANDLE unbound_output
;
4129 HANDLE prev_output
, prev_error
;
4134 GetStartupInfoW(&si
);
4136 prev_output
= GetStdHandle(STD_OUTPUT_HANDLE
);
4137 res
= DuplicateHandle(GetCurrentProcess(), prev_output
, GetCurrentProcess(), &unbound_output
,
4138 0, FALSE
, DUPLICATE_SAME_ACCESS
);
4139 ok(res
, "DuplicateHandle failed: %u\n", GetLastError());
4141 res
= GetConsoleMode(unbound_output
, &mode
);
4142 ok(res
, "GetConsoleMode failed: %u\n", GetLastError());
4144 prev_error
= GetStdHandle(STD_ERROR_HANDLE
);
4145 if (si
.dwFlags
& STARTF_USESTDHANDLES
)
4147 res
= GetConsoleMode(prev_error
, &mode
);
4148 ok(!res
&& GetLastError() == ERROR_INVALID_HANDLE
, "GetConsoleMode failed: %u\n", GetLastError());
4153 ok(GetStdHandle(STD_OUTPUT_HANDLE
) == prev_output
, "GetStdHandle(STD_OUTPUT_HANDLE) = %p\n", GetStdHandle(STD_OUTPUT_HANDLE
));
4154 ok(GetStdHandle(STD_ERROR_HANDLE
) == prev_error
, "GetStdHandle(STD_ERROR_HANDLE) = %p\n", GetStdHandle(STD_ERROR_HANDLE
));
4155 res
= GetConsoleMode(unbound_output
, &mode
);
4156 ok(!res
&& GetLastError() == ERROR_INVALID_HANDLE
, "GetConsoleMode failed: %u\n", GetLastError());
4158 res
= AllocConsole();
4159 ok(res
, "AllocConsole failed: %u\n", GetLastError());
4161 if (si
.dwFlags
& STARTF_USESTDHANDLES
)
4163 ok(GetStdHandle(STD_OUTPUT_HANDLE
) == prev_output
, "GetStdHandle(STD_OUTPUT_HANDLE) = %p\n", GetStdHandle(STD_OUTPUT_HANDLE
));
4164 ok(GetStdHandle(STD_ERROR_HANDLE
) == prev_error
, "GetStdHandle(STD_ERROR_HANDLE) = %p\n", GetStdHandle(STD_ERROR_HANDLE
));
4167 res
= GetConsoleMode(unbound_output
, &mode
);
4168 ok(res
, "GetConsoleMode failed: %u\n", GetLastError());
4171 SetStdHandle(STD_OUTPUT_HANDLE
, NULL
);
4172 SetStdHandle(STD_ERROR_HANDLE
, NULL
);
4173 res
= AllocConsole();
4174 ok(res
, "AllocConsole failed: %u\n", GetLastError());
4176 ok(GetStdHandle(STD_OUTPUT_HANDLE
) != NULL
, "GetStdHandle(STD_OUTPUT_HANDLE) = %p\n", GetStdHandle(STD_OUTPUT_HANDLE
));
4177 ok(GetStdHandle(STD_ERROR_HANDLE
) != NULL
, "GetStdHandle(STD_ERROR_HANDLE) = %p\n", GetStdHandle(STD_ERROR_HANDLE
));
4179 res
= GetConsoleMode(unbound_output
, &mode
);
4180 ok(res
, "GetConsoleMode failed: %u\n", GetLastError());
4181 res
= GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE
), &mode
);
4182 ok(res
, "GetConsoleMode failed: %u\n", GetLastError());
4183 res
= GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE
), &mode
);
4184 ok(res
, "GetConsoleMode failed: %u\n", GetLastError());
4186 res
= CloseHandle(unbound_output
);
4187 ok(res
, "CloseHandle failed: %u\n", GetLastError());
4190 static void test_AllocConsole(void)
4192 SECURITY_ATTRIBUTES inheritable_attr
= { sizeof(inheritable_attr
), NULL
, TRUE
};
4193 STARTUPINFOA si
= { sizeof(si
) };
4194 PROCESS_INFORMATION info
;
4195 char **argv
, buf
[MAX_PATH
];
4196 HANDLE pipe_read
, pipe_write
;
4199 if (skip_nt
) return;
4201 winetest_get_mainargs(&argv
);
4202 sprintf(buf
, "\"%s\" console alloc_console", argv
[0], GetCurrentProcessId());
4203 res
= CreateProcessA(NULL
, buf
, NULL
, NULL
, FALSE
, CREATE_NEW_CONSOLE
, NULL
, NULL
, &si
, &info
);
4204 ok(res
, "CreateProcess failed: %u\n", GetLastError());
4205 CloseHandle(info
.hThread
);
4206 wait_child_process(info
.hProcess
);
4207 CloseHandle(info
.hProcess
);
4209 res
= CreatePipe(&pipe_read
, &pipe_write
, &inheritable_attr
, 0);
4210 ok(res
, "CreatePipe failed: %u\n", GetLastError());
4212 si
.dwFlags
= STARTF_USESTDHANDLES
;
4213 si
.hStdError
= pipe_write
;
4214 res
= CreateProcessA(NULL
, buf
, NULL
, NULL
, TRUE
, CREATE_NEW_CONSOLE
, NULL
, NULL
, &si
, &info
);
4215 ok(res
, "CreateProcess failed: %u\n", GetLastError());
4216 CloseHandle(info
.hThread
);
4217 wait_child_process(info
.hProcess
);
4218 CloseHandle(info
.hProcess
);
4220 CloseHandle(pipe_read
);
4221 CloseHandle(pipe_write
);
4224 static void test_pseudo_console_child(HANDLE input
, HANDLE output
)
4226 CONSOLE_SCREEN_BUFFER_INFO sb_info
;
4227 CONSOLE_CURSOR_INFO cursor_info
;
4231 ret
= GetConsoleMode(input
, &mode
);
4232 ok(ret
, "GetConsoleMode failed: %u\n", GetLastError());
4233 ok(mode
== (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
|
4234 ENABLE_INSERT_MODE
| ENABLE_QUICK_EDIT_MODE
| ENABLE_EXTENDED_FLAGS
| ENABLE_AUTO_POSITION
),
4235 "mode = %x\n", mode
);
4237 ret
= SetConsoleMode(input
, mode
& ~ENABLE_AUTO_POSITION
);
4238 ok(ret
, "SetConsoleMode failed: %u\n", GetLastError());
4240 ret
= GetConsoleMode(input
, &mode
);
4241 ok(ret
, "GetConsoleMode failed: %u\n", GetLastError());
4242 ok(mode
== (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
|
4243 ENABLE_INSERT_MODE
| ENABLE_QUICK_EDIT_MODE
| ENABLE_EXTENDED_FLAGS
), "mode = %x\n", mode
);
4245 ret
= SetConsoleMode(input
, mode
| ENABLE_AUTO_POSITION
);
4246 ok(ret
, "SetConsoleMode failed: %u\n", GetLastError());
4248 ret
= GetConsoleMode(output
, &mode
);
4249 ok(ret
, "GetConsoleMode failed: %u\n", GetLastError());
4250 mode
&= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING
;
4251 ok(mode
== (ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
), "mode = %x\n", mode
);
4253 ret
= SetConsoleMode(output
, mode
& ~ENABLE_WRAP_AT_EOL_OUTPUT
);
4254 ok(ret
, "SetConsoleMode failed: %u\n", GetLastError());
4256 ret
= GetConsoleMode(output
, &mode
);
4257 ok(ret
, "GetConsoleMode failed: %u\n", GetLastError());
4258 ok(mode
== ENABLE_PROCESSED_OUTPUT
, "mode = %x\n", mode
);
4260 ret
= SetConsoleMode(output
, mode
| ENABLE_WRAP_AT_EOL_OUTPUT
);
4261 ok(ret
, "SetConsoleMode failed: %u\n", GetLastError());
4263 ret
= GetConsoleScreenBufferInfo(output
, &sb_info
);
4264 ok(ret
, "GetConsoleScreenBufferInfo failed: %u\n", GetLastError());
4265 ok(sb_info
.dwSize
.X
== 40, "dwSize.X = %u\n", sb_info
.dwSize
.X
);
4266 ok(sb_info
.dwSize
.Y
== 30, "dwSize.Y = %u\n", sb_info
.dwSize
.Y
);
4267 ok(sb_info
.dwCursorPosition
.X
== 0, "dwCursorPosition.X = %u\n", sb_info
.dwCursorPosition
.X
);
4268 ok(sb_info
.dwCursorPosition
.Y
== 0, "dwCursorPosition.Y = %u\n", sb_info
.dwCursorPosition
.Y
);
4269 ok(sb_info
.wAttributes
== 7, "wAttributes = %x\n", sb_info
.wAttributes
);
4270 ok(sb_info
.srWindow
.Left
== 0, "srWindow.Left = %u\n", sb_info
.srWindow
.Left
);
4271 ok(sb_info
.srWindow
.Top
== 0, "srWindow.Top = %u\n", sb_info
.srWindow
.Top
);
4272 ok(sb_info
.srWindow
.Right
== 39, "srWindow.Right = %u\n", sb_info
.srWindow
.Right
);
4273 ok(sb_info
.srWindow
.Bottom
== 29, "srWindow.Bottom = %u\n", sb_info
.srWindow
.Bottom
);
4274 ok(sb_info
.dwMaximumWindowSize
.X
== 40, "dwMaximumWindowSize.X = %u\n", sb_info
.dwMaximumWindowSize
.X
);
4275 ok(sb_info
.dwMaximumWindowSize
.Y
== 30, "dwMaximumWindowSize.Y = %u\n", sb_info
.dwMaximumWindowSize
.Y
);
4277 ret
= GetConsoleCursorInfo(output
, &cursor_info
);
4278 ok(ret
, "GetConsoleCursorInfo failed: %u\n", GetLastError());
4279 ok(cursor_info
.dwSize
== 25, "dwSize = %u\n", cursor_info
.dwSize
);
4280 ok(cursor_info
.bVisible
== TRUE
, "bVisible = %x\n", cursor_info
.bVisible
);
4282 test_console_title();
4283 test_WriteConsoleInputW(input
);
4286 static DWORD WINAPI
read_pipe_proc( void *handle
)
4290 while (ReadFile(handle
, buf
, sizeof(buf
), &size
, NULL
));
4291 ok(GetLastError() == ERROR_BROKEN_PIPE
, "ReadFile returned %u\n", GetLastError());
4292 CloseHandle(handle
);
4296 static void test_pseudo_console(void)
4298 STARTUPINFOEXA startup
= {{ sizeof(startup
) }};
4299 HANDLE console_pipe
, console_pipe2
, thread
;
4300 char **argv
, cmdline
[MAX_PATH
];
4301 PROCESS_INFORMATION info
;
4302 HPCON pseudo_console
;
4308 if (!pCreatePseudoConsole
)
4310 win_skip("CreatePseudoConsole not available\n");
4314 console_pipe
= CreateNamedPipeW(L
"\\\\.\\pipe\\pseudoconsoleconn", PIPE_ACCESS_DUPLEX
,
4315 PIPE_WAIT
| PIPE_TYPE_BYTE
, 1, 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
4316 ok(console_pipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipeW failed: %u\n", GetLastError());
4318 console_pipe2
= CreateFileW(L
"\\\\.\\pipe\\pseudoconsoleconn", GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
4319 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, NULL
);
4320 ok(console_pipe2
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
4322 thread
= CreateThread( NULL
, 0, read_pipe_proc
, console_pipe
, 0, NULL
);
4323 CloseHandle(thread
);
4327 hres
= pCreatePseudoConsole(size
, console_pipe2
, console_pipe2
, 0, &pseudo_console
);
4328 ok(hres
== E_INVALIDARG
, "CreatePseudoConsole failed: %08x\n", hres
);
4332 hres
= pCreatePseudoConsole(size
, console_pipe2
, console_pipe2
, 0, &pseudo_console
);
4333 ok(hres
== E_INVALIDARG
, "CreatePseudoConsole failed: %08x\n", hres
);
4337 hres
= pCreatePseudoConsole(size
, console_pipe2
, console_pipe2
, 0, &pseudo_console
);
4338 ok(hres
== S_OK
, "CreatePseudoConsole failed: %08x\n", hres
);
4339 CloseHandle(console_pipe2
);
4341 InitializeProcThreadAttributeList(NULL
, 1, 0, &attr_size
);
4342 startup
.lpAttributeList
= HeapAlloc(GetProcessHeap(), 0, attr_size
);
4343 InitializeProcThreadAttributeList(startup
.lpAttributeList
, 1, 0, &attr_size
);
4344 UpdateProcThreadAttribute(startup
.lpAttributeList
, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
, pseudo_console
,
4345 sizeof(pseudo_console
), NULL
, NULL
);
4347 winetest_get_mainargs(&argv
);
4348 sprintf(cmdline
, "\"%s\" %s --pseudo-console", argv
[0], argv
[1]);
4349 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, EXTENDED_STARTUPINFO_PRESENT
, NULL
, NULL
, &startup
.StartupInfo
, &info
);
4350 ok(ret
, "CreateProcessW failed: %u\n", GetLastError());
4352 CloseHandle(info
.hThread
);
4353 HeapFree(GetProcessHeap(), 0, startup
.lpAttributeList
);
4354 wait_child_process(info
.hProcess
);
4355 CloseHandle(info
.hProcess
);
4357 pClosePseudoConsole(pseudo_console
);
4362 HANDLE hConIn
, hConOut
, revert_output
= NULL
, unbound_output
;
4363 BOOL ret
, test_current
;
4364 CONSOLE_SCREEN_BUFFER_INFO sbi
;
4365 BOOL using_pseudo_console
;
4370 init_function_pointers();
4372 argc
= winetest_get_mainargs(&argv
);
4374 if (argc
> 3 && !strcmp(argv
[2], "attach_console"))
4377 sscanf(argv
[3], "%x", &parent_pid
);
4378 test_AttachConsole_child(parent_pid
);
4382 if (argc
== 3 && !strcmp(argv
[2], "alloc_console"))
4384 test_AllocConsole_child();
4388 test_current
= argc
>= 3 && !strcmp(argv
[2], "--current");
4389 using_pseudo_console
= argc
>= 3 && !strcmp(argv
[2], "--pseudo-console");
4391 if (!test_current
&& !using_pseudo_console
)
4393 static const char font_name
[] = "Lucida Console";
4395 char old_font
[LF_FACESIZE
];
4396 BOOL
delete = FALSE
;
4399 /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
4400 * correctly for characters that don't have a glyph in the console font. So,
4401 * we first set the console font to Lucida Console (which has a wider
4402 * selection of glyphs available than the default raster fonts). We want
4403 * to be able to restore the original font afterwards, so don't change
4404 * if we can't read the original font.
4406 err
= RegOpenKeyExA(HKEY_CURRENT_USER
, "Console", 0,
4407 KEY_QUERY_VALUE
| KEY_SET_VALUE
, &console_key
);
4408 if (err
== ERROR_SUCCESS
)
4410 size
= sizeof(old_font
);
4411 err
= RegQueryValueExA(console_key
, "FaceName", NULL
, NULL
,
4412 (LPBYTE
) old_font
, &size
);
4413 if (err
== ERROR_SUCCESS
|| err
== ERROR_FILE_NOT_FOUND
)
4415 delete = (err
== ERROR_FILE_NOT_FOUND
);
4416 err
= RegSetValueExA(console_key
, "FaceName", 0, REG_SZ
,
4417 (const BYTE
*) font_name
, sizeof(font_name
));
4418 if (err
!= ERROR_SUCCESS
)
4419 trace("Unable to change default console font, error %d\n", err
);
4423 trace("Unable to query default console font, error %d\n", err
);
4424 RegCloseKey(console_key
);
4430 trace("Unable to open HKCU\\Console, error %d\n", err
);
4434 /* Now detach and open a fresh console to play with */
4436 ok(AllocConsole(), "Couldn't alloc console\n");
4438 /* Restore default console font if needed */
4439 if (console_key
!= NULL
)
4442 err
= RegDeleteValueA(console_key
, "FaceName");
4444 err
= RegSetValueExA(console_key
, "FaceName", 0, REG_SZ
,
4445 (const BYTE
*) old_font
, strlen(old_font
) + 1);
4446 ok(err
== ERROR_SUCCESS
, "Unable to restore default console font, error %d\n", err
);
4450 unbound_output
= create_unbound_handle(TRUE
, FALSE
);
4451 if (!unbound_output
)
4453 win_skip("Skipping NT path tests, not supported on this Windows version\n");
4460 revert_output
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4461 sb
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
4462 CONSOLE_TEXTMODE_BUFFER
, NULL
);
4463 ok(sb
!= INVALID_HANDLE_VALUE
, "Could not allocate screen buffer: %u\n", GetLastError());
4464 SetConsoleActiveScreenBuffer(sb
);
4467 hConIn
= CreateFileA("CONIN$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4468 hConOut
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4470 /* now verify everything's ok */
4471 ok(hConIn
!= INVALID_HANDLE_VALUE
, "Opening ConIn\n");
4472 ok(hConOut
!= INVALID_HANDLE_VALUE
, "Opening ConOut\n");
4474 if (using_pseudo_console
)
4476 test_pseudo_console_child(hConIn
, hConOut
);
4480 ret
= GetConsoleScreenBufferInfo(hConOut
, &sbi
);
4481 ok(ret
, "Getting sb info\n");
4484 /* Reduce the size of the buffer to the visible area plus 3 lines to speed
4487 trace("Visible area: %dx%d - %dx%d Buffer size: %dx%d\n", sbi
.srWindow
.Left
, sbi
.srWindow
.Top
, sbi
.srWindow
.Right
, sbi
.srWindow
.Bottom
, sbi
.dwSize
.X
, sbi
.dwSize
.Y
);
4488 sbi
.dwSize
.Y
= size
= (sbi
.srWindow
.Bottom
+ 1) + 3;
4489 ret
= SetConsoleScreenBufferSize(hConOut
, sbi
.dwSize
);
4490 ok(ret
, "Setting sb info\n");
4491 ret
= GetConsoleScreenBufferInfo(hConOut
, &sbi
);
4492 ok(ret
, "Getting sb info\n");
4493 ok(sbi
.dwSize
.Y
== size
, "Unexpected buffer size: %d instead of %d\n", sbi
.dwSize
.Y
, size
);
4496 test_ReadConsole(hConIn
);
4497 /* Non interactive tests */
4498 testCursor(hConOut
, sbi
.dwSize
);
4499 /* test parameters (FIXME: test functionality) */
4500 testCursorInfo(hConOut
);
4501 /* will test wrapped (on/off) & processed (on/off) strings output */
4502 testWrite(hConOut
, sbi
.dwSize
);
4503 /* will test line scrolling at the bottom of the screen */
4504 /* testBottomScroll(); */
4505 /* will test all the scrolling operations */
4506 testScroll(hConOut
, sbi
.dwSize
);
4507 /* will test sb creation / modification / codepage handling */
4508 if (!test_current
) testScreenBuffer(hConOut
);
4509 /* Test waiting for a console handle */
4510 testWaitForConsoleInput(hConIn
);
4511 test_wait(hConIn
, hConOut
);
4515 /* clear duplicated console font table */
4516 CloseHandle(hConIn
);
4517 CloseHandle(hConOut
);
4519 ok(AllocConsole(), "Couldn't alloc console\n");
4520 hConIn
= CreateFileA("CONIN$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4521 hConOut
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4522 ok(hConIn
!= INVALID_HANDLE_VALUE
, "Opening ConIn\n");
4523 ok(hConOut
!= INVALID_HANDLE_VALUE
, "Opening ConOut\n");
4527 /* still to be done: access rights & access on objects */
4529 if (!pGetConsoleInputExeNameA
|| !pSetConsoleInputExeNameA
)
4530 win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
4532 test_GetSetConsoleInputExeName();
4534 if (!test_current
) test_GetConsoleProcessList();
4535 test_OpenConsoleW();
4538 test_VerifyConsoleIoHandle(hConOut
);
4539 test_GetSetStdHandle();
4540 test_DuplicateConsoleHandle();
4541 test_GetNumberOfConsoleInputEvents(hConIn
);
4542 test_WriteConsoleInputA(hConIn
);
4543 test_WriteConsoleInputW(hConIn
);
4544 test_FlushConsoleInputBuffer(hConIn
, hConOut
);
4545 test_WriteConsoleOutputCharacterA(hConOut
);
4546 test_WriteConsoleOutputCharacterW(hConOut
);
4547 test_WriteConsoleOutputAttribute(hConOut
);
4548 test_WriteConsoleOutput(hConOut
);
4549 test_FillConsoleOutputCharacterA(hConOut
);
4550 test_FillConsoleOutputCharacterW(hConOut
);
4551 test_FillConsoleOutputAttribute(hConOut
);
4552 test_ReadConsoleOutputCharacterA(hConOut
);
4553 test_ReadConsoleOutputCharacterW(hConOut
);
4554 test_ReadConsoleOutputAttribute(hConOut
);
4555 test_ReadConsoleOutput(hConOut
);
4558 test_GetCurrentConsoleFont(hConOut
);
4559 test_GetCurrentConsoleFontEx(hConOut
);
4560 test_GetConsoleFontSize(hConOut
);
4561 test_GetLargestConsoleWindowSize(hConOut
);
4562 test_GetConsoleFontInfo(hConOut
);
4563 test_SetConsoleFont(hConOut
);
4565 test_GetConsoleScreenBufferInfoEx(hConOut
);
4566 test_SetConsoleScreenBufferInfoEx(hConOut
);
4567 test_file_info(hConIn
, hConOut
);
4568 test_console_title();
4571 test_pseudo_console();
4572 test_AttachConsole(hConOut
);
4573 test_AllocConsole();
4576 else if (revert_output
) SetConsoleActiveScreenBuffer(revert_output
);
4578 CloseHandle(unbound_output
);