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: %#lx\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 /* dummy console ctrl handler to test reset of ctrl handler's list */
127 static BOOL WINAPI
mydummych(DWORD event
)
132 static void testCursor(HANDLE hCon
, COORD sbSize
)
137 ok(SetConsoleCursorPosition(0, c
) == 0, "No handle\n");
138 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %lu\n",
139 ERROR_INVALID_HANDLE
, GetLastError());
142 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
147 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in lower-right\n");
152 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
153 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %lu\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 %lu\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 %lu\n",
166 ERROR_INVALID_PARAMETER
, GetLastError());
170 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
171 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %lu\n",
172 ERROR_INVALID_PARAMETER
, GetLastError());
175 static void testCursorInfo(HANDLE hCon
)
178 CONSOLE_CURSOR_INFO info
;
181 SetLastError(0xdeadbeef);
182 ret
= GetConsoleCursorInfo(NULL
, NULL
);
183 ok(!ret
, "Expected failure\n");
184 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %lu\n",
185 ERROR_INVALID_HANDLE
, GetLastError());
187 SetLastError(0xdeadbeef);
189 ret
= GetConsoleCursorInfo(NULL
, &info
);
190 ok(!ret
, "Expected failure\n");
191 ok(info
.dwSize
== -1, "Expected no change for dwSize\n");
192 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %lu\n",
193 ERROR_INVALID_HANDLE
, GetLastError());
195 /* Test the correct call first to distinguish between win9x and the rest */
196 SetLastError(0xdeadbeef);
197 ret
= GetConsoleCursorInfo(hCon
, &info
);
198 ok(ret
, "Expected success\n");
199 ok(info
.dwSize
== 25 ||
200 info
.dwSize
== 12 /* win9x */,
201 "Expected 12 or 25, got %ld\n", info
.dwSize
);
202 ok(info
.bVisible
, "Expected the cursor to be visible\n");
203 ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %lu\n",
204 0xdeadbeef, GetLastError());
206 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
208 ret
= GetConsoleCursorInfo(pipe1
, &info
);
209 ok(!ret
, "Expected failure\n");
210 ok(info
.dwSize
== -1, "Expected no change for dwSize\n");
211 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: %lu\n", GetLastError());
215 /* Don't test NULL CONSOLE_CURSOR_INFO, it crashes on win9x and win7 */
218 static void testEmptyWrite(HANDLE hCon
)
220 static const char emptybuf
[16];
225 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
228 ok(WriteConsoleA(hCon
, NULL
, 0, &len
, NULL
) != 0 && len
== 0, "WriteConsole\n");
231 /* Passing a NULL lpBuffer with sufficiently large non-zero length succeeds
232 * on native Windows and result in memory-like contents being written to
233 * the console. Calling WriteConsoleW like this will crash on Wine. */
237 ok(!WriteConsoleA(hCon
, NULL
, 16, &len
, NULL
) && len
== -1, "WriteConsole\n");
240 /* Cursor advances for this call. */
242 ok(WriteConsoleA(hCon
, NULL
, 128, &len
, NULL
) != 0 && len
== 128, "WriteConsole\n");
246 ok(WriteConsoleA(hCon
, emptybuf
, 0, &len
, NULL
) != 0 && len
== 0, "WriteConsole\n");
249 /* WriteConsole does not halt on a null terminator and is happy to write
250 * memory contents beyond the actual size of the buffer. */
252 ok(WriteConsoleA(hCon
, emptybuf
, 16, &len
, NULL
) != 0 && len
== 16, "WriteConsole\n");
257 static void simple_write_console(HANDLE console
, const char *text
)
263 /* single line write */
265 ok(SetConsoleCursorPosition(console
, c
) != 0, "Cursor in upper-left\n");
267 ret
= WriteConsoleA(console
, text
, strlen(text
), &len
, NULL
);
268 ok(ret
, "WriteConsoleA failed: %lu\n", GetLastError());
269 ok(len
== strlen(text
), "unexpected len %lu\n", len
);
272 static void testWriteSimple(HANDLE hCon
)
274 const char* mytest
= "abcdefg";
275 int mylen
= strlen(mytest
);
280 simple_write_console(hCon
, mytest
);
282 for (c
.X
= 0; c
.X
< mylen
; c
.X
++)
284 okCHAR(hCon
, c
, mytest
[c
.X
], TEST_ATTRIB
);
288 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
290 ret
= WriteFile(hCon
, mytest
, mylen
, &len
, NULL
);
291 ok(ret
, "WriteFile failed: %lu\n", GetLastError());
292 ok(len
== mylen
, "unexpected len = %lu\n", len
);
294 for (c
.X
= 0; c
.X
< 2 * mylen
; c
.X
++)
296 okCHAR(hCon
, c
, mytest
[c
.X
% mylen
], TEST_ATTRIB
);
300 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
303 static void testWriteNotWrappedNotProcessed(HANDLE hCon
, COORD sbSize
)
307 const char* mytest
= "123";
308 const int mylen
= strlen(mytest
);
313 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, mode
& ~(ENABLE_PROCESSED_OUTPUT
|ENABLE_WRAP_AT_EOL_OUTPUT
)),
314 "clearing wrap at EOL & processed output\n");
316 /* write line, wrapping disabled, buffer exceeds sb width */
317 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
318 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
320 ret
= WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
);
321 ok(ret
!= 0 && len
== mylen
, "Couldn't write, ret = %d, len = %ld\n", ret
, len
);
323 for (p
= mylen
- 3; p
< mylen
; p
++)
325 c
.X
= sbSize
.X
- 3 + p
% 3;
326 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
330 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
332 p
= sbSize
.X
- 3 + mylen
% 3;
335 /* write line, wrapping disabled, strings end on end of line */
336 c
.X
= sbSize
.X
- mylen
; c
.Y
= 0;
337 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
339 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
341 /* test how control chars are handled. */
343 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
344 for (p
= 0; p
< 32; p
++) ctrl_buf
[p
] = (char)p
;
345 ok(WriteConsoleA(hCon
, ctrl_buf
, 32, &len
, NULL
) != 0 && len
== 32, "WriteConsole\n");
346 for (p
= 0; p
< 32; p
++)
349 okCHAR(hCon
, c
, (char)p
, TEST_ATTRIB
);
353 static void testWriteNotWrappedProcessed(HANDLE hCon
, COORD sbSize
)
357 const char* mytest
= "abcd\nf\tg";
358 const int mylen
= strlen(mytest
);
359 const int mylen2
= strchr(mytest
, '\n') - mytest
;
363 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, (mode
| ENABLE_PROCESSED_OUTPUT
) &
364 ~(ENABLE_WRAP_AT_EOL_OUTPUT
| ENABLE_VIRTUAL_TERMINAL_PROCESSING
)),
365 "clearing wrap at EOL & setting processed output\n");
367 /* write line, wrapping disabled, buffer exceeds sb width */
368 c
.X
= sbSize
.X
- 5; c
.Y
= 0;
369 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-5\n");
371 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
373 for (c
.X
= sbSize
.X
- 5; c
.X
< sbSize
.X
- 1; c
.X
++)
375 okCHAR(hCon
, c
, mytest
[c
.X
- sbSize
.X
+ 5], TEST_ATTRIB
);
378 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
379 /* Win9x and WinMe change the attribs for '\n' up to 'f' */
380 if (attr
== TEST_ATTRIB
)
382 win_skip("Win9x/WinMe don't respect ~ENABLE_WRAP_AT_EOL_OUTPUT\n");
386 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
389 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
390 for (c
.X
= 1; c
.X
< 8; c
.X
++)
391 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
392 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
394 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
398 /* write line, wrapping disabled, strings end on end of line */
399 c
.X
= sbSize
.X
- 4; c
.Y
= 0;
400 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-4\n");
402 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
404 for (c
.X
= sbSize
.X
- 4; c
.X
< sbSize
.X
; c
.X
++)
406 okCHAR(hCon
, c
, mytest
[c
.X
- sbSize
.X
+ 4], TEST_ATTRIB
);
409 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
410 for (c
.X
= 1; c
.X
< 8; c
.X
++)
411 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
412 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
414 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
418 /* write line, wrapping disabled, strings end after end of line */
419 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
420 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-4\n");
422 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
424 for (p
= mylen2
- 3; p
< mylen2
; p
++)
426 c
.X
= sbSize
.X
- 3 + p
% 3;
427 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
430 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
431 for (c
.X
= 1; c
.X
< 8; c
.X
++)
432 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
433 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
435 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
440 static void testWriteWrappedNotProcessed(HANDLE hCon
, COORD sbSize
)
444 const char* mytest
= "abcd\nf\tg";
445 const int mylen
= strlen(mytest
);
448 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
,(mode
| ENABLE_WRAP_AT_EOL_OUTPUT
) & ~(ENABLE_PROCESSED_OUTPUT
)),
449 "setting wrap at EOL & clearing processed output\n");
451 /* write line, wrapping enabled, buffer doesn't exceed sb width */
452 c
.X
= sbSize
.X
- 9; c
.Y
= 0;
453 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-9\n");
455 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
457 for (p
= 0; p
< mylen
; p
++)
459 c
.X
= sbSize
.X
- 9 + p
;
460 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
462 c
.X
= sbSize
.X
- 9 + mylen
;
463 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
465 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
467 /* write line, wrapping enabled, buffer does exceed sb width */
468 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
469 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
473 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
476 static void testWriteWrappedProcessed(HANDLE hCon
, COORD sbSize
)
480 const char* mytest
= "abcd\nf\tg";
481 const int mylen
= strlen(mytest
);
485 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, mode
| (ENABLE_WRAP_AT_EOL_OUTPUT
|ENABLE_PROCESSED_OUTPUT
)),
486 "setting wrap at EOL & processed output\n");
488 /* write line, wrapping enabled, buffer doesn't exceed sb width */
489 c
.X
= sbSize
.X
- 9; c
.Y
= 0;
490 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-9\n");
492 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
493 for (p
= 0; p
< 4; p
++)
495 c
.X
= sbSize
.X
- 9 + p
;
496 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
498 c
.X
= sbSize
.X
- 9 + p
;
499 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
500 if (attr
== TEST_ATTRIB
)
501 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n");
503 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
505 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
506 for (c
.X
= 1; c
.X
< 8; c
.X
++)
507 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
508 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
510 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
513 /* write line, wrapping enabled, buffer does exceed sb width */
514 c
.X
= sbSize
.X
- 3; c
.Y
= 2;
515 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
517 ok(WriteConsoleA(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
518 for (p
= 0; p
< 3; p
++)
520 c
.X
= sbSize
.X
- 3 + p
;
521 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
524 okCHAR(hCon
, c
, mytest
[3], TEST_ATTRIB
);
526 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
527 if (attr
== TEST_ATTRIB
)
528 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n");
530 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
533 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
534 for (c
.X
= 1; c
.X
< 8; c
.X
++)
535 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
536 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
538 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
542 static void testWrite(HANDLE hCon
, COORD sbSize
)
544 /* FIXME: should in fact ensure that the sb is at least 10 characters wide */
545 ok(SetConsoleTextAttribute(hCon
, TEST_ATTRIB
), "Setting default text color\n");
546 resetContent(hCon
, sbSize
, FALSE
);
547 testEmptyWrite(hCon
);
548 resetContent(hCon
, sbSize
, FALSE
);
549 testWriteSimple(hCon
);
550 resetContent(hCon
, sbSize
, FALSE
);
551 testWriteNotWrappedNotProcessed(hCon
, sbSize
);
552 resetContent(hCon
, sbSize
, FALSE
);
553 testWriteNotWrappedProcessed(hCon
, sbSize
);
554 resetContent(hCon
, sbSize
, FALSE
);
555 testWriteWrappedNotProcessed(hCon
, sbSize
);
556 resetContent(hCon
, sbSize
, FALSE
);
557 testWriteWrappedProcessed(hCon
, sbSize
);
560 static void testScroll(HANDLE hCon
, COORD sbSize
)
562 SMALL_RECT scroll
, clip
;
570 #define IN_SRECT(r,c) ((r).Left <= (c).X && (c).X <= (r).Right && (r).Top <= (c).Y && (c).Y <= (r).Bottom)
571 #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)
573 /* no clipping, src & dst rect don't overlap */
574 resetContent(hCon
, sbSize
, TRUE
);
577 scroll
.Right
= W
- 1;
579 scroll
.Bottom
= H
- 1;
582 ci
.Char
.UnicodeChar
= '#';
583 ci
.Attributes
= TEST_ATTRIB
;
586 clip
.Right
= sbSize
.X
- 1;
588 clip
.Bottom
= sbSize
.Y
- 1;
590 ok(ScrollConsoleScreenBufferA(hCon
, &scroll
, NULL
, dst
, &ci
), "Scrolling SB\n");
592 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
594 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
596 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
600 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
602 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
603 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
604 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
608 /* no clipping, src & dst rect do overlap */
609 resetContent(hCon
, sbSize
, TRUE
);
612 scroll
.Right
= W
- 1;
614 scroll
.Bottom
= H
- 1;
617 ci
.Char
.UnicodeChar
= '#';
618 ci
.Attributes
= TEST_ATTRIB
;
621 clip
.Right
= sbSize
.X
- 1;
623 clip
.Bottom
= sbSize
.Y
- 1;
625 ok(ScrollConsoleScreenBufferA(hCon
, &scroll
, NULL
, dst
, &ci
), "Scrolling SB\n");
627 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
629 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
631 if (dst
.X
<= c
.X
&& c
.X
< dst
.X
+ W
&& dst
.Y
<= c
.Y
&& c
.Y
< dst
.Y
+ H
)
635 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
637 else if (c
.X
< W
&& c
.Y
< H
) okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
638 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
642 /* clipping, src & dst rect don't overlap */
643 resetContent(hCon
, sbSize
, TRUE
);
646 scroll
.Right
= W
- 1;
648 scroll
.Bottom
= H
- 1;
651 ci
.Char
.UnicodeChar
= '#';
652 ci
.Attributes
= TEST_ATTRIB
;
655 clip
.Right
= min(W
+ W
/ 2, sbSize
.X
- 1);
657 clip
.Bottom
= min(H
+ H
/ 2, sbSize
.Y
- 1);
659 SetLastError(0xdeadbeef);
660 ret
= ScrollConsoleScreenBufferA(hCon
, &scroll
, &clip
, dst
, &ci
);
663 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
665 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
667 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
671 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
673 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
674 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
675 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
681 /* Win9x will fail, Only accept ERROR_NOT_ENOUGH_MEMORY */
682 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
,
683 "Expected ERROR_NOT_ENOUGH_MEMORY, got %lu\n", GetLastError());
686 /* no clipping, src & dst rect do overlap */
688 scroll
.Right
= W
- 1;
690 scroll
.Bottom
= H
- 1;
693 ci
.Char
.UnicodeChar
= '#';
694 ci
.Attributes
= TEST_ATTRIB
;
696 ret
= ScrollConsoleScreenBufferA(hCon
, &scroll
, NULL
, dst
, &ci
);
697 ok(ret
, "ScrollConsoleScreenBufferA failed: %lu\n", GetLastError());
698 /* no win10 1909 error here, only check the result of the clipped case */
700 /* clipping, src & dst rect do overlap */
701 resetContent(hCon
, sbSize
, TRUE
);
704 scroll
.Right
= W
- 1;
706 scroll
.Bottom
= H
- 1;
709 ci
.Char
.UnicodeChar
= '#';
710 ci
.Attributes
= TEST_ATTRIB
;
713 clip
.Right
= min(W
+ W
/ 2, sbSize
.X
- 1);
715 clip
.Bottom
= min(H
+ H
/ 2, sbSize
.Y
- 1);
717 /* Windows 10 1909 fails if the destination is not in the clip rect
718 * but the result is still ok!
720 SetLastError(0xdeadbeef);
721 ret
= ScrollConsoleScreenBufferA(hCon
, &scroll
, &clip
, dst
, &ci
);
722 ok((ret
&& GetLastError() == 0xdeadbeef) ||
723 broken(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
),
724 "ScrollConsoleScreenBufferA failed: %lu\n", GetLastError());
726 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
728 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
730 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
734 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
736 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
737 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
738 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
743 static int mch_count
;
744 /* we need the event as Wine console event generation isn't synchronous
745 * (ie GenerateConsoleCtrlEvent returns before all ctrl-handlers in all
746 * processes have been called).
748 static HANDLE mch_event
;
749 static BOOL WINAPI
mch(DWORD event
)
756 static void testCtrlHandler(void)
758 ok(!SetConsoleCtrlHandler(mch
, FALSE
), "Shouldn't succeed\n");
759 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Bad error %lu\n", GetLastError());
760 ok(SetConsoleCtrlHandler(mch
, TRUE
), "Couldn't set handler\n");
761 /* wine requires the event for the test, as we cannot ensure, so far, that
762 * events are processed synchronously in GenerateConsoleCtrlEvent()
764 mch_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
766 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT
, 0), "Couldn't send ctrl-c event\n");
767 /* FIXME: it isn't synchronous on wine but it can still happen before we test */
768 if (0) ok(mch_count
== 1, "Event isn't synchronous\n");
769 ok(WaitForSingleObject(mch_event
, 3000) == WAIT_OBJECT_0
, "event sending didn't work\n");
770 CloseHandle(mch_event
);
772 ok(SetConsoleCtrlHandler(NULL
, FALSE
), "Couldn't turn on ctrl-c handling\n");
773 ok((RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
& 1) == 0,
774 "Unexpect ConsoleFlags value %lx\n", RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
);
776 /* Turning off ctrl-c handling doesn't work on win9x such way ... */
777 ok(SetConsoleCtrlHandler(NULL
, TRUE
), "Couldn't turn off ctrl-c handling\n");
778 ok((RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
& 1) != 0,
779 "Unexpect ConsoleFlags value %lx\n", RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
);
780 mch_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
782 if(!(GetVersion() & 0x80000000))
783 /* ... and next line leads to an unhandled exception on 9x. Avoid it on 9x. */
784 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT
, 0), "Couldn't send ctrl-c event\n");
785 ok(WaitForSingleObject(mch_event
, 3000) == WAIT_TIMEOUT
&& mch_count
== 0, "Event shouldn't have been sent\n");
786 CloseHandle(mch_event
);
787 ok(SetConsoleCtrlHandler(mch
, FALSE
), "Couldn't remove handler\n");
788 ok(!SetConsoleCtrlHandler(mch
, FALSE
), "Shouldn't succeed\n");
789 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Bad error %lu\n", GetLastError());
793 * Test console screen buffer:
794 * 1) Try to set invalid handle.
795 * 2) Try to set non-console handles.
796 * 3) Use CONOUT$ file as active SB.
798 * 5) Test output codepage to show it is not a property of SB.
799 * 6) Test switching to old SB if we close all handles to current SB - works
800 * in Windows, TODO in wine.
802 * What is not tested but should be:
803 * 1) ScreenBufferInfo
805 static void testScreenBuffer(HANDLE hConOut
)
807 HANDLE hConOutRW
, hConOutRO
, hConOutWT
;
808 HANDLE hFileOutRW
, hFileOutRO
, hFileOutWT
;
810 char test_str1
[] = "Test for SB1";
811 char test_str2
[] = "Test for SB2";
812 char test_cp866
[] = {0xe2, 0xa5, 0xe1, 0xe2, 0};
813 char test_cp1251
[] = {0xf2, 0xe5, 0xf1, 0xf2, 0};
814 WCHAR test_unicode
[] = {0x0442, 0x0435, 0x0441, 0x0442, 0};
822 if (!IsValidCodePage(866))
824 skip("Codepage 866 not available\n");
828 /* In the beginning set output codepage to 866 */
829 oldcp
= GetConsoleOutputCP();
830 SetLastError(0xdeadbeef);
831 ret
= SetConsoleOutputCP(866);
832 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
834 win_skip("SetConsoleOutputCP is not implemented\n");
837 ok(ret
, "Cannot set output codepage to 866\n");
839 hConOutRW
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
840 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
841 CONSOLE_TEXTMODE_BUFFER
, NULL
);
842 ok(hConOutRW
!= INVALID_HANDLE_VALUE
,
843 "Cannot create a new screen buffer for ReadWrite\n");
844 hConOutRO
= CreateConsoleScreenBuffer(GENERIC_READ
,
845 FILE_SHARE_READ
, NULL
,
846 CONSOLE_TEXTMODE_BUFFER
, NULL
);
847 ok(hConOutRO
!= INVALID_HANDLE_VALUE
,
848 "Cannot create a new screen buffer for ReadOnly\n");
849 hConOutWT
= CreateConsoleScreenBuffer(GENERIC_WRITE
,
850 FILE_SHARE_WRITE
, NULL
,
851 CONSOLE_TEXTMODE_BUFFER
, NULL
);
852 ok(hConOutWT
!= INVALID_HANDLE_VALUE
,
853 "Cannot create a new screen buffer for WriteOnly\n");
855 hFileOutRW
= CreateFileA("NUL", GENERIC_READ
| GENERIC_WRITE
,
856 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
857 OPEN_EXISTING
, 0, NULL
);
858 ok(hFileOutRW
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for ReadWrite\n");
859 hFileOutRO
= CreateFileA("NUL", GENERIC_READ
, FILE_SHARE_READ
,
860 NULL
, OPEN_EXISTING
, 0, NULL
);
861 ok(hFileOutRO
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for ReadOnly\n");
862 hFileOutWT
= CreateFileA("NUL", GENERIC_WRITE
, FILE_SHARE_WRITE
,
863 NULL
, OPEN_EXISTING
, 0, NULL
);
864 ok(hFileOutWT
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for WriteOnly\n");
866 /* Trying to set invalid handle */
868 ok(!SetConsoleActiveScreenBuffer(INVALID_HANDLE_VALUE
),
869 "Shouldn't succeed\n");
870 ok(GetLastError() == ERROR_INVALID_HANDLE
,
871 "GetLastError: expecting %u got %lu\n",
872 ERROR_INVALID_HANDLE
, GetLastError());
874 /* Trying to set non-console handles */
876 ok(!SetConsoleActiveScreenBuffer(hFileOutRW
), "Shouldn't succeed\n");
877 ok(GetLastError() == ERROR_INVALID_HANDLE
,
878 "GetLastError: expecting %u got %lu\n",
879 ERROR_INVALID_HANDLE
, GetLastError());
882 ok(!SetConsoleActiveScreenBuffer(hFileOutRO
), "Shouldn't succeed\n");
883 ok(GetLastError() == ERROR_INVALID_HANDLE
,
884 "GetLastError: expecting %u got %lu\n",
885 ERROR_INVALID_HANDLE
, GetLastError());
888 ok(!SetConsoleActiveScreenBuffer(hFileOutWT
), "Shouldn't succeed\n");
889 ok(GetLastError() == ERROR_INVALID_HANDLE
,
890 "GetLastError: expecting %u got %lu\n",
891 ERROR_INVALID_HANDLE
, GetLastError());
893 /* trying to write non-console handle */
894 SetLastError(0xdeadbeef);
895 ret
= WriteConsoleA(hFileOutRW
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
896 error
= GetLastError();
897 ok(!ret
, "Shouldn't succeed\n");
898 ok(error
== ERROR_INVALID_HANDLE
|| error
== ERROR_INVALID_FUNCTION
,
899 "GetLastError: got %lu\n", error
);
901 SetLastError(0xdeadbeef);
902 ret
= WriteConsoleA(hFileOutRO
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
903 error
= GetLastError();
904 ok(!ret
, "Shouldn't succeed\n");
905 ok(error
== ERROR_INVALID_HANDLE
|| error
== ERROR_INVALID_FUNCTION
,
906 "GetLastError: got %lu\n", error
);
908 SetLastError(0xdeadbeef);
909 ret
= WriteConsoleA(hFileOutWT
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
910 error
= GetLastError();
911 ok(!ret
, "Shouldn't succeed\n");
912 ok(error
== ERROR_INVALID_HANDLE
|| error
== ERROR_INVALID_FUNCTION
,
913 "GetLastError: got %lu\n", error
);
915 CloseHandle(hFileOutRW
);
916 CloseHandle(hFileOutRO
);
917 CloseHandle(hFileOutWT
);
919 /* Trying to set SB handles with various access modes */
921 ok(!SetConsoleActiveScreenBuffer(hConOutRO
), "Shouldn't succeed\n");
922 ok(GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_ACCESS_DENIED
) /* win10 1809 */,
923 "unexpected last error %lu\n", GetLastError());
925 ok(SetConsoleActiveScreenBuffer(hConOutWT
), "Couldn't set new WriteOnly SB\n");
927 ok(SetConsoleActiveScreenBuffer(hConOutRW
), "Couldn't set new ReadWrite SB\n");
929 CloseHandle(hConOutWT
);
930 CloseHandle(hConOutRO
);
932 /* Now we have two ReadWrite SB, active must be hConOutRW */
933 /* Open current SB via CONOUT$ */
934 hConOutNew
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0,
935 NULL
, OPEN_EXISTING
, 0, 0);
936 ok(hConOutNew
!= INVALID_HANDLE_VALUE
, "CONOUT$ is not opened\n");
941 SetConsoleCursorPosition(hConOut
, c
);
943 SetConsoleCursorPosition(hConOutRW
, c
);
944 okCURSOR(hConOutNew
, c
);
946 okCURSOR(hConOut
, c
);
951 /* Write using hConOutNew... */
952 SetConsoleCursorPosition(hConOutNew
, c
);
953 ret
= WriteConsoleA(hConOutNew
, test_str2
, lstrlenA(test_str2
), &len
, NULL
);
954 ok (ret
&& len
== lstrlenA(test_str2
), "WriteConsoleA failed\n");
955 /* ... and read it back via hConOutRW */
956 ret
= ReadConsoleOutputCharacterA(hConOutRW
, str_buf
, lstrlenA(test_str2
), c
, &len
);
957 ok(ret
&& len
== lstrlenA(test_str2
), "ReadConsoleOutputCharacterA failed\n");
958 str_buf
[lstrlenA(test_str2
)] = 0;
959 ok(!lstrcmpA(str_buf
, test_str2
), "got '%s' expected '%s'\n", str_buf
, test_str2
);
962 /* Now test output codepage handling. Current is 866 as we set earlier. */
963 SetConsoleCursorPosition(hConOutRW
, c
);
964 ret
= WriteConsoleA(hConOutRW
, test_cp866
, lstrlenA(test_cp866
), &len
, NULL
);
965 ok(ret
&& len
== lstrlenA(test_cp866
), "WriteConsoleA failed\n");
966 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenW(test_unicode
), c
, &len
);
967 /* Work around some broken results under Windows with some locale (ja, cn, ko...)
968 * Looks like a real bug in Win10 (at least).
970 if (ret
&& broken(len
== lstrlenW(test_unicode
) / sizeof(WCHAR
)))
971 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenW(test_unicode
) * sizeof(WCHAR
), c
, &len
);
972 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
973 ok(len
== lstrlenW(test_unicode
), "unexpected len %lu %u\n", len
, lstrlenW(test_unicode
));
974 ok(!memcmp(str_wbuf
, test_unicode
, lstrlenW(test_unicode
) * sizeof(WCHAR
)),
975 "string does not match the pattern\n");
978 * cp866 is OK, let's switch to cp1251.
979 * We expect that this codepage will be used in every SB - active and not.
981 ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n");
982 SetConsoleCursorPosition(hConOutRW
, c
);
983 ret
= WriteConsoleA(hConOutRW
, test_cp1251
, lstrlenA(test_cp1251
), &len
, NULL
);
984 ok(ret
&& len
== lstrlenA(test_cp1251
), "WriteConsoleA failed\n");
985 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenA(test_cp1251
), c
, &len
);
986 ok(ret
&& len
== lstrlenA(test_cp1251
), "ReadConsoleOutputCharacterW failed\n");
987 str_wbuf
[lstrlenA(test_cp1251
)] = 0;
988 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
990 /* Check what has happened to hConOut. */
991 SetConsoleCursorPosition(hConOut
, c
);
992 ret
= WriteConsoleA(hConOut
, test_cp1251
, lstrlenA(test_cp1251
), &len
, NULL
);
993 ok(ret
&& len
== lstrlenA(test_cp1251
), "WriteConsoleA failed\n");
994 ret
= ReadConsoleOutputCharacterW(hConOut
, str_wbuf
, lstrlenA(test_cp1251
), c
, &len
);
995 ok(ret
&& len
== lstrlenA(test_cp1251
), "ReadConsoleOutputCharacterW failed\n");
996 str_wbuf
[lstrlenA(test_cp1251
)] = 0;
997 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
999 /* Close all handles of current console SB */
1000 CloseHandle(hConOutNew
);
1001 CloseHandle(hConOutRW
);
1003 /* Now active SB should be hConOut */
1004 hConOutNew
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0,
1005 NULL
, OPEN_EXISTING
, 0, 0);
1006 ok(hConOutNew
!= INVALID_HANDLE_VALUE
, "CONOUT$ is not opened\n");
1008 /* Write using hConOutNew... */
1009 SetConsoleCursorPosition(hConOutNew
, c
);
1010 ret
= WriteConsoleA(hConOutNew
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
1011 ok (ret
&& len
== lstrlenA(test_str1
), "WriteConsoleA failed\n");
1012 /* ... and read it back via hConOut */
1013 ret
= ReadConsoleOutputCharacterA(hConOut
, str_buf
, lstrlenA(test_str1
), c
, &len
);
1014 ok(ret
&& len
== lstrlenA(test_str1
), "ReadConsoleOutputCharacterA failed\n");
1015 str_buf
[lstrlenA(test_str1
)] = 0;
1016 todo_wine
ok(!lstrcmpA(str_buf
, test_str1
), "got '%s' expected '%s'\n", str_buf
, test_str1
);
1017 CloseHandle(hConOutNew
);
1019 /* This is not really needed under Windows */
1020 SetConsoleActiveScreenBuffer(hConOut
);
1022 /* restore codepage */
1023 SetConsoleOutputCP(oldcp
);
1026 static void test_new_screen_buffer_properties(HANDLE hConOut
)
1030 CONSOLE_FONT_INFOEX cfi
, cfi2
;
1031 CONSOLE_SCREEN_BUFFER_INFO csbi
, csbi2
;
1033 /* Font information */
1034 cfi
.cbSize
= cfi2
.cbSize
= sizeof(CONSOLE_FONT_INFOEX
);
1036 ret
= GetCurrentConsoleFontEx(hConOut
, FALSE
, &cfi
);
1037 ok(ret
, "GetCurrentConsoleFontEx failed: error %lu\n", GetLastError());
1039 hConOut2
= CreateConsoleScreenBuffer(GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
1040 CONSOLE_TEXTMODE_BUFFER
, NULL
);
1041 ok(hConOut2
!= INVALID_HANDLE_VALUE
, "CreateConsoleScreenBuffer failed: error %lu\n", GetLastError());
1043 ret
= GetCurrentConsoleFontEx(hConOut2
, FALSE
, &cfi2
);
1044 ok(ret
, "GetCurrentConsoleFontEx failed: error %lu\n", GetLastError());
1045 CloseHandle(hConOut2
);
1047 ok(cfi2
.nFont
== cfi
.nFont
, "Font index should match: "
1048 "got %lu, expected %lu\n", cfi2
.nFont
, cfi
.nFont
);
1049 ok(cfi2
.dwFontSize
.X
== cfi
.dwFontSize
.X
, "Font width should match: "
1050 "got %d, expected %d\n", cfi2
.dwFontSize
.X
, cfi
.dwFontSize
.X
);
1051 ok(cfi2
.dwFontSize
.Y
== cfi
.dwFontSize
.Y
, "Font height should match: "
1052 "got %d, expected %d\n", cfi2
.dwFontSize
.Y
, cfi
.dwFontSize
.Y
);
1053 ok(cfi2
.FontFamily
== cfi
.FontFamily
, "Font family should match: "
1054 "got %u, expected %u\n", cfi2
.FontFamily
, cfi
.FontFamily
);
1055 ok(cfi2
.FontWeight
== cfi
.FontWeight
, "Font weight should match: "
1056 "got %u, expected %u\n", cfi2
.FontWeight
, cfi
.FontWeight
);
1057 ok(!lstrcmpW(cfi2
.FaceName
, cfi
.FaceName
), "Font name should match: "
1058 "got %s, expected %s\n", wine_dbgstr_w(cfi2
.FaceName
), wine_dbgstr_w(cfi
.FaceName
));
1060 /* Display window size */
1061 ret
= GetConsoleScreenBufferInfo(hConOut
, &csbi
);
1062 ok(ret
, "GetConsoleScreenBufferInfo failed: error %lu\n", GetLastError());
1064 hConOut2
= CreateConsoleScreenBuffer(GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
1065 CONSOLE_TEXTMODE_BUFFER
, NULL
);
1066 ok(hConOut2
!= INVALID_HANDLE_VALUE
, "CreateConsoleScreenBuffer failed: error %lu\n", GetLastError());
1068 ret
= GetConsoleScreenBufferInfo(hConOut2
, &csbi2
);
1069 ok(ret
, "GetConsoleScreenBufferInfo failed: error %lu\n", GetLastError());
1070 CloseHandle(hConOut2
);
1072 ok(csbi2
.srWindow
.Left
== csbi
.srWindow
.Left
, "Left coordinate should match\n");
1073 ok(csbi2
.srWindow
.Top
== csbi
.srWindow
.Top
, "Top coordinate should match\n");
1074 ok(csbi2
.srWindow
.Right
== csbi
.srWindow
.Right
, "Right coordinate should match\n");
1075 ok(csbi2
.srWindow
.Bottom
== csbi
.srWindow
.Bottom
, "Bottom coordinate should match\n");
1078 static void test_new_screen_buffer_color_attributes(HANDLE hConOut
)
1080 CONSOLE_SCREEN_BUFFER_INFOEX csbi
, csbi2
;
1083 WORD orig_attr
, orig_popup
, attr
;
1085 csbi
.cbSize
= csbi2
.cbSize
= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
);
1087 ret
= GetConsoleScreenBufferInfoEx(hConOut
, &csbi
);
1088 ok(ret
, "GetConsoleScreenBufferInfoEx failed: error %lu\n", GetLastError());
1089 orig_attr
= csbi
.wAttributes
;
1090 orig_popup
= csbi
.wPopupAttributes
;
1092 hConOut2
= CreateConsoleScreenBuffer(GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
1093 CONSOLE_TEXTMODE_BUFFER
, NULL
);
1094 ok(hConOut2
!= INVALID_HANDLE_VALUE
, "CreateConsoleScreenBuffer failed: error %lu\n", GetLastError());
1096 ret
= GetConsoleScreenBufferInfoEx(hConOut2
, &csbi2
);
1097 ok(ret
, "GetConsoleScreenBufferInfoEx failed: error %lu\n", GetLastError());
1098 CloseHandle(hConOut2
);
1100 ok(csbi2
.wAttributes
== orig_attr
, "Character Attributes should have been copied: "
1101 "got %#x, expected %#x\n", csbi2
.wAttributes
, orig_attr
);
1102 ok(csbi2
.wPopupAttributes
!= orig_popup
, "Popup Attributes should not match original value\n");
1103 ok(csbi2
.wPopupAttributes
== orig_attr
, "Popup Attributes should match Character Attributes\n");
1105 /* Test different Character Attributes */
1106 attr
= FOREGROUND_BLUE
|BACKGROUND_GREEN
;
1107 ret
= SetConsoleTextAttribute(hConOut
, attr
);
1108 ok(ret
, "SetConsoleTextAttribute failed: error %lu\n", GetLastError());
1110 hConOut2
= CreateConsoleScreenBuffer(GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
1111 CONSOLE_TEXTMODE_BUFFER
, NULL
);
1112 ok(hConOut2
!= INVALID_HANDLE_VALUE
, "CreateConsoleScreenBuffer failed: error %lu\n", GetLastError());
1114 memset(&csbi2
, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
));
1115 csbi2
.cbSize
= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
);
1117 ret
= GetConsoleScreenBufferInfoEx(hConOut2
, &csbi2
);
1118 ok(ret
, "GetConsoleScreenBufferInfoEx failed: error %lu\n", GetLastError());
1119 CloseHandle(hConOut2
);
1121 ok(csbi2
.wAttributes
== attr
, "Character Attributes should have been copied: "
1122 "got %#x, expected %#x\n", csbi2
.wAttributes
, attr
);
1123 ok(csbi2
.wPopupAttributes
!= orig_popup
, "Popup Attributes should not match original value\n");
1124 ok(csbi2
.wPopupAttributes
== attr
, "Popup Attributes should match Character Attributes\n");
1126 ret
= SetConsoleTextAttribute(hConOut
, orig_attr
);
1127 ok(ret
, "SetConsoleTextAttribute failed: error %lu\n", GetLastError());
1129 /* Test inheritance of different Popup Attributes */
1130 csbi
.wPopupAttributes
= attr
;
1131 ret
= SetConsoleScreenBufferInfoEx(hConOut
, &csbi
);
1132 ok(ret
, "SetConsoleScreenBufferInfoEx failed: error %lu\n", GetLastError());
1134 hConOut2
= CreateConsoleScreenBuffer(GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
1135 CONSOLE_TEXTMODE_BUFFER
, NULL
);
1136 ok(hConOut2
!= INVALID_HANDLE_VALUE
, "CreateConsoleScreenBuffer failed: error %lu\n", GetLastError());
1138 memset(&csbi2
, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
));
1139 csbi2
.cbSize
= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
);
1141 ret
= GetConsoleScreenBufferInfoEx(hConOut2
, &csbi2
);
1142 ok(ret
, "GetConsoleScreenBufferInfoEx failed: error %lu\n", GetLastError());
1143 CloseHandle(hConOut2
);
1145 ok(csbi2
.wAttributes
== orig_attr
, "Character Attributes should have been copied: "
1146 "got %#x, expected %#x\n", csbi2
.wAttributes
, orig_attr
);
1147 ok(csbi2
.wPopupAttributes
!= orig_popup
, "Popup Attributes should not match original value\n");
1148 ok(csbi2
.wPopupAttributes
== orig_attr
, "Popup Attributes should match Character Attributes\n");
1150 csbi
.wPopupAttributes
= orig_popup
;
1151 ret
= SetConsoleScreenBufferInfoEx(hConOut
, &csbi
);
1152 ok(ret
, "SetConsoleScreenBufferInfoEx failed: error %lu\n", GetLastError());
1155 static void CALLBACK
signaled_function(void *p
, BOOLEAN timeout
)
1159 ok(!timeout
, "wait shouldn't have timed out\n");
1162 static void testWaitForConsoleInput(HANDLE input_handle
)
1165 HANDLE complete_event
;
1166 INPUT_RECORD record
;
1167 DWORD events_written
;
1171 complete_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1173 /* Test success case */
1174 ret
= RegisterWaitForSingleObject(&wait_handle
, input_handle
, signaled_function
, complete_event
, INFINITE
, WT_EXECUTEONLYONCE
);
1175 ok(ret
== TRUE
, "Expected RegisterWaitForSingleObject to return TRUE, got %d\n", ret
);
1176 /* give worker thread a chance to start up */
1178 record
.EventType
= KEY_EVENT
;
1179 record
.Event
.KeyEvent
.bKeyDown
= 1;
1180 record
.Event
.KeyEvent
.wRepeatCount
= 1;
1181 record
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1182 record
.Event
.KeyEvent
.wVirtualScanCode
= VK_RETURN
;
1183 record
.Event
.KeyEvent
.uChar
.UnicodeChar
= '\r';
1184 record
.Event
.KeyEvent
.dwControlKeyState
= 0;
1185 ret
= WriteConsoleInputW(input_handle
, &record
, 1, &events_written
);
1186 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
1187 wait_ret
= WaitForSingleObject(complete_event
, INFINITE
);
1188 ok(wait_ret
== WAIT_OBJECT_0
, "Expected the handle to be signaled\n");
1189 ret
= UnregisterWait(wait_handle
);
1190 /* If the callback is still running, this fails with ERROR_IO_PENDING, but
1191 that's ok and expected. */
1192 ok(ret
!= 0 || GetLastError() == ERROR_IO_PENDING
,
1193 "UnregisterWait failed with error %ld\n", GetLastError());
1195 /* Test timeout case */
1196 FlushConsoleInputBuffer(input_handle
);
1197 ret
= RegisterWaitForSingleObject(&wait_handle
, input_handle
, signaled_function
, complete_event
, INFINITE
, WT_EXECUTEONLYONCE
);
1198 wait_ret
= WaitForSingleObject(complete_event
, 100);
1199 ok(wait_ret
== WAIT_TIMEOUT
, "Expected the wait to time out\n");
1200 ret
= UnregisterWait(wait_handle
);
1201 ok(ret
, "UnregisterWait failed with error %ld\n", GetLastError());
1204 CloseHandle(complete_event
);
1207 static BOOL
filter_spurious_event(HANDLE input
)
1212 if (!ReadConsoleInputW(input
, &ir
, 1, &r
) || r
!= 1) return FALSE
;
1214 switch (ir
.EventType
)
1217 if (ir
.Event
.MouseEvent
.dwEventFlags
== MOUSE_MOVED
) return TRUE
;
1218 ok(0, "Unexcepted mouse message: state=%lx ctrl=%lx flags=%lx (%u, %u)\n",
1219 ir
.Event
.MouseEvent
.dwButtonState
,
1220 ir
.Event
.MouseEvent
.dwControlKeyState
,
1221 ir
.Event
.MouseEvent
.dwEventFlags
,
1222 ir
.Event
.MouseEvent
.dwMousePosition
.X
,
1223 ir
.Event
.MouseEvent
.dwMousePosition
.Y
);
1225 case WINDOW_BUFFER_SIZE_EVENT
:
1228 ok(0, "Unexpected message %u\n", ir
.EventType
);
1233 static void test_wait(HANDLE input
, HANDLE orig_output
)
1235 HANDLE output
, unbound_output
, unbound_input
;
1242 if (skip_nt
) return;
1244 memset(&ir
, 0, sizeof(ir
));
1245 ir
.EventType
= MOUSE_EVENT
;
1246 ir
.Event
.MouseEvent
.dwEventFlags
= MOUSE_MOVED
;
1249 output
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
1250 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
1251 CONSOLE_TEXTMODE_BUFFER
, NULL
);
1252 ok(output
!= INVALID_HANDLE_VALUE
, "CreateConsoleScreenBuffer failed: %lu\n", GetLastError());
1254 ret
= SetConsoleActiveScreenBuffer(output
);
1255 ok(ret
, "SetConsoleActiveScreenBuffer failed: %lu\n", GetLastError());
1256 ret
= FlushConsoleInputBuffer(input
);
1257 ok(ret
, "FlushConsoleInputBuffer failed: %lu\n", GetLastError());
1259 unbound_output
= create_unbound_handle(TRUE
, TRUE
);
1260 unbound_input
= create_unbound_handle(FALSE
, TRUE
);
1262 while ((res
= WaitForSingleObject(input
, 0)) == WAIT_OBJECT_0
)
1264 if (!filter_spurious_event(input
)) break;
1266 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lx\n", res
);
1267 while ((res
= WaitForSingleObject(output
, 0)) == WAIT_OBJECT_0
)
1269 if (!filter_spurious_event(input
)) break;
1271 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lx\n", res
);
1272 while ((res
= WaitForSingleObject(orig_output
, 0)) == WAIT_OBJECT_0
)
1274 if (!filter_spurious_event(input
)) break;
1276 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lx\n", res
);
1277 while ((res
= WaitForSingleObject(unbound_output
, 0)) == WAIT_OBJECT_0
)
1279 if (!filter_spurious_event(unbound_input
)) break;
1281 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lx\n", res
);
1282 while ((res
= WaitForSingleObject(unbound_input
, 0)) == WAIT_OBJECT_0
)
1284 if (!filter_spurious_event(unbound_input
)) break;
1286 ok(res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lx\n", res
);
1287 while ((status
= NtWaitForSingleObject(input
, FALSE
, &zero
)) == STATUS_SUCCESS
)
1289 if (!filter_spurious_event(input
)) break;
1291 ok(status
== STATUS_TIMEOUT
|| broken(status
== STATUS_ACCESS_DENIED
/* win2k8 */),
1292 "NtWaitForSingleObject returned %lx\n", status
);
1293 while ((status
= NtWaitForSingleObject(output
, FALSE
, &zero
)) == STATUS_SUCCESS
)
1295 if (!filter_spurious_event(input
)) break;
1297 ok(status
== STATUS_TIMEOUT
|| broken(status
== STATUS_ACCESS_DENIED
/* win2k8 */),
1298 "NtWaitForSingleObject returned %lx\n", status
);
1300 ret
= WriteConsoleInputW(input
, &ir
, 1, &count
);
1301 ok(ret
, "WriteConsoleInputW failed: %lu\n", GetLastError());
1303 res
= WaitForSingleObject(input
, 0);
1304 ok(!res
, "WaitForSingleObject returned %lx\n", res
);
1305 res
= WaitForSingleObject(output
, 0);
1306 ok(!res
, "WaitForSingleObject returned %lx\n", res
);
1307 res
= WaitForSingleObject(orig_output
, 0);
1308 ok(!res
, "WaitForSingleObject returned %lx\n", res
);
1309 res
= WaitForSingleObject(unbound_output
, 0);
1310 ok(!res
, "WaitForSingleObject returned %lx\n", res
);
1311 res
= WaitForSingleObject(unbound_input
, 0);
1312 ok(!res
, "WaitForSingleObject returned %lx\n", res
);
1313 status
= NtWaitForSingleObject(input
, FALSE
, &zero
);
1314 ok(!status
|| broken(status
== STATUS_ACCESS_DENIED
/* win2k8 */),
1315 "NtWaitForSingleObject returned %lx\n", status
);
1316 status
= NtWaitForSingleObject(output
, FALSE
, &zero
);
1317 ok(!status
|| broken(status
== STATUS_ACCESS_DENIED
/* win2k8 */),
1318 "NtWaitForSingleObject returned %lx\n", status
);
1320 ret
= SetConsoleActiveScreenBuffer(orig_output
);
1321 ok(ret
, "SetConsoleActiveScreenBuffer failed: %lu\n", GetLastError());
1323 CloseHandle(unbound_input
);
1324 CloseHandle(unbound_output
);
1325 CloseHandle(output
);
1328 static void test_GetSetConsoleInputExeName(void)
1332 char buffer
[MAX_PATH
], module
[MAX_PATH
], *p
;
1333 static char input_exe
[MAX_PATH
] = "winetest.exe";
1335 SetLastError(0xdeadbeef);
1336 ret
= pGetConsoleInputExeNameA(0, NULL
);
1337 error
= GetLastError();
1338 ok(ret
, "GetConsoleInputExeNameA failed\n");
1339 ok(error
== ERROR_BUFFER_OVERFLOW
, "got %lu expected ERROR_BUFFER_OVERFLOW\n", error
);
1341 SetLastError(0xdeadbeef);
1342 ret
= pGetConsoleInputExeNameA(0, buffer
);
1343 error
= GetLastError();
1344 ok(ret
, "GetConsoleInputExeNameA failed\n");
1345 ok(error
== ERROR_BUFFER_OVERFLOW
, "got %lu expected ERROR_BUFFER_OVERFLOW\n", error
);
1347 GetModuleFileNameA(GetModuleHandleA(NULL
), module
, sizeof(module
));
1348 p
= strrchr(module
, '\\') + 1;
1350 ret
= pGetConsoleInputExeNameA(ARRAY_SIZE(buffer
), buffer
);
1351 ok(ret
, "GetConsoleInputExeNameA failed\n");
1352 todo_wine
ok(!lstrcmpA(buffer
, p
), "got %s expected %s\n", buffer
, p
);
1354 SetLastError(0xdeadbeef);
1355 ret
= pSetConsoleInputExeNameA(NULL
);
1356 error
= GetLastError();
1357 ok(!ret
, "SetConsoleInputExeNameA failed\n");
1358 ok(error
== ERROR_INVALID_PARAMETER
, "got %lu expected ERROR_INVALID_PARAMETER\n", error
);
1360 SetLastError(0xdeadbeef);
1361 ret
= pSetConsoleInputExeNameA("");
1362 error
= GetLastError();
1363 ok(!ret
, "SetConsoleInputExeNameA failed\n");
1364 ok(error
== ERROR_INVALID_PARAMETER
, "got %lu expected ERROR_INVALID_PARAMETER\n", error
);
1366 ret
= pSetConsoleInputExeNameA(input_exe
);
1367 ok(ret
, "SetConsoleInputExeNameA failed\n");
1369 ret
= pGetConsoleInputExeNameA(ARRAY_SIZE(buffer
), buffer
);
1370 ok(ret
, "GetConsoleInputExeNameA failed\n");
1371 ok(!lstrcmpA(buffer
, input_exe
), "got %s expected %s\n", buffer
, input_exe
);
1374 static void test_GetConsoleProcessList(void)
1376 DWORD ret
, *list
= NULL
;
1378 if (!pGetConsoleProcessList
)
1380 win_skip("GetConsoleProcessList is not available\n");
1384 SetLastError(0xdeadbeef);
1385 ret
= pGetConsoleProcessList(NULL
, 0);
1386 ok(ret
== 0, "Expected failure\n");
1387 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1388 "Expected ERROR_INVALID_PARAMETER, got %ld\n",
1391 SetLastError(0xdeadbeef);
1392 ret
= pGetConsoleProcessList(NULL
, 1);
1393 ok(ret
== 0, "Expected failure\n");
1394 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1395 "Expected ERROR_INVALID_PARAMETER, got %ld\n",
1398 /* We should only have 1 process but only for these specific unit tests as
1399 * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS)
1400 * gives us two processes - see test_AttachConsole.
1402 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD
));
1404 SetLastError(0xdeadbeef);
1405 ret
= pGetConsoleProcessList(list
, 0);
1406 ok(ret
== 0, "Expected failure\n");
1407 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1408 "Expected ERROR_INVALID_PARAMETER, got %ld\n",
1411 SetLastError(0xdeadbeef);
1412 ret
= pGetConsoleProcessList(list
, 1);
1413 ok(ret
== 1, "Expected 1, got %ld\n", ret
);
1415 HeapFree(GetProcessHeap(), 0, list
);
1417 list
= HeapAlloc(GetProcessHeap(), 0, ret
* sizeof(DWORD
));
1419 SetLastError(0xdeadbeef);
1420 ret
= pGetConsoleProcessList(list
, ret
);
1421 ok(ret
== 1, "Expected 1, got %ld\n", ret
);
1425 DWORD pid
= GetCurrentProcessId();
1426 ok(list
[0] == pid
, "Expected %ld, got %ld\n", pid
, list
[0]);
1429 HeapFree(GetProcessHeap(), 0, list
);
1432 static void test_OpenCON(void)
1434 static const WCHAR conW
[] = {'C','O','N',0};
1435 static const DWORD accesses
[] = {CREATE_NEW
, CREATE_ALWAYS
, OPEN_EXISTING
,
1436 OPEN_ALWAYS
, TRUNCATE_EXISTING
};
1440 for (i
= 0; i
< ARRAY_SIZE(accesses
); i
++)
1442 h
= CreateFileW(conW
, GENERIC_WRITE
, 0, NULL
, accesses
[i
], 0, NULL
);
1443 ok(h
!= INVALID_HANDLE_VALUE
|| broken(accesses
[i
] == TRUNCATE_EXISTING
/* Win8 */),
1444 "Expected to open the CON device on write (%lx)\n", accesses
[i
]);
1447 h
= CreateFileW(conW
, GENERIC_READ
, 0, NULL
, accesses
[i
], 0, NULL
);
1448 /* Windows versions differ here:
1449 * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1450 * NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING
1451 * So don't test when disposition is TRUNCATE_EXISTING
1453 ok(h
!= INVALID_HANDLE_VALUE
|| broken(accesses
[i
] == TRUNCATE_EXISTING
/* Win7+ */),
1454 "Expected to open the CON device on read (%lx)\n", accesses
[i
]);
1456 h
= CreateFileW(conW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, accesses
[i
], 0, NULL
);
1457 ok(h
== INVALID_HANDLE_VALUE
, "Expected not to open the CON device on read-write (%lx)\n", accesses
[i
]);
1458 ok(GetLastError() == ERROR_FILE_NOT_FOUND
|| GetLastError() == ERROR_INVALID_PARAMETER
,
1459 "Unexpected error %lx\n", GetLastError());
1463 static void test_OpenConsoleW(void)
1465 static const WCHAR coninW
[] = {'C','O','N','I','N','$',0};
1466 static const WCHAR conoutW
[] = {'C','O','N','O','U','T','$',0};
1467 static const WCHAR emptyW
[] = {0};
1468 static const WCHAR invalidW
[] = {'I','N','V','A','L','I','D',0};
1478 } invalid_table
[] = {
1479 {NULL
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1480 {NULL
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1481 {NULL
, 0xdeadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1482 {NULL
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1483 {NULL
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1484 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1485 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1486 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1487 {emptyW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1488 {emptyW
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1489 {emptyW
, 0xdeadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1490 {emptyW
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1491 {emptyW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1492 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1493 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1494 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
, ERROR_PATH_NOT_FOUND
},
1495 {invalidW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1496 {invalidW
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1497 {invalidW
, 0xdeadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1498 {invalidW
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1499 {invalidW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1500 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1501 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1502 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
, ERROR_FILE_NOT_FOUND
},
1503 {coninW
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1504 {coninW
, 0xdeadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_ACCESS_DENIED
},
1505 {coninW
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1506 {conoutW
, 0, FALSE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1507 {conoutW
, 0xceadbeef, FALSE
, 0, ERROR_INVALID_PARAMETER
, ERROR_ACCESS_DENIED
},
1508 {conoutW
, 0xdeadbeef, TRUE
, 0xdeadbeef, ERROR_INVALID_PARAMETER
, 0},
1517 {coninW
, 0, FALSE
, 0 },
1518 {coninW
, 0, TRUE
, 0 },
1519 {coninW
, GENERIC_EXECUTE
, TRUE
, 0 },
1520 {coninW
, GENERIC_ALL
, TRUE
, 0 },
1521 {coninW
, 0, FALSE
, OPEN_ALWAYS
},
1522 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0 },
1523 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
},
1524 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
},
1525 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
},
1526 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
},
1527 {conoutW
, 0, FALSE
, 0 },
1528 {conoutW
, 0, FALSE
, OPEN_ALWAYS
},
1529 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0 },
1530 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, },
1531 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
},
1532 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
},
1533 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
},
1541 win_skip("OpenConsoleW is not available\n");
1545 for (index
= 0; index
< ARRAY_SIZE(invalid_table
); index
++)
1547 SetLastError(0xdeadbeef);
1548 ret
= pOpenConsoleW(invalid_table
[index
].name
, invalid_table
[index
].access
,
1549 invalid_table
[index
].inherit
, invalid_table
[index
].creation
);
1550 gle
= GetLastError();
1551 ok(ret
== INVALID_HANDLE_VALUE
,
1552 "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1554 ok(gle
== invalid_table
[index
].gle
|| (gle
!= 0 && gle
== invalid_table
[index
].gle2
),
1555 "Expected GetLastError() to return %lu/%lu for index %d, got %lu\n",
1556 invalid_table
[index
].gle
, invalid_table
[index
].gle2
, index
, gle
);
1559 for (index
= 0; index
< ARRAY_SIZE(valid_table
); index
++)
1561 ret
= pOpenConsoleW(valid_table
[index
].name
, valid_table
[index
].access
,
1562 valid_table
[index
].inherit
, valid_table
[index
].creation
);
1564 ok(ret
!= INVALID_HANDLE_VALUE
|| broken(ret
== INVALID_HANDLE_VALUE
/* until Win7 */),
1565 "Expected OpenConsoleW to succeed for index %d, got %p\n", index
, ret
);
1566 if (ret
!= INVALID_HANDLE_VALUE
)
1570 ret
= pOpenConsoleW(coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
);
1571 ok(ret
!= INVALID_HANDLE_VALUE
, "Expected OpenConsoleW to return a valid handle\n");
1572 if (ret
!= INVALID_HANDLE_VALUE
)
1575 ret
= pOpenConsoleW(conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
);
1576 ok(ret
!= INVALID_HANDLE_VALUE
, "Expected OpenConsoleW to return a valid handle\n");
1577 if (ret
!= INVALID_HANDLE_VALUE
)
1581 static void test_CreateFileW(void)
1592 {TRUE
, 0, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1593 {TRUE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1594 {TRUE
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1595 {TRUE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, 0, FALSE
},
1596 {TRUE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, 0, FALSE
},
1597 {TRUE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1598 {FALSE
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1599 {FALSE
, 0, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1600 {FALSE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
, TRUE
},
1601 {FALSE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, 0, FALSE
},
1602 {FALSE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, 0, FALSE
},
1603 {FALSE
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, 0, FALSE
},
1604 /* TRUNCATE_EXISTING is forbidden starting with Windows 8 */
1607 static const UINT nt_disposition
[5] =
1609 FILE_CREATE
, /* CREATE_NEW */
1610 FILE_OVERWRITE_IF
, /* CREATE_ALWAYS */
1611 FILE_OPEN
, /* OPEN_EXISTING */
1612 FILE_OPEN_IF
, /* OPEN_ALWAYS */
1613 FILE_OVERWRITE
/* TRUNCATE_EXISTING */
1618 SECURITY_ATTRIBUTES sa
;
1619 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
1620 UNICODE_STRING string
;
1621 IO_STATUS_BLOCK iosb
;
1624 for (index
= 0; index
< ARRAY_SIZE(cf_table
); index
++)
1626 SetLastError(0xdeadbeef);
1628 sa
.nLength
= sizeof(sa
);
1629 sa
.lpSecurityDescriptor
= NULL
;
1630 sa
.bInheritHandle
= cf_table
[index
].inherit
;
1632 ret
= CreateFileW(cf_table
[index
].input
? L
"CONIN$" : L
"CONOUT$", cf_table
[index
].access
,
1633 FILE_SHARE_READ
|FILE_SHARE_WRITE
, &sa
,
1634 cf_table
[index
].creation
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1635 if (ret
== INVALID_HANDLE_VALUE
)
1637 ok(cf_table
[index
].gle
,
1638 "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index
);
1639 ok(GetLastError() == cf_table
[index
].gle
,
1640 "Expected GetLastError() to return %lu for index %d, got %lu\n",
1641 cf_table
[index
].gle
, index
, GetLastError());
1645 ok(!cf_table
[index
].gle
|| broken(cf_table
[index
].is_broken
) /* Win7 */,
1646 "Expected CreateFileW to succeed for index %d\n", index
);
1650 if (skip_nt
) continue;
1652 SetLastError(0xdeadbeef);
1654 sa
.nLength
= sizeof(sa
);
1655 sa
.lpSecurityDescriptor
= NULL
;
1656 sa
.bInheritHandle
= cf_table
[index
].inherit
;
1658 ret
= CreateFileW(cf_table
[index
].input
? L
"\\??\\CONIN$" : L
"\\??\\CONOUT$", cf_table
[index
].access
,
1659 FILE_SHARE_READ
|FILE_SHARE_WRITE
, &sa
,
1660 cf_table
[index
].creation
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1661 if (cf_table
[index
].gle
)
1662 ok(ret
== INVALID_HANDLE_VALUE
&& GetLastError() == cf_table
[index
].gle
,
1663 "CreateFileW to returned %p %lu for index %d\n", ret
, GetLastError(), index
);
1665 ok(ret
!= INVALID_HANDLE_VALUE
&& (!cf_table
[index
].gle
|| broken(cf_table
[index
].is_broken
) /* Win7 */),
1666 "CreateFileW to returned %p %lu for index %d\n", ret
, GetLastError(), index
);
1667 if (ret
!= INVALID_HANDLE_VALUE
) CloseHandle(ret
);
1669 if (cf_table
[index
].gle
) continue;
1671 RtlInitUnicodeString(&string
, cf_table
[index
].input
1672 ? L
"\\Device\\ConDrv\\CurrentIn" : L
"\\Device\\ConDrv\\CurrentOut");
1673 attr
.ObjectName
= &string
;
1674 status
= NtCreateFile(&ret
, cf_table
[index
].access
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
, &attr
, &iosb
, NULL
,
1675 FILE_ATTRIBUTE_NORMAL
, 0, nt_disposition
[cf_table
[index
].creation
- CREATE_NEW
],
1676 FILE_NON_DIRECTORY_FILE
, NULL
, 0);
1677 ok(!status
, "NtCreateFile failed %lx for %u\n", status
, index
);
1680 RtlInitUnicodeString(&string
, cf_table
[index
].input
? L
"\\??\\CONIN$" : L
"\\??\\CONOUT$");
1681 attr
.ObjectName
= &string
;
1682 status
= NtCreateFile(&ret
, cf_table
[index
].access
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
, &attr
, &iosb
, NULL
,
1683 FILE_ATTRIBUTE_NORMAL
, 0, nt_disposition
[cf_table
[index
].creation
- CREATE_NEW
],
1684 FILE_NON_DIRECTORY_FILE
, NULL
, 0);
1685 ok(!status
, "NtCreateFile failed %lx for %u\n", status
, index
);
1690 static void test_VerifyConsoleIoHandle( HANDLE handle
)
1695 if (!pVerifyConsoleIoHandle
)
1697 win_skip("VerifyConsoleIoHandle is not available\n");
1701 /* invalid handle */
1702 SetLastError(0xdeadbeef);
1703 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee0);
1704 error
= GetLastError();
1705 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1706 ok(error
== 0xdeadbeef, "wrong GetLastError() %ld\n", error
);
1708 /* invalid handle + 1 */
1709 SetLastError(0xdeadbeef);
1710 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee1);
1711 error
= GetLastError();
1712 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1713 ok(error
== 0xdeadbeef, "wrong GetLastError() %ld\n", error
);
1715 /* invalid handle + 2 */
1716 SetLastError(0xdeadbeef);
1717 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee2);
1718 error
= GetLastError();
1719 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1720 ok(error
== 0xdeadbeef, "wrong GetLastError() %ld\n", error
);
1722 /* invalid handle + 3 */
1723 SetLastError(0xdeadbeef);
1724 ret
= pVerifyConsoleIoHandle((HANDLE
)0xdeadbee3);
1725 error
= GetLastError();
1726 ok(!ret
, "expected VerifyConsoleIoHandle to fail\n");
1727 ok(error
== 0xdeadbeef, "wrong GetLastError() %ld\n", error
);
1730 SetLastError(0xdeadbeef);
1731 ret
= pVerifyConsoleIoHandle(handle
);
1732 error
= GetLastError();
1734 broken(!ret
), /* Windows 8 and 10 */
1735 "expected VerifyConsoleIoHandle to succeed\n");
1736 ok(error
== 0xdeadbeef, "wrong GetLastError() %ld\n", error
);
1739 static void test_GetSetStdHandle(void)
1745 /* get invalid std handle */
1746 SetLastError(0xdeadbeef);
1747 handle
= GetStdHandle(42);
1748 error
= GetLastError();
1749 ok(error
== ERROR_INVALID_HANDLE
|| broken(error
== ERROR_INVALID_FUNCTION
)/* Win9x */,
1750 "wrong GetLastError() %ld\n", error
);
1751 ok(handle
== INVALID_HANDLE_VALUE
, "expected INVALID_HANDLE_VALUE\n");
1754 SetLastError(0xdeadbeef);
1755 handle
= GetStdHandle(STD_INPUT_HANDLE
);
1756 error
= GetLastError();
1757 ok(error
== 0xdeadbeef, "wrong GetLastError() %ld\n", error
);
1759 /* set invalid std handle */
1760 SetLastError(0xdeadbeef);
1761 ret
= SetStdHandle(42, handle
);
1762 error
= GetLastError();
1763 ok(!ret
, "expected SetStdHandle to fail\n");
1764 ok(error
== ERROR_INVALID_HANDLE
|| broken(error
== ERROR_INVALID_FUNCTION
)/* Win9x */,
1765 "wrong GetLastError() %ld\n", error
);
1767 /* set valid (restore old value) */
1768 SetLastError(0xdeadbeef);
1769 ret
= SetStdHandle(STD_INPUT_HANDLE
, handle
);
1770 error
= GetLastError();
1771 ok(ret
, "expected SetStdHandle to succeed\n");
1772 ok(error
== 0xdeadbeef, "wrong GetLastError() %ld\n", error
);
1775 static void test_DuplicateConsoleHandle(void)
1777 HANDLE handle
, event
;
1780 if (skip_nt
) return;
1782 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1784 /* duplicate an event handle with DuplicateConsoleHandle */
1785 handle
= DuplicateConsoleHandle(event
, 0, FALSE
, DUPLICATE_SAME_ACCESS
);
1786 ok(handle
!= NULL
, "DuplicateConsoleHandle failed: %lu\n", GetLastError());
1788 ret
= SetEvent(handle
);
1789 ok(ret
, "SetEvent failed: %lu\n", GetLastError());
1791 ret
= CloseConsoleHandle(handle
);
1792 ok(ret
, "CloseConsoleHandle failed: %lu\n", GetLastError());
1793 ret
= CloseConsoleHandle(event
);
1794 ok(ret
, "CloseConsoleHandle failed: %lu\n", GetLastError());
1796 handle
= DuplicateConsoleHandle((HANDLE
)0xdeadbeef, 0, FALSE
, DUPLICATE_SAME_ACCESS
);
1797 ok(handle
== INVALID_HANDLE_VALUE
, "DuplicateConsoleHandle failed: %lu\n", GetLastError());
1798 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error = %lu\n", GetLastError());
1801 static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle
)
1814 {NULL
, NULL
, ERROR_INVALID_HANDLE
},
1815 {NULL
, &count
, ERROR_INVALID_HANDLE
},
1816 {INVALID_HANDLE_VALUE
, NULL
, ERROR_INVALID_HANDLE
},
1817 {INVALID_HANDLE_VALUE
, &count
, ERROR_INVALID_HANDLE
},
1820 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
1822 SetLastError(0xdeadbeef);
1823 if (invalid_table
[i
].nrofevents
) count
= 0xdeadbeef;
1824 ret
= GetNumberOfConsoleInputEvents(invalid_table
[i
].handle
,
1825 invalid_table
[i
].nrofevents
);
1826 ok(!ret
, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i
, ret
);
1827 if (invalid_table
[i
].nrofevents
)
1829 ok(count
== 0xdeadbeef,
1830 "[%d] Expected output count to be unmodified, got %lu\n", i
, count
);
1832 ok(GetLastError() == invalid_table
[i
].last_error
,
1833 "[%d] Expected last error to be %lu, got %lu\n",
1834 i
, invalid_table
[i
].last_error
, GetLastError());
1837 /* Test crashes on Windows 7. */
1840 SetLastError(0xdeadbeef);
1841 ret
= GetNumberOfConsoleInputEvents(input_handle
, NULL
);
1842 ok(!ret
, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret
);
1843 ok(GetLastError() == ERROR_INVALID_ACCESS
,
1844 "Expected last error to be ERROR_INVALID_ACCESS, got %lu\n",
1849 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1850 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1851 ok(count
!= 0xdeadbeef, "Expected output count to initialized\n");
1854 static void test_WriteConsoleInputA(HANDLE input_handle
)
1857 INPUT_RECORD event_list
[5];
1858 MOUSE_EVENT_RECORD mouse_event
= { {0, 0}, 0, 0, MOUSE_MOVED
};
1859 KEY_EVENT_RECORD key_event
;
1860 DWORD count
, console_mode
, gle
;
1867 const INPUT_RECORD
*buffer
;
1874 {NULL
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1875 {NULL
, NULL
, 0, &count
,ERROR_INVALID_HANDLE
},
1876 {NULL
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1877 {NULL
, NULL
, 1, &count
, ERROR_NOACCESS
, ERROR_INVALID_ACCESS
},
1878 {NULL
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1879 {NULL
, &event
, 0, &count
, ERROR_INVALID_HANDLE
},
1880 {NULL
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1881 {NULL
, &event
, 1, &count
, ERROR_INVALID_HANDLE
},
1882 {INVALID_HANDLE_VALUE
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1883 {INVALID_HANDLE_VALUE
, NULL
, 0, &count
, ERROR_INVALID_HANDLE
},
1884 {INVALID_HANDLE_VALUE
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1885 {INVALID_HANDLE_VALUE
, NULL
, 1, &count
, ERROR_INVALID_HANDLE
, ERROR_INVALID_ACCESS
},
1886 {INVALID_HANDLE_VALUE
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1887 {INVALID_HANDLE_VALUE
, &event
, 0, &count
, ERROR_INVALID_HANDLE
},
1888 {INVALID_HANDLE_VALUE
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1889 {INVALID_HANDLE_VALUE
, &event
, 1, &count
, ERROR_INVALID_HANDLE
},
1890 {input_handle
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1891 {input_handle
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1892 {input_handle
, NULL
, 1, &count
, ERROR_NOACCESS
, ERROR_INVALID_ACCESS
},
1893 {input_handle
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1894 {input_handle
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
1897 /* Suppress external sources of input events for the duration of the test. */
1898 ret
= GetConsoleMode(input_handle
, &console_mode
);
1899 ok(ret
== TRUE
, "Expected GetConsoleMode to return TRUE, got %d\n", ret
);
1902 skip("GetConsoleMode failed with last error %lu\n", GetLastError());
1906 ret
= SetConsoleMode(input_handle
, console_mode
& ~(ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
));
1907 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
1910 skip("SetConsoleMode failed with last error %lu\n", GetLastError());
1914 /* Discard any events queued before the tests. */
1915 ret
= FlushConsoleInputBuffer(input_handle
);
1916 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1918 event
.EventType
= MOUSE_EVENT
;
1919 event
.Event
.MouseEvent
= mouse_event
;
1921 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
1923 if (invalid_table
[i
].win_crash
)
1926 SetLastError(0xdeadbeef);
1927 if (invalid_table
[i
].written
) count
= 0xdeadbeef;
1928 ret
= WriteConsoleInputA(invalid_table
[i
].handle
,
1929 invalid_table
[i
].buffer
,
1930 invalid_table
[i
].count
,
1931 invalid_table
[i
].written
);
1932 ok(!ret
, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i
, ret
);
1933 gle
= GetLastError();
1934 ok(gle
== invalid_table
[i
].gle
|| (gle
!= 0 && gle
== invalid_table
[i
].gle2
),
1935 "[%d] Expected last error to be %lu or %lu, got %lu\n",
1936 i
, invalid_table
[i
].gle
, invalid_table
[i
].gle2
, gle
);
1940 ret
= WriteConsoleInputA(input_handle
, NULL
, 0, &count
);
1941 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1942 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
1945 ret
= WriteConsoleInputA(input_handle
, &event
, 0, &count
);
1946 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1947 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
1950 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1951 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1952 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
1954 ret
= FlushConsoleInputBuffer(input_handle
);
1955 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1957 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1958 event
.EventType
= MOUSE_EVENT
;
1959 event
.Event
.MouseEvent
= mouse_event
;
1961 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1962 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1963 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
1965 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1966 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1967 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
1969 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
1970 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1971 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
1973 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1974 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1976 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
1978 ret
= FlushConsoleInputBuffer(input_handle
);
1979 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
1981 for (i
= 0; i
< ARRAY_SIZE(event_list
); i
++)
1983 event_list
[i
].EventType
= MOUSE_EVENT
;
1984 event_list
[i
].Event
.MouseEvent
= mouse_event
;
1987 /* Writing consecutive chunks of mouse events appears to work. */
1988 ret
= WriteConsoleInputA(input_handle
, event_list
, ARRAY_SIZE(event_list
), &count
);
1989 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
1990 ok(count
== ARRAY_SIZE(event_list
),
1991 "Expected count to be event list length, got %lu\n", count
);
1993 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
1994 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
1995 ok(count
== ARRAY_SIZE(event_list
),
1996 "Expected count to be event list length, got %lu\n", count
);
1998 ret
= WriteConsoleInputA(input_handle
, event_list
, ARRAY_SIZE(event_list
), &count
);
1999 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
2000 ok(count
== ARRAY_SIZE(event_list
),
2001 "Expected count to be event list length, got %lu\n", count
);
2003 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2004 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2005 ok(count
== 2*ARRAY_SIZE(event_list
),
2006 "Expected count to be twice event list length, got %lu\n", count
);
2008 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
2009 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
2010 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
2011 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2013 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2014 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2016 ok(count
== 2*ARRAY_SIZE(event_list
),
2017 "Expected count to be twice event list length, got %lu\n", count
);
2019 ret
= FlushConsoleInputBuffer(input_handle
);
2020 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2022 key_event
.bKeyDown
= FALSE
;
2023 key_event
.wRepeatCount
= 0;
2024 key_event
.wVirtualKeyCode
= VK_SPACE
;
2025 key_event
.wVirtualScanCode
= VK_SPACE
;
2026 key_event
.uChar
.AsciiChar
= ' ';
2027 key_event
.dwControlKeyState
= 0;
2029 event
.EventType
= KEY_EVENT
;
2030 event
.Event
.KeyEvent
= key_event
;
2032 /* Key events don't exhibit the same behavior as mouse events. */
2033 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
2034 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
2035 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2037 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2038 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2039 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2041 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
2042 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
2043 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2045 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2046 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2047 ok(count
== 2, "Expected count to be 2, got %lu\n", count
);
2049 ret
= FlushConsoleInputBuffer(input_handle
);
2050 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2052 /* Try interleaving mouse and key events. */
2053 event
.EventType
= MOUSE_EVENT
;
2054 event
.Event
.MouseEvent
= mouse_event
;
2056 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
2057 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
2058 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2060 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2061 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2062 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2064 event
.EventType
= KEY_EVENT
;
2065 event
.Event
.KeyEvent
= key_event
;
2067 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
2068 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
2069 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2071 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2072 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2073 ok(count
== 2, "Expected count to be 2, got %lu\n", count
);
2075 event
.EventType
= MOUSE_EVENT
;
2076 event
.Event
.MouseEvent
= mouse_event
;
2078 ret
= WriteConsoleInputA(input_handle
, &event
, 1, &count
);
2079 ok(ret
== TRUE
, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret
);
2080 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2082 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2083 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2084 ok(count
== 3, "Expected count to be 3, got %lu\n", count
);
2086 /* Restore the old console mode. */
2087 ret
= SetConsoleMode(input_handle
, console_mode
);
2088 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
2091 static void test_WriteConsoleInputW(HANDLE input_handle
)
2094 INPUT_RECORD event_list
[5];
2095 MOUSE_EVENT_RECORD mouse_event
= { {0, 0}, 0, 0, MOUSE_MOVED
};
2096 KEY_EVENT_RECORD key_event
;
2097 DWORD count
, console_mode
, gle
;
2104 const INPUT_RECORD
*buffer
;
2111 {NULL
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2112 {NULL
, NULL
, 0, &count
, ERROR_INVALID_HANDLE
},
2113 {NULL
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2114 {NULL
, NULL
, 1, &count
, ERROR_NOACCESS
, ERROR_INVALID_ACCESS
},
2115 {NULL
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2116 {NULL
, &event
, 0, &count
, ERROR_INVALID_HANDLE
},
2117 {NULL
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2118 {NULL
, &event
, 1, &count
, ERROR_INVALID_HANDLE
},
2119 {INVALID_HANDLE_VALUE
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2120 {INVALID_HANDLE_VALUE
, NULL
, 0, &count
, ERROR_INVALID_HANDLE
},
2121 {INVALID_HANDLE_VALUE
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2122 {INVALID_HANDLE_VALUE
, NULL
, 1, &count
, ERROR_INVALID_HANDLE
, ERROR_INVALID_ACCESS
},
2123 {INVALID_HANDLE_VALUE
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2124 {INVALID_HANDLE_VALUE
, &event
, 0, &count
, ERROR_INVALID_HANDLE
},
2125 {INVALID_HANDLE_VALUE
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2126 {INVALID_HANDLE_VALUE
, &event
, 1, &count
, ERROR_INVALID_HANDLE
},
2127 {input_handle
, NULL
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2128 {input_handle
, NULL
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2129 {input_handle
, NULL
, 1, &count
, ERROR_NOACCESS
, ERROR_INVALID_ACCESS
},
2130 {input_handle
, &event
, 0, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2131 {input_handle
, &event
, 1, NULL
, ERROR_INVALID_ACCESS
, 0, 1},
2134 /* Suppress external sources of input events for the duration of the test. */
2135 ret
= GetConsoleMode(input_handle
, &console_mode
);
2136 ok(ret
== TRUE
, "Expected GetConsoleMode to return TRUE, got %d\n", ret
);
2139 skip("GetConsoleMode failed with last error %lu\n", GetLastError());
2143 ret
= SetConsoleMode(input_handle
, console_mode
& ~(ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
));
2144 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
2147 skip("SetConsoleMode failed with last error %lu\n", GetLastError());
2151 /* Discard any events queued before the tests. */
2152 ret
= FlushConsoleInputBuffer(input_handle
);
2153 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2155 event
.EventType
= MOUSE_EVENT
;
2156 event
.Event
.MouseEvent
= mouse_event
;
2158 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2160 if (invalid_table
[i
].win_crash
)
2163 SetLastError(0xdeadbeef);
2164 if (invalid_table
[i
].written
) count
= 0xdeadbeef;
2165 ret
= WriteConsoleInputW(invalid_table
[i
].handle
,
2166 invalid_table
[i
].buffer
,
2167 invalid_table
[i
].count
,
2168 invalid_table
[i
].written
);
2169 ok(!ret
, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i
, ret
);
2170 gle
= GetLastError();
2171 ok(gle
== invalid_table
[i
].gle
|| (gle
!= 0 && gle
== invalid_table
[i
].gle2
),
2172 "[%d] Expected last error to be %lu or %lu, got %lu\n",
2173 i
, invalid_table
[i
].gle
, invalid_table
[i
].gle2
, gle
);
2177 ret
= WriteConsoleInputW(input_handle
, NULL
, 0, &count
);
2178 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2179 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2182 ret
= WriteConsoleInputW(input_handle
, &event
, 0, &count
);
2183 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2184 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2187 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2188 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2189 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2191 ret
= FlushConsoleInputBuffer(input_handle
);
2192 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2194 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
2195 event
.EventType
= MOUSE_EVENT
;
2196 event
.Event
.MouseEvent
= mouse_event
;
2198 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2199 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2200 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2202 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2203 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2204 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2206 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2207 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2208 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2210 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2211 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2213 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2215 ret
= FlushConsoleInputBuffer(input_handle
);
2216 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2218 for (i
= 0; i
< ARRAY_SIZE(event_list
); i
++)
2220 event_list
[i
].EventType
= MOUSE_EVENT
;
2221 event_list
[i
].Event
.MouseEvent
= mouse_event
;
2224 /* Writing consecutive chunks of mouse events appears to work. */
2225 ret
= WriteConsoleInputW(input_handle
, event_list
, ARRAY_SIZE(event_list
), &count
);
2226 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2227 ok(count
== ARRAY_SIZE(event_list
),
2228 "Expected count to be event list length, got %lu\n", count
);
2230 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2231 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2232 ok(count
== ARRAY_SIZE(event_list
),
2233 "Expected count to be event list length, got %lu\n", count
);
2235 ret
= WriteConsoleInputW(input_handle
, event_list
, ARRAY_SIZE(event_list
), &count
);
2236 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2237 ok(count
== ARRAY_SIZE(event_list
),
2238 "Expected count to be event list length, got %lu\n", count
);
2240 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2241 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2242 ok(count
== 2*ARRAY_SIZE(event_list
),
2243 "Expected count to be twice event list length, got %lu\n", count
);
2245 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
2246 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2247 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2248 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2250 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2251 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2253 ok(count
== 2*ARRAY_SIZE(event_list
),
2254 "Expected count to be twice event list length, got %lu\n", count
);
2256 ret
= FlushConsoleInputBuffer(input_handle
);
2257 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2259 key_event
.bKeyDown
= FALSE
;
2260 key_event
.wRepeatCount
= 0;
2261 key_event
.wVirtualKeyCode
= VK_SPACE
;
2262 key_event
.wVirtualScanCode
= VK_SPACE
;
2263 key_event
.uChar
.UnicodeChar
= ' ';
2264 key_event
.dwControlKeyState
= 0;
2266 event
.EventType
= KEY_EVENT
;
2267 event
.Event
.KeyEvent
= key_event
;
2269 /* Key events don't exhibit the same behavior as mouse events. */
2270 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2271 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2272 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2274 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2275 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2276 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2278 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2279 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2280 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2282 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2283 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2284 ok(count
== 2, "Expected count to be 2, got %lu\n", count
);
2286 ret
= FlushConsoleInputBuffer(input_handle
);
2287 ok(ret
== TRUE
, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret
);
2289 /* Try interleaving mouse and key events. */
2290 event
.EventType
= MOUSE_EVENT
;
2291 event
.Event
.MouseEvent
= mouse_event
;
2293 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2294 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2295 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2297 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2298 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2299 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2301 event
.EventType
= KEY_EVENT
;
2302 event
.Event
.KeyEvent
= key_event
;
2304 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2305 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2306 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2308 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2309 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2310 ok(count
== 2, "Expected count to be 2, got %lu\n", count
);
2312 event
.EventType
= MOUSE_EVENT
;
2313 event
.Event
.MouseEvent
= mouse_event
;
2315 ret
= WriteConsoleInputW(input_handle
, &event
, 1, &count
);
2316 ok(ret
== TRUE
, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret
);
2317 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2319 ret
= GetNumberOfConsoleInputEvents(input_handle
, &count
);
2320 ok(ret
== TRUE
, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret
);
2321 ok(count
== 3, "Expected count to be 3, got %lu\n", count
);
2323 /* Restore the old console mode. */
2324 ret
= SetConsoleMode(input_handle
, console_mode
);
2325 ok(ret
== TRUE
, "Expected SetConsoleMode to return TRUE, got %d\n", ret
);
2328 static void test_FlushConsoleInputBuffer(HANDLE input
, HANDLE output
)
2330 INPUT_RECORD record
;
2334 ret
= FlushConsoleInputBuffer(input
);
2335 ok(ret
, "FlushConsoleInputBuffer failed: %lu\n", GetLastError());
2337 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2338 ok(ret
, "GetNumberOfConsoleInputEvents failed: %lu\n", GetLastError());
2339 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2341 record
.EventType
= KEY_EVENT
;
2342 record
.Event
.KeyEvent
.bKeyDown
= 1;
2343 record
.Event
.KeyEvent
.wRepeatCount
= 1;
2344 record
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
2345 record
.Event
.KeyEvent
.wVirtualScanCode
= VK_RETURN
;
2346 record
.Event
.KeyEvent
.uChar
.UnicodeChar
= '\r';
2347 record
.Event
.KeyEvent
.dwControlKeyState
= 0;
2348 ret
= WriteConsoleInputW(input
, &record
, 1, &count
);
2349 ok(ret
, "WriteConsoleInputW failed: %lu\n", GetLastError());
2351 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2352 ok(ret
, "GetNumberOfConsoleInputEvents failed: %lu\n", GetLastError());
2353 ok(count
== 1, "Expected count to be 0, got %lu\n", count
);
2355 ret
= FlushConsoleInputBuffer(input
);
2356 ok(ret
, "FlushConsoleInputBuffer failed: %lu\n", GetLastError());
2358 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2359 ok(ret
, "GetNumberOfConsoleInputEvents failed: %lu\n", GetLastError());
2360 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2362 ret
= WriteConsoleInputW(input
, &record
, 1, &count
);
2363 ok(ret
, "WriteConsoleInputW failed: %lu\n", GetLastError());
2365 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2366 ok(ret
, "GetNumberOfConsoleInputEvents failed: %lu\n", GetLastError());
2367 ok(count
== 1, "Expected count to be 0, got %lu\n", count
);
2369 ret
= FlushFileBuffers(input
);
2370 ok(ret
, "FlushFileBuffers failed: %lu\n", GetLastError());
2372 ret
= GetNumberOfConsoleInputEvents(input
, &count
);
2373 ok(ret
, "GetNumberOfConsoleInputEvents failed: %lu\n", GetLastError());
2374 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2376 ret
= FlushConsoleInputBuffer(output
);
2377 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "FlushConsoleInputBuffer returned: %x(%lu)\n",
2378 ret
, GetLastError());
2380 ret
= FlushFileBuffers(output
);
2381 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "FlushFileBuffers returned: %x(%lu)\n",
2382 ret
, GetLastError());
2385 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle
)
2387 static const char output
[] = {'a', 0};
2389 COORD origin
= {0, 0};
2396 HANDLE hConsoleOutput
;
2400 LPDWORD lpNumCharsWritten
;
2401 DWORD expected_count
;
2406 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2407 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2408 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2409 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2410 {NULL
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2411 {NULL
, output
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2412 {NULL
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2413 {NULL
, output
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2414 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2415 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2416 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2417 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2418 {INVALID_HANDLE_VALUE
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2419 {INVALID_HANDLE_VALUE
, output
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2420 {INVALID_HANDLE_VALUE
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2421 {INVALID_HANDLE_VALUE
, output
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2422 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2423 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2424 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2425 {output_handle
, output
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2426 {output_handle
, output
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2429 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2431 if (invalid_table
[i
].win7_crash
)
2434 SetLastError(0xdeadbeef);
2435 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2436 ret
= WriteConsoleOutputCharacterA(invalid_table
[i
].hConsoleOutput
,
2437 invalid_table
[i
].str
,
2438 invalid_table
[i
].length
,
2439 invalid_table
[i
].coord
,
2440 invalid_table
[i
].lpNumCharsWritten
);
2441 ok(!ret
, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i
, ret
);
2442 ok(GetLastError() == invalid_table
[i
].last_error
,
2443 "[%d] Expected last error to be %lu, got %lu\n",
2444 i
, invalid_table
[i
].last_error
, GetLastError());
2448 ret
= WriteConsoleOutputCharacterA(output_handle
, NULL
, 0, origin
, &count
);
2449 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2450 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2453 ret
= WriteConsoleOutputCharacterA(output_handle
, output
, 0, origin
, &count
);
2454 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2455 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2458 ret
= WriteConsoleOutputCharacterA(output_handle
, output
, 1, origin
, &count
);
2459 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2460 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2464 ret
= WriteConsoleOutputCharacterA(output_handle
, output
, 0, origin
, &count
);
2465 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2466 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2468 for (i
= 1; i
< 32; i
++)
2470 CONSOLE_SCREEN_BUFFER_INFO csbi
;
2474 ret
= WriteConsoleOutputCharacterA(output_handle
, &ch
, 1, c
, &count
);
2475 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2476 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2477 okCHAR(output_handle
, c
, (char)i
, 7);
2478 ret
= GetConsoleScreenBufferInfo(output_handle
, &csbi
);
2482 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle
)
2484 static const WCHAR outputW
[] = {'a',0};
2486 COORD origin
= {0, 0};
2493 HANDLE hConsoleOutput
;
2497 LPDWORD lpNumCharsWritten
;
2498 DWORD expected_count
;
2503 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2504 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2505 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2506 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2507 {NULL
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2508 {NULL
, outputW
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2509 {NULL
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2510 {NULL
, outputW
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2511 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2512 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2513 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2514 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2515 {INVALID_HANDLE_VALUE
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2516 {INVALID_HANDLE_VALUE
, outputW
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2517 {INVALID_HANDLE_VALUE
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2518 {INVALID_HANDLE_VALUE
, outputW
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2519 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2520 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2521 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2522 {output_handle
, outputW
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2523 {output_handle
, outputW
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2526 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2528 if (invalid_table
[i
].win7_crash
)
2531 SetLastError(0xdeadbeef);
2532 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2533 ret
= WriteConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
2534 invalid_table
[i
].str
,
2535 invalid_table
[i
].length
,
2536 invalid_table
[i
].coord
,
2537 invalid_table
[i
].lpNumCharsWritten
);
2538 ok(!ret
, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
2539 ok(GetLastError() == invalid_table
[i
].last_error
,
2540 "[%d] Expected last error to be %lu, got %lu\n",
2541 i
, invalid_table
[i
].last_error
, GetLastError());
2545 ret
= WriteConsoleOutputCharacterW(output_handle
, NULL
, 0, origin
, &count
);
2546 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2547 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2550 ret
= WriteConsoleOutputCharacterW(output_handle
, outputW
, 0, origin
, &count
);
2551 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2552 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2555 ret
= WriteConsoleOutputCharacterW(output_handle
, outputW
, 1, origin
, &count
);
2556 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2557 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2561 ret
= WriteConsoleOutputCharacterW(output_handle
, outputW
, 0, origin
, &count
);
2562 ok(ret
== TRUE
, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2563 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2567 static void test_WriteConsoleOutputAttribute(HANDLE output_handle
)
2569 WORD attr
= FOREGROUND_BLUE
;
2570 COORD origin
= {0, 0};
2577 HANDLE hConsoleOutput
;
2581 LPDWORD lpNumAttrsWritten
;
2582 DWORD expected_count
;
2587 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2588 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2589 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2590 {NULL
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2591 {NULL
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2592 {NULL
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2593 {NULL
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2594 {NULL
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2595 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2596 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2597 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2598 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2599 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2600 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2601 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2602 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2603 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2604 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2605 {output_handle
, NULL
, 1, {0, 0}, &count
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2606 {output_handle
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2607 {output_handle
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2610 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2612 if (invalid_table
[i
].win7_crash
)
2615 SetLastError(0xdeadbeef);
2616 if (invalid_table
[i
].lpNumAttrsWritten
) count
= 0xdeadbeef;
2617 ret
= WriteConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
2618 invalid_table
[i
].attr
,
2619 invalid_table
[i
].length
,
2620 invalid_table
[i
].coord
,
2621 invalid_table
[i
].lpNumAttrsWritten
);
2622 ok(!ret
, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
2623 ok(GetLastError() == invalid_table
[i
].last_error
,
2624 "[%d] Expected last error to be %lu, got %lu\n",
2625 i
, invalid_table
[i
].last_error
, GetLastError());
2629 ret
= WriteConsoleOutputAttribute(output_handle
, NULL
, 0, origin
, &count
);
2630 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2631 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2634 ret
= WriteConsoleOutputAttribute(output_handle
, &attr
, 0, origin
, &count
);
2635 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2636 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2639 ret
= WriteConsoleOutputAttribute(output_handle
, &attr
, 1, origin
, &count
);
2640 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2641 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2645 ret
= WriteConsoleOutputAttribute(output_handle
, &attr
, 0, origin
, &count
);
2646 ok(ret
== TRUE
, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2647 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2650 static void set_region(SMALL_RECT
*region
, unsigned int left
, unsigned int top
, unsigned int right
, unsigned int bottom
)
2652 region
->Left
= left
;
2654 region
->Right
= right
;
2655 region
->Bottom
= bottom
;
2658 #define check_region(a,b,c,d,e) check_region_(__LINE__,a,b,c,d,e)
2659 static void check_region_(unsigned int line
, const SMALL_RECT
*region
, unsigned int left
, unsigned int top
, int right
, int bottom
)
2661 ok_(__FILE__
,line
)(region
->Left
== left
, "Left = %u, expected %u\n", region
->Left
, left
);
2662 ok_(__FILE__
,line
)(region
->Top
== top
, "Top = %u, expected %u\n", region
->Top
, top
);
2663 /* In multiple places returned region depends on Windows versions: some return right < left, others leave it untouched */
2665 ok_(__FILE__
,line
)(region
->Right
== right
, "Right = %u, expected %u\n", region
->Right
, right
);
2667 ok_(__FILE__
,line
)(region
->Right
== -right
|| region
->Right
== region
->Left
- 1,
2668 "Right = %u, expected %d\n", region
->Right
, right
);
2670 ok_(__FILE__
,line
)(region
->Bottom
== bottom
, "Bottom = %u, expected %u\n", region
->Bottom
, bottom
);
2671 else if (bottom
< 0)
2672 ok_(__FILE__
,line
)(region
->Bottom
== -bottom
|| region
->Bottom
== region
->Top
- 1,
2673 "Bottom = %u, expected %d\n", region
->Bottom
, bottom
);
2676 static void test_WriteConsoleOutput(HANDLE console
)
2678 CONSOLE_SCREEN_BUFFER_INFO info
;
2679 CHAR_INFO char_info_buf
[2048];
2685 for (i
= 0; i
< ARRAY_SIZE(char_info_buf
); i
++)
2687 char_info_buf
[i
].Char
.UnicodeChar
= '0' + i
% 10;
2688 char_info_buf
[i
].Attributes
= 0;
2691 ret
= GetConsoleScreenBufferInfo(console
, &info
);
2692 ok(ret
, "GetConsoleScreenBufferInfo failed: %lu\n", GetLastError());
2698 set_region(®ion
, 10, 7, 15, 11);
2699 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2700 ok(ret
, "WriteConsoleOutputW failed: %lu\n", GetLastError());
2701 check_region(®ion
, 10, 7, 15, 11);
2707 set_region(®ion
, 200, 7, 15, 211);
2708 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2709 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
2710 check_region(®ion
, 200, 7, 15, 211);
2716 set_region(®ion
, 200, 7, 211, 8);
2717 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2718 ok(ret
, "WriteConsoleOutputW failed: %lu\n", GetLastError());
2719 check_region(®ion
, 200, 7, 211, 8);
2725 set_region(®ion
, 10, 7, 9, 11);
2726 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2727 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
2728 check_region(®ion
, 10, 7, 9, 11);
2734 set_region(®ion
, 10, 7, 11, 6);
2735 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2736 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
2737 check_region(®ion
, 10, 7, 11, 6);
2743 set_region(®ion
, 10, 7, 15, 11);
2744 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2745 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
2746 check_region(®ion
, 10, 7, 15, 11);
2752 set_region(®ion
, 10, 7, 15, 11);
2753 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2754 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "WriteConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
2755 check_region(®ion
, 10, 7, 15, 11);
2761 set_region(®ion
, 10, 7, 15, 11);
2762 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2763 ok(ret
, "WriteConsoleOutputW failed: %lu\n", GetLastError());
2764 check_region(®ion
, 10, 7, 13, 11);
2770 set_region(®ion
, 10, 7, 15, 11);
2771 ret
= WriteConsoleOutputW((HANDLE
)0xdeadbeef, char_info_buf
, size
, coord
, ®ion
);
2772 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "WriteConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
2773 if (!skip_nt
) check_region(®ion
, 10, 7, 13, 11);
2779 set_region(®ion
, 10, 7, 15, 11);
2780 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2781 ok(ret
, "WriteConsoleOutputW failed: %lu\n", GetLastError());
2782 check_region(®ion
, 10, 7, 15, 10);
2788 set_region(®ion
, info
.dwSize
.X
- 2, 7, info
.dwSize
.X
+ 2, 7);
2789 ret
= WriteConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
2790 ok(ret
, "WriteConsoleOutputW failed: %lu\n", GetLastError());
2791 check_region(®ion
, info
.dwSize
.X
- 2, 7, info
.dwSize
.X
- 1, 7);
2794 static void test_FillConsoleOutputCharacterA(HANDLE output_handle
)
2796 COORD origin
= {0, 0};
2803 HANDLE hConsoleOutput
;
2807 LPDWORD lpNumCharsWritten
;
2812 {NULL
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2813 {NULL
, 'a', 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2814 {NULL
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2815 {NULL
, 'a', 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2816 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2817 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2818 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2819 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2820 {output_handle
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2821 {output_handle
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2824 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2826 if (invalid_table
[i
].win7_crash
)
2829 SetLastError(0xdeadbeef);
2830 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2831 ret
= FillConsoleOutputCharacterA(invalid_table
[i
].hConsoleOutput
,
2832 invalid_table
[i
].ch
,
2833 invalid_table
[i
].length
,
2834 invalid_table
[i
].coord
,
2835 invalid_table
[i
].lpNumCharsWritten
);
2836 ok(!ret
, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i
, ret
);
2837 ok(GetLastError() == invalid_table
[i
].last_error
,
2838 "[%d] Expected last error to be %lu, got %lu\n",
2839 i
, invalid_table
[i
].last_error
, GetLastError());
2843 ret
= FillConsoleOutputCharacterA(output_handle
, 'a', 0, origin
, &count
);
2844 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2845 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2848 ret
= FillConsoleOutputCharacterA(output_handle
, 'a', 1, origin
, &count
);
2849 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
2850 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2853 static void test_FillConsoleOutputCharacterW(HANDLE output_handle
)
2855 COORD origin
= {0, 0};
2862 HANDLE hConsoleOutput
;
2866 LPDWORD lpNumCharsWritten
;
2871 {NULL
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2872 {NULL
, 'a', 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2873 {NULL
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2874 {NULL
, 'a', 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2875 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2876 {INVALID_HANDLE_VALUE
, 'a', 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2877 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2878 {INVALID_HANDLE_VALUE
, 'a', 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2879 {output_handle
, 'a', 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2880 {output_handle
, 'a', 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2883 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2885 if (invalid_table
[i
].win7_crash
)
2888 SetLastError(0xdeadbeef);
2889 if (invalid_table
[i
].lpNumCharsWritten
) count
= 0xdeadbeef;
2890 ret
= FillConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
2891 invalid_table
[i
].ch
,
2892 invalid_table
[i
].length
,
2893 invalid_table
[i
].coord
,
2894 invalid_table
[i
].lpNumCharsWritten
);
2895 ok(!ret
, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
2896 ok(GetLastError() == invalid_table
[i
].last_error
,
2897 "[%d] Expected last error to be %lu, got %lu\n",
2898 i
, invalid_table
[i
].last_error
, GetLastError());
2902 ret
= FillConsoleOutputCharacterW(output_handle
, 'a', 0, origin
, &count
);
2903 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2904 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2907 ret
= FillConsoleOutputCharacterW(output_handle
, 'a', 1, origin
, &count
);
2908 ok(ret
== TRUE
, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
2909 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2912 static void test_FillConsoleOutputAttribute(HANDLE output_handle
)
2914 COORD origin
= {0, 0};
2921 HANDLE hConsoleOutput
;
2925 LPDWORD lpNumAttrsWritten
;
2930 {NULL
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2931 {NULL
, FOREGROUND_BLUE
, 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2932 {NULL
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2933 {NULL
, FOREGROUND_BLUE
, 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2934 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2935 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 0, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2936 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2937 {INVALID_HANDLE_VALUE
, FOREGROUND_BLUE
, 1, {0, 0}, &count
, ERROR_INVALID_HANDLE
},
2938 {output_handle
, FOREGROUND_BLUE
, 0, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2939 {output_handle
, FOREGROUND_BLUE
, 1, {0, 0}, NULL
, ERROR_INVALID_ACCESS
, 1},
2942 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
2944 if (invalid_table
[i
].win7_crash
)
2947 SetLastError(0xdeadbeef);
2948 if (invalid_table
[i
].lpNumAttrsWritten
) count
= 0xdeadbeef;
2949 ret
= FillConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
2950 invalid_table
[i
].attr
,
2951 invalid_table
[i
].length
,
2952 invalid_table
[i
].coord
,
2953 invalid_table
[i
].lpNumAttrsWritten
);
2954 ok(!ret
, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
2955 ok(GetLastError() == invalid_table
[i
].last_error
,
2956 "[%d] Expected last error to be %lu, got %lu\n",
2957 i
, invalid_table
[i
].last_error
, GetLastError());
2961 ret
= FillConsoleOutputAttribute(output_handle
, FOREGROUND_BLUE
, 0, origin
, &count
);
2962 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2963 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
2966 ret
= FillConsoleOutputAttribute(output_handle
, FOREGROUND_BLUE
, 1, origin
, &count
);
2967 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2968 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2971 ret
= FillConsoleOutputAttribute(output_handle
, ~0, 1, origin
, &count
);
2972 ok(ret
== TRUE
, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret
);
2973 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
2976 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle
)
2979 COORD origin
= {0, 0};
2986 HANDLE hConsoleOutput
;
2991 DWORD expected_count
;
2996 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2997 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
2998 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
2999 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
3000 {NULL
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3001 {NULL
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3002 {NULL
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3003 {NULL
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3004 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3005 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3006 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3007 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
3008 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3009 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3010 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3011 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3012 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3013 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3014 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
3015 {output_handle
, NULL
, 10, {0, 0}, &count
, 10, ERROR_INVALID_ACCESS
, 1},
3016 {output_handle
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3017 {output_handle
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3020 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
3022 if (invalid_table
[i
].win7_crash
)
3025 SetLastError(0xdeadbeef);
3026 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
3027 ret
= ReadConsoleOutputCharacterA(invalid_table
[i
].hConsoleOutput
,
3028 invalid_table
[i
].lpstr
,
3029 invalid_table
[i
].length
,
3030 invalid_table
[i
].coord
,
3031 invalid_table
[i
].read_count
);
3032 ok(!ret
, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i
, ret
);
3033 ok(GetLastError() == invalid_table
[i
].last_error
,
3034 "[%d] Expected last error to be %lu, got %lu\n",
3035 i
, invalid_table
[i
].last_error
, GetLastError());
3039 ret
= ReadConsoleOutputCharacterA(output_handle
, NULL
, 0, origin
, &count
);
3040 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
3041 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
3044 ret
= ReadConsoleOutputCharacterA(output_handle
, &read
, 0, origin
, &count
);
3045 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
3046 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
3049 ret
= ReadConsoleOutputCharacterA(output_handle
, &read
, 1, origin
, &count
);
3050 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
3051 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
3055 ret
= ReadConsoleOutputCharacterA(output_handle
, &read
, 1, origin
, &count
);
3056 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret
);
3057 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
3060 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle
)
3063 COORD origin
= {0, 0};
3070 HANDLE hConsoleOutput
;
3075 DWORD expected_count
;
3080 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3081 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3082 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3083 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
3084 {NULL
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3085 {NULL
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3086 {NULL
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3087 {NULL
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3088 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3089 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3090 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3091 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
3092 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3093 {INVALID_HANDLE_VALUE
, &read
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3094 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3095 {INVALID_HANDLE_VALUE
, &read
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3096 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3097 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3098 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
3099 {output_handle
, NULL
, 10, {0, 0}, &count
, 10, ERROR_INVALID_ACCESS
, 1},
3100 {output_handle
, &read
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3101 {output_handle
, &read
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3104 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
3106 if (invalid_table
[i
].win7_crash
)
3109 SetLastError(0xdeadbeef);
3110 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
3111 ret
= ReadConsoleOutputCharacterW(invalid_table
[i
].hConsoleOutput
,
3112 invalid_table
[i
].buffer
,
3113 invalid_table
[i
].length
,
3114 invalid_table
[i
].coord
,
3115 invalid_table
[i
].read_count
);
3116 ok(!ret
, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i
, ret
);
3117 ok(GetLastError() == invalid_table
[i
].last_error
,
3118 "[%d] Expected last error to be %lu, got %lu\n",
3119 i
, invalid_table
[i
].last_error
, GetLastError());
3123 ret
= ReadConsoleOutputCharacterW(output_handle
, NULL
, 0, origin
, &count
);
3124 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
3125 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
3128 ret
= ReadConsoleOutputCharacterW(output_handle
, &read
, 0, origin
, &count
);
3129 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
3130 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
3133 ret
= ReadConsoleOutputCharacterW(output_handle
, &read
, 1, origin
, &count
);
3134 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
3135 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
3139 ret
= ReadConsoleOutputCharacterW(output_handle
, &read
, 1, origin
, &count
);
3140 ok(ret
== TRUE
, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret
);
3141 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
3144 static void test_ReadConsoleOutputAttribute(HANDLE output_handle
)
3147 COORD origin
= {0, 0};
3154 HANDLE hConsoleOutput
;
3159 DWORD expected_count
;
3164 {NULL
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3165 {NULL
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3166 {NULL
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3167 {NULL
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
3168 {NULL
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3169 {NULL
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3170 {NULL
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3171 {NULL
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3172 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3173 {INVALID_HANDLE_VALUE
, NULL
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3174 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3175 {INVALID_HANDLE_VALUE
, NULL
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
, 1},
3176 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3177 {INVALID_HANDLE_VALUE
, &attr
, 0, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3178 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3179 {INVALID_HANDLE_VALUE
, &attr
, 1, {0, 0}, &count
, 0, ERROR_INVALID_HANDLE
},
3180 {output_handle
, NULL
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3181 {output_handle
, NULL
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3182 {output_handle
, NULL
, 1, {0, 0}, &count
, 1, ERROR_INVALID_ACCESS
, 1},
3183 {output_handle
, &attr
, 0, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3184 {output_handle
, &attr
, 1, {0, 0}, NULL
, 0xdeadbeef, ERROR_INVALID_ACCESS
, 1},
3187 for (i
= 0; i
< ARRAY_SIZE(invalid_table
); i
++)
3189 if (invalid_table
[i
].win7_crash
)
3192 SetLastError(0xdeadbeef);
3193 if (invalid_table
[i
].read_count
) count
= 0xdeadbeef;
3194 ret
= ReadConsoleOutputAttribute(invalid_table
[i
].hConsoleOutput
,
3195 invalid_table
[i
].lpAttribute
,
3196 invalid_table
[i
].length
,
3197 invalid_table
[i
].coord
,
3198 invalid_table
[i
].read_count
);
3199 ok(!ret
, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i
, ret
);
3200 ok(GetLastError() == invalid_table
[i
].last_error
,
3201 "[%d] Expected last error to be %lu, got %lu\n",
3202 i
, invalid_table
[i
].last_error
, GetLastError());
3206 ret
= ReadConsoleOutputAttribute(output_handle
, NULL
, 0, origin
, &count
);
3207 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
3208 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
3211 ret
= ReadConsoleOutputAttribute(output_handle
, &attr
, 0, origin
, &count
);
3212 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
3213 ok(count
== 0, "Expected count to be 0, got %lu\n", count
);
3216 ret
= ReadConsoleOutputAttribute(output_handle
, &attr
, 1, origin
, &count
);
3217 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
3218 ok(count
== 1, "Expected count to be 1, got %lu\n", count
);
3222 ret
= ReadConsoleOutputAttribute(output_handle
, &attr
, 1, origin
, &count
);
3223 ok(ret
== TRUE
, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret
);
3224 ok(count
== 0, "Expected count to be 1, got %lu\n", count
);
3227 static void test_ReadConsoleOutput(HANDLE console
)
3229 CONSOLE_SCREEN_BUFFER_INFO info
;
3230 CHAR_INFO char_info_buf
[2048];
3237 if (skip_nt
) return;
3239 ret
= GetConsoleScreenBufferInfo(console
, &info
);
3240 ok(ret
, "GetConsoleScreenBufferInfo failed: %lu\n", GetLastError());
3246 set_region(®ion
, 10, 7, 15, 11);
3247 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3248 ok(ret
, "ReadConsoleOutputW failed: %lu\n", GetLastError());
3249 check_region(®ion
, 10, 7, 15, 11);
3255 set_region(®ion
, 200, 7, 15, 211);
3256 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3257 ok(!ret
, "ReadConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
3258 check_region(®ion
, 200, 7, -15, 0);
3264 set_region(®ion
, 200, 7, 211, 8);
3265 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3266 ok((!ret
&& (GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_INVALID_FUNCTION
)) || broken(ret
/* win8 */),
3267 "ReadConsoleOutputW returned: %x %lu\n", ret
, GetLastError());
3268 if (!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
) check_region(®ion
, 200, 7, -211, -8);
3274 set_region(®ion
, 10, 7, 9, 11);
3275 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3276 ok((!ret
&& (GetLastError() == ERROR_INVALID_FUNCTION
|| GetLastError() == ERROR_NOT_ENOUGH_MEMORY
)) || broken(ret
/* win8 */),
3277 "ReadConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
3278 check_region(®ion
, 10, 7, 9, -11);
3284 set_region(®ion
, 10, 7, 11, 6);
3285 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3286 ok((!ret
&& (GetLastError() == ERROR_INVALID_FUNCTION
|| GetLastError() == ERROR_NOT_ENOUGH_MEMORY
)) || broken(ret
/* win8 */),
3287 "ReadConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
3288 check_region(®ion
, 10, 7, -11, 6);
3294 set_region(®ion
, 10, 7, 15, 11);
3295 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3296 ok((!ret
&& (GetLastError() == ERROR_INVALID_FUNCTION
|| GetLastError() == ERROR_NOT_ENOUGH_MEMORY
)) || broken(ret
/* win8 */),
3297 "ReadConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
3298 check_region(®ion
, 10, 7, -15, -11);
3304 set_region(®ion
, 10, 7, 15, 11);
3305 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3306 ok((!ret
&& (GetLastError() == ERROR_INVALID_FUNCTION
|| GetLastError() == ERROR_NOT_ENOUGH_MEMORY
)) || broken(ret
/* win8 */),
3307 "ReadConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
3308 check_region(®ion
, 10, 7, -15, 6);
3314 set_region(®ion
, 10, 7, 15, 11);
3315 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3316 ok(ret
, "ReadConsoleOutputW failed: %lu\n", GetLastError());
3317 check_region(®ion
, 10, 7, 13, 11);
3323 set_region(®ion
, 10, 7, 15, 11);
3324 ret
= ReadConsoleOutputW((HANDLE
)0xdeadbeef, char_info_buf
, size
, coord
, ®ion
);
3325 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "ReadConsoleOutputW returned: %x(%lu)\n", ret
, GetLastError());
3326 if (!skip_nt
) check_region(®ion
, 10, 7, 13, 11);
3332 set_region(®ion
, 10, 7, 15, 11);
3333 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3334 ok(ret
, "ReadConsoleOutputW failed: %lu\n", GetLastError());
3335 check_region(®ion
, 10, 7, 15, 10);
3341 set_region(®ion
, info
.dwSize
.X
- 2, 7, info
.dwSize
.X
+ 2, 7);
3342 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3343 ok(ret
|| GetLastError() == ERROR_INVALID_PARAMETER
, "ReadConsoleOutputW failed: %lu\n", GetLastError());
3344 if (ret
) check_region(®ion
, info
.dwSize
.X
- 2, 7, info
.dwSize
.X
- 1, 7);
3348 ret
= WriteConsoleOutputCharacterW(console
, L
"xyz", 3, coord
, &count
);
3349 ok(ret
, "WriteConsoleOutputCharacterW failed: %lu\n", GetLastError());
3350 ok(count
== 3, "count = %lu\n", count
);
3352 memset(char_info_buf
, 0xc0, sizeof(char_info_buf
));
3357 set_region(®ion
, 2, 3, 5, 3);
3358 ret
= ReadConsoleOutputW(console
, char_info_buf
, size
, coord
, ®ion
);
3359 ok(ret
, "ReadConsoleOutputW failed: %lu\n", GetLastError());
3360 check_region(®ion
, 2, 3, 5, 3);
3361 ch
= char_info_buf
[coord
.Y
* size
.X
+ coord
.X
].Char
.UnicodeChar
;
3362 ok(ch
== 'x', "unexpected char %c/%x\n", ch
, ch
);
3363 ch
= char_info_buf
[coord
.Y
* size
.X
+ coord
.X
+ 1].Char
.UnicodeChar
;
3364 ok(ch
== 'y', "unexpected char %c/%x\n", ch
, ch
);
3365 ch
= char_info_buf
[coord
.Y
* size
.X
+ coord
.X
+ 2].Char
.UnicodeChar
;
3366 ok(ch
== 'z', "unexpected char %c/%x\n", ch
, ch
);
3369 static void test_ReadConsole(HANDLE input
)
3375 SetLastError(0xdeadbeef);
3376 ret
= GetFileSize(input
, NULL
);
3377 ok(ret
== INVALID_FILE_SIZE
|| broken(TRUE
), /* only Win7 pro64 on 64bit returns a valid file size here */
3378 "expected INVALID_FILE_SIZE, got %#lx\n", ret
);
3379 if (ret
== INVALID_FILE_SIZE
)
3380 ok(GetLastError() == ERROR_INVALID_HANDLE
||
3381 GetLastError() == ERROR_INVALID_FUNCTION
, /* Win 8, 10 */
3382 "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
3385 SetLastError(0xdeadbeef);
3386 ret
= ReadFile(input
, buf
, -128, &bytes
, NULL
);
3387 ok(!ret
, "expected 0, got %lu\n", ret
);
3388 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
||
3389 GetLastError() == ERROR_NOACCESS
, /* Win 8, 10 */
3390 "expected ERROR_NOT_ENOUGH_MEMORY, got %ld\n", GetLastError());
3391 ok(!bytes
, "expected 0, got %lu\n", bytes
);
3394 SetLastError(0xdeadbeef);
3395 ret
= ReadConsoleA(input
, buf
, -128, &bytes
, NULL
);
3396 ok(!ret
, "expected 0, got %lu\n", ret
);
3397 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
||
3398 GetLastError() == ERROR_NOACCESS
, /* Win 8, 10 */
3399 "expected ERROR_NOT_ENOUGH_MEMORY, got %ld\n", GetLastError());
3400 ok(bytes
== 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", bytes
);
3403 SetLastError(0xdeadbeef);
3404 ret
= ReadConsoleW(input
, buf
, -128, &bytes
, NULL
);
3405 ok(!ret
, "expected 0, got %lu\n", ret
);
3406 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
||
3407 GetLastError() == ERROR_NOACCESS
, /* Win 8, 10 */
3408 "expected ERROR_NOT_ENOUGH_MEMORY, got %ld\n", GetLastError());
3409 ok(bytes
== 0xdeadbeef, "expected 0xdeadbeef, got %#lx\n", bytes
);
3411 output
= CreateFileA("CONOUT$", GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
3412 ok(output
!= INVALID_HANDLE_VALUE
, "Could not open console\n");
3414 ret
= ReadConsoleW(output
, buf
, sizeof(buf
) / sizeof(WCHAR
), &bytes
, NULL
);
3415 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3416 "ReadConsoleW returned %lx(%lu)\n", ret
, GetLastError());
3418 ret
= ReadConsoleA(output
, buf
, sizeof(buf
), &bytes
, NULL
);
3419 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3420 "ReadConsoleA returned %lx(%lu)\n", ret
, GetLastError());
3422 ret
= ReadFile(output
, buf
, sizeof(buf
), &bytes
, NULL
);
3423 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
3424 "ReadFile returned %lx(%lu)\n", ret
, GetLastError());
3426 CloseHandle(output
);
3429 static void test_GetCurrentConsoleFont(HANDLE std_output
)
3432 CONSOLE_FONT_INFO cfi
;
3433 CONSOLE_SCREEN_BUFFER_INFO csbi
;
3434 short int width
, height
;
3435 HANDLE pipe1
, pipe2
;
3438 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3439 SetLastError(0xdeadbeef);
3440 ret
= GetCurrentConsoleFont(NULL
, FALSE
, &cfi
);
3441 ok(!ret
, "got %d, expected 0\n", ret
);
3442 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3443 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3444 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3446 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3447 SetLastError(0xdeadbeef);
3448 ret
= GetCurrentConsoleFont(NULL
, TRUE
, &cfi
);
3449 ok(!ret
, "got %d, expected 0\n", ret
);
3450 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3451 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3452 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3454 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3455 SetLastError(0xdeadbeef);
3456 ret
= GetCurrentConsoleFont(GetStdHandle(STD_INPUT_HANDLE
), FALSE
, &cfi
);
3457 ok(!ret
, "got %d, expected 0\n", ret
);
3458 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3459 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3460 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3462 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3463 SetLastError(0xdeadbeef);
3464 ret
= GetCurrentConsoleFont(GetStdHandle(STD_INPUT_HANDLE
), TRUE
, &cfi
);
3465 ok(!ret
, "got %d, expected 0\n", ret
);
3466 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3467 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3468 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3470 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3471 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3472 SetLastError(0xdeadbeef);
3473 ret
= GetCurrentConsoleFont(pipe1
, TRUE
, &cfi
);
3474 ok(!ret
, "got %d, expected 0\n", ret
);
3475 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3476 ok(!cfi
.dwFontSize
.X
, "got %d, expected 0\n", cfi
.dwFontSize
.X
);
3477 ok(!cfi
.dwFontSize
.Y
, "got %d, expected 0\n", cfi
.dwFontSize
.Y
);
3481 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3482 SetLastError(0xdeadbeef);
3483 ret
= GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3484 ok(ret
, "got %d, expected non-zero\n", ret
);
3485 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3486 GetConsoleScreenBufferInfo(std_output
, &csbi
);
3487 width
= csbi
.srWindow
.Right
- csbi
.srWindow
.Left
+ 1;
3488 height
= csbi
.srWindow
.Bottom
- csbi
.srWindow
.Top
+ 1;
3489 c
= GetConsoleFontSize(std_output
, cfi
.nFont
);
3490 ok(cfi
.dwFontSize
.X
== width
|| cfi
.dwFontSize
.X
== c
.X
/* Vista and higher */,
3491 "got %d, expected %d\n", cfi
.dwFontSize
.X
, width
);
3492 ok(cfi
.dwFontSize
.Y
== height
|| cfi
.dwFontSize
.Y
== c
.Y
/* Vista and higher */,
3493 "got %d, expected %d\n", cfi
.dwFontSize
.Y
, height
);
3495 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3496 SetLastError(0xdeadbeef);
3497 ret
= GetCurrentConsoleFont(std_output
, TRUE
, &cfi
);
3498 ok(ret
, "got %d, expected non-zero\n", ret
);
3499 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3500 ok(cfi
.dwFontSize
.X
== csbi
.dwMaximumWindowSize
.X
,
3501 "got %d, expected %d\n", cfi
.dwFontSize
.X
, csbi
.dwMaximumWindowSize
.X
);
3502 ok(cfi
.dwFontSize
.Y
== csbi
.dwMaximumWindowSize
.Y
,
3503 "got %d, expected %d\n", cfi
.dwFontSize
.Y
, csbi
.dwMaximumWindowSize
.Y
);
3506 static void test_GetCurrentConsoleFontEx(HANDLE std_output
)
3509 BOOL (WINAPI
*pGetCurrentConsoleFontEx
)(HANDLE
, BOOL
, CONSOLE_FONT_INFOEX
*);
3510 CONSOLE_FONT_INFO cfi
;
3511 CONSOLE_FONT_INFOEX cfix
;
3513 HANDLE std_input
= GetStdHandle(STD_INPUT_HANDLE
);
3514 HANDLE pipe1
, pipe2
;
3517 hmod
= GetModuleHandleA("kernel32.dll");
3518 pGetCurrentConsoleFontEx
= (void *)GetProcAddress(hmod
, "GetCurrentConsoleFontEx");
3519 if (!pGetCurrentConsoleFontEx
)
3521 win_skip("GetCurrentConsoleFontEx is not available\n");
3525 SetLastError(0xdeadbeef);
3526 ret
= pGetCurrentConsoleFontEx(NULL
, FALSE
, &cfix
);
3527 ok(!ret
, "got %d, expected 0\n", ret
);
3528 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3530 SetLastError(0xdeadbeef);
3531 ret
= pGetCurrentConsoleFontEx(NULL
, TRUE
, &cfix
);
3532 ok(!ret
, "got %d, expected 0\n", ret
);
3533 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3535 SetLastError(0xdeadbeef);
3536 ret
= pGetCurrentConsoleFontEx(std_input
, FALSE
, &cfix
);
3537 ok(!ret
, "got %d, expected 0\n", ret
);
3538 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3540 SetLastError(0xdeadbeef);
3541 ret
= pGetCurrentConsoleFontEx(std_input
, TRUE
, &cfix
);
3542 ok(!ret
, "got %d, expected 0\n", ret
);
3543 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3545 SetLastError(0xdeadbeef);
3546 ret
= pGetCurrentConsoleFontEx(std_output
, FALSE
, &cfix
);
3547 ok(!ret
, "got %d, expected 0\n", ret
);
3548 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3550 SetLastError(0xdeadbeef);
3551 ret
= pGetCurrentConsoleFontEx(std_output
, TRUE
, &cfix
);
3552 ok(!ret
, "got %d, expected 0\n", ret
);
3553 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3555 cfix
.cbSize
= sizeof(CONSOLE_FONT_INFOEX
);
3557 SetLastError(0xdeadbeef);
3558 ret
= pGetCurrentConsoleFontEx(NULL
, FALSE
, &cfix
);
3559 ok(!ret
, "got %d, expected 0\n", ret
);
3560 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3562 SetLastError(0xdeadbeef);
3563 ret
= pGetCurrentConsoleFontEx(NULL
, TRUE
, &cfix
);
3564 ok(!ret
, "got %d, expected 0\n", ret
);
3565 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3567 SetLastError(0xdeadbeef);
3568 ret
= pGetCurrentConsoleFontEx(std_input
, FALSE
, &cfix
);
3569 ok(!ret
, "got %d, expected 0\n", ret
);
3570 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3572 SetLastError(0xdeadbeef);
3573 ret
= pGetCurrentConsoleFontEx(std_input
, TRUE
, &cfix
);
3574 ok(!ret
, "got %d, expected 0\n", ret
);
3575 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3577 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3578 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3579 SetLastError(0xdeadbeef);
3580 ret
= pGetCurrentConsoleFontEx(pipe1
, TRUE
, &cfix
);
3581 ok(!ret
, "got %d, expected 0\n", ret
);
3582 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3586 SetLastError(0xdeadbeef);
3587 ret
= pGetCurrentConsoleFontEx(std_output
, FALSE
, &cfix
);
3588 ok(ret
, "got %d, expected non-zero\n", ret
);
3589 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3591 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3592 SetLastError(0xdeadbeef);
3593 ret
= GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3594 ok(ret
, "got %d, expected non-zero\n", ret
);
3595 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3597 ok(cfix
.dwFontSize
.X
== cfi
.dwFontSize
.X
, "expected values to match\n");
3598 ok(cfix
.dwFontSize
.Y
== cfi
.dwFontSize
.Y
, "expected values to match\n");
3600 SetLastError(0xdeadbeef);
3601 c
= GetConsoleFontSize(std_output
, cfix
.nFont
);
3602 ok(c
.X
&& c
.Y
, "GetConsoleFontSize failed; err = %lu\n", GetLastError());
3603 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3605 ok(cfix
.dwFontSize
.X
== c
.X
, "Font width doesn't match; got %u, expected %u\n",
3606 cfix
.dwFontSize
.X
, c
.X
);
3607 ok(cfix
.dwFontSize
.Y
== c
.Y
, "Font height doesn't match; got %u, expected %u\n",
3608 cfix
.dwFontSize
.Y
, c
.Y
);
3610 ok(cfi
.dwFontSize
.X
== c
.X
, "Font width doesn't match; got %u, expected %u\n",
3611 cfi
.dwFontSize
.X
, c
.X
);
3612 ok(cfi
.dwFontSize
.Y
== c
.Y
, "Font height doesn't match; got %u, expected %u\n",
3613 cfi
.dwFontSize
.Y
, c
.Y
);
3615 SetLastError(0xdeadbeef);
3616 ret
= pGetCurrentConsoleFontEx(std_output
, TRUE
, &cfix
);
3617 ok(ret
, "got %d, expected non-zero\n", ret
);
3618 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3620 memset(&cfi
, 0, sizeof(CONSOLE_FONT_INFO
));
3621 SetLastError(0xdeadbeef);
3622 ret
= GetCurrentConsoleFont(std_output
, TRUE
, &cfi
);
3623 ok(ret
, "got %d, expected non-zero\n", ret
);
3624 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3626 ok(cfix
.dwFontSize
.X
== cfi
.dwFontSize
.X
, "expected values to match\n");
3627 ok(cfix
.dwFontSize
.Y
== cfi
.dwFontSize
.Y
, "expected values to match\n");
3630 static void test_SetCurrentConsoleFontEx(HANDLE std_output
)
3632 CONSOLE_FONT_INFOEX orig_cfix
, cfix
;
3634 HANDLE pipe1
, pipe2
;
3635 HANDLE std_input
= GetStdHandle(STD_INPUT_HANDLE
);
3637 orig_cfix
.cbSize
= sizeof(CONSOLE_FONT_INFOEX
);
3639 ret
= GetCurrentConsoleFontEx(std_output
, FALSE
, &orig_cfix
);
3640 ok(ret
, "got %d, expected non-zero\n", ret
);
3645 SetLastError(0xdeadbeef);
3646 ret
= SetCurrentConsoleFontEx(NULL
, FALSE
, &cfix
);
3647 ok(!ret
, "got %d, expected 0\n", ret
);
3648 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3650 SetLastError(0xdeadbeef);
3651 ret
= SetCurrentConsoleFontEx(NULL
, TRUE
, &cfix
);
3652 ok(!ret
, "got %d, expected 0\n", ret
);
3653 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3655 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3656 SetLastError(0xdeadbeef);
3657 ret
= SetCurrentConsoleFontEx(pipe1
, FALSE
, &cfix
);
3658 ok(!ret
, "got %d, expected 0\n", ret
);
3659 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3663 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3664 SetLastError(0xdeadbeef);
3665 ret
= SetCurrentConsoleFontEx(pipe1
, TRUE
, &cfix
);
3666 ok(!ret
, "got %d, expected 0\n", ret
);
3667 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3671 SetLastError(0xdeadbeef);
3672 ret
= SetCurrentConsoleFontEx(std_input
, FALSE
, &cfix
);
3673 ok(!ret
, "got %d, expected 0\n", ret
);
3674 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3676 SetLastError(0xdeadbeef);
3677 ret
= SetCurrentConsoleFontEx(std_input
, TRUE
, &cfix
);
3678 ok(!ret
, "got %d, expected 0\n", ret
);
3679 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3681 SetLastError(0xdeadbeef);
3682 ret
= SetCurrentConsoleFontEx(std_output
, FALSE
, &cfix
);
3683 ok(!ret
, "got %d, expected 0\n", ret
);
3684 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3686 SetLastError(0xdeadbeef);
3687 ret
= SetCurrentConsoleFontEx(std_output
, TRUE
, &cfix
);
3688 ok(!ret
, "got %d, expected 0\n", ret
);
3689 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
3693 SetLastError(0xdeadbeef);
3694 ret
= SetCurrentConsoleFontEx(NULL
, FALSE
, &cfix
);
3695 ok(!ret
, "got %d, expected 0\n", ret
);
3696 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3698 SetLastError(0xdeadbeef);
3699 ret
= SetCurrentConsoleFontEx(NULL
, TRUE
, &cfix
);
3700 ok(!ret
, "got %d, expected 0\n", ret
);
3701 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3703 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3704 SetLastError(0xdeadbeef);
3705 ret
= SetCurrentConsoleFontEx(pipe1
, FALSE
, &cfix
);
3706 ok(!ret
, "got %d, expected 0\n", ret
);
3707 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3711 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3712 SetLastError(0xdeadbeef);
3713 ret
= SetCurrentConsoleFontEx(pipe1
, TRUE
, &cfix
);
3714 ok(!ret
, "got %d, expected 0\n", ret
);
3715 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3719 SetLastError(0xdeadbeef);
3720 ret
= SetCurrentConsoleFontEx(std_input
, FALSE
, &cfix
);
3721 ok(!ret
, "got %d, expected 0\n", ret
);
3722 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3724 SetLastError(0xdeadbeef);
3725 ret
= SetCurrentConsoleFontEx(std_input
, TRUE
, &cfix
);
3726 ok(!ret
, "got %d, expected 0\n", ret
);
3727 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3729 SetLastError(0xdeadbeef);
3730 ret
= SetCurrentConsoleFontEx(std_output
, FALSE
, &cfix
);
3731 ok(ret
, "got %d, expected non-zero\n", ret
);
3732 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3734 SetLastError(0xdeadbeef);
3735 ret
= SetCurrentConsoleFontEx(std_output
, TRUE
, &cfix
);
3736 ok(ret
, "got %d, expected non-zero\n", ret
);
3737 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3739 /* Restore original console font parameters */
3740 SetLastError(0xdeadbeef);
3741 ret
= SetCurrentConsoleFontEx(std_output
, FALSE
, &orig_cfix
);
3742 ok(ret
, "got %d, expected non-zero\n", ret
);
3743 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3746 static void test_GetConsoleFontSize(HANDLE std_output
)
3750 CONSOLE_FONT_INFO cfi
;
3752 CONSOLE_SCREEN_BUFFER_INFO csbi
;
3753 LONG font_width
, font_height
;
3755 DWORD (WINAPI
*pGetNumberOfConsoleFonts
)(void);
3756 HANDLE pipe1
, pipe2
;
3758 memset(&c
, 10, sizeof(COORD
));
3759 SetLastError(0xdeadbeef);
3760 c
= GetConsoleFontSize(NULL
, index
);
3761 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3762 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3763 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3765 memset(&c
, 10, sizeof(COORD
));
3766 SetLastError(0xdeadbeef);
3767 c
= GetConsoleFontSize(GetStdHandle(STD_INPUT_HANDLE
), index
);
3768 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3769 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3770 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3772 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3773 memset(&c
, 10, sizeof(COORD
));
3774 SetLastError(0xdeadbeef);
3775 c
= GetConsoleFontSize(pipe1
, index
);
3776 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3777 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3778 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3782 GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3783 memset(&c
, 10, sizeof(COORD
));
3784 SetLastError(0xdeadbeef);
3785 c
= GetConsoleFontSize(std_output
, cfi
.nFont
);
3786 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3787 GetClientRect(GetConsoleWindow(), &r
);
3788 GetConsoleScreenBufferInfo(std_output
, &csbi
);
3789 font_width
= (r
.right
- r
.left
) / (csbi
.srWindow
.Right
- csbi
.srWindow
.Left
+ 1);
3790 font_height
= (r
.bottom
- r
.top
) / (csbi
.srWindow
.Bottom
- csbi
.srWindow
.Top
+ 1);
3791 ok(c
.X
== font_width
, "got %d, expected %ld\n", c
.X
, font_width
);
3792 ok(c
.Y
== font_height
, "got %d, expected %ld\n", c
.Y
, font_height
);
3794 hmod
= GetModuleHandleA("kernel32.dll");
3795 pGetNumberOfConsoleFonts
= (void *)GetProcAddress(hmod
, "GetNumberOfConsoleFonts");
3796 if (!pGetNumberOfConsoleFonts
)
3798 win_skip("GetNumberOfConsoleFonts is not available\n");
3801 index
= pGetNumberOfConsoleFonts();
3803 memset(&c
, 10, sizeof(COORD
));
3804 SetLastError(0xdeadbeef);
3805 c
= GetConsoleFontSize(std_output
, index
);
3806 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == 0xdeadbeef) /* win10 1809 */,
3807 "unexpected last error %lu\n", GetLastError());
3808 if (GetLastError() == ERROR_INVALID_PARAMETER
)
3810 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3811 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3815 static void test_GetLargestConsoleWindowSize(HANDLE std_output
)
3819 LONG workarea_w
, workarea_h
, maxcon_w
, maxcon_h
;
3820 CONSOLE_SCREEN_BUFFER_INFO sbi
;
3821 CONSOLE_FONT_INFO cfi
;
3822 HANDLE pipe1
, pipe2
;
3826 DWORD (WINAPI
*pGetNumberOfConsoleFonts
)(void);
3827 BOOL (WINAPI
*pSetConsoleFont
)(HANDLE
, DWORD
);
3829 memset(&c
, 10, sizeof(COORD
));
3830 SetLastError(0xdeadbeef);
3831 c
= GetLargestConsoleWindowSize(NULL
);
3832 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3833 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3834 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3836 memset(&c
, 10, sizeof(COORD
));
3837 SetLastError(0xdeadbeef);
3838 c
= GetLargestConsoleWindowSize(GetStdHandle(STD_INPUT_HANDLE
));
3839 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3840 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3841 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3843 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
3844 memset(&c
, 10, sizeof(COORD
));
3845 SetLastError(0xdeadbeef);
3846 c
= GetLargestConsoleWindowSize(pipe1
);
3847 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3848 ok(!c
.X
, "got %d, expected 0\n", c
.X
);
3849 ok(!c
.Y
, "got %d, expected 0\n", c
.Y
);
3853 SystemParametersInfoW(SPI_GETWORKAREA
, 0, &r
, 0);
3854 workarea_w
= r
.right
- r
.left
;
3855 workarea_h
= r
.bottom
- r
.top
- GetSystemMetrics(SM_CYCAPTION
);
3857 GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3858 index
= cfi
.nFont
; /* save current font index */
3860 hmod
= GetModuleHandleA("kernel32.dll");
3861 pGetNumberOfConsoleFonts
= (void *)GetProcAddress(hmod
, "GetNumberOfConsoleFonts");
3862 if (!pGetNumberOfConsoleFonts
)
3864 win_skip("GetNumberOfConsoleFonts is not available\n");
3867 pSetConsoleFont
= (void *)GetProcAddress(hmod
, "SetConsoleFont");
3868 if (!pSetConsoleFont
)
3870 win_skip("SetConsoleFont is not available\n");
3874 for (i
= 0; i
< pGetNumberOfConsoleFonts(); i
++)
3876 pSetConsoleFont(std_output
, i
);
3877 memset(&c
, 10, sizeof(COORD
));
3878 SetLastError(0xdeadbeef);
3879 c
= GetLargestConsoleWindowSize(std_output
);
3880 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3881 GetCurrentConsoleFont(std_output
, FALSE
, &cfi
);
3882 font
= GetConsoleFontSize(std_output
, cfi
.nFont
);
3883 maxcon_w
= workarea_w
/ font
.X
;
3884 maxcon_h
= workarea_h
/ font
.Y
;
3885 ok(c
.X
== maxcon_w
|| c
.X
== maxcon_w
- 1 /* Win10 */, "got %d, expected %ld\n", c
.X
, maxcon_w
);
3886 ok(c
.Y
== maxcon_h
|| c
.Y
== maxcon_h
- 1 /* Win10 */, "got %d, expected %ld\n", c
.Y
, maxcon_h
);
3888 ret
= GetConsoleScreenBufferInfo(std_output
, &sbi
);
3889 ok(ret
, "GetConsoleScreenBufferInfo failed %lu\n", GetLastError());
3890 ok(sbi
.dwMaximumWindowSize
.X
== min(c
.X
, sbi
.dwSize
.X
), "got %d, expected %d\n",
3891 sbi
.dwMaximumWindowSize
.X
, min(c
.X
, sbi
.dwSize
.X
));
3892 ok(sbi
.dwMaximumWindowSize
.Y
== min(c
.Y
, sbi
.dwSize
.Y
), "got %d, expected %d\n",
3893 sbi
.dwMaximumWindowSize
.Y
, min(c
.Y
, sbi
.dwSize
.Y
));
3895 pSetConsoleFont(std_output
, index
); /* restore original font size */
3898 static void test_GetConsoleFontInfo(HANDLE std_output
)
3901 BOOL (WINAPI
*pGetConsoleFontInfo
)(HANDLE
, BOOL
, DWORD
, CONSOLE_FONT_INFO
*);
3902 DWORD (WINAPI
*pGetNumberOfConsoleFonts
)(void);
3903 DWORD num_fonts
, index
, i
;
3904 int memsize
, win_width
, win_height
, tmp_w
, tmp_h
;
3905 CONSOLE_FONT_INFO
*cfi
;
3907 CONSOLE_SCREEN_BUFFER_INFO csbi
;
3908 COORD orig_sb_size
, tmp_sb_size
, orig_font
, tmp_font
;
3910 hmod
= GetModuleHandleA("kernel32.dll");
3911 pGetConsoleFontInfo
= (void *)GetProcAddress(hmod
, "GetConsoleFontInfo");
3912 if (!pGetConsoleFontInfo
)
3914 win_skip("GetConsoleFontInfo is not available\n");
3918 pGetNumberOfConsoleFonts
= (void *)GetProcAddress(hmod
, "GetNumberOfConsoleFonts");
3919 if (!pGetNumberOfConsoleFonts
)
3921 win_skip("GetNumberOfConsoleFonts is not available\n");
3925 num_fonts
= pGetNumberOfConsoleFonts();
3926 memsize
= num_fonts
* sizeof(CONSOLE_FONT_INFO
);
3927 cfi
= HeapAlloc(GetProcessHeap(), 0, memsize
);
3928 memset(cfi
, 0, memsize
);
3930 GetConsoleScreenBufferInfo(std_output
, &csbi
);
3931 orig_sb_size
= csbi
.dwSize
;
3932 tmp_sb_size
.X
= csbi
.dwSize
.X
+ 3;
3933 tmp_sb_size
.Y
= csbi
.dwSize
.Y
+ 5;
3934 SetConsoleScreenBufferSize(std_output
, tmp_sb_size
);
3936 SetLastError(0xdeadbeef);
3937 ret
= pGetConsoleFontInfo(NULL
, FALSE
, 0, cfi
);
3938 ok(!ret
, "got %d, expected zero\n", ret
);
3939 if (GetLastError() == LOWORD(E_NOTIMPL
) /* win10 1709+ */ ||
3940 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win10 1607 */)
3942 skip("GetConsoleFontInfo is not implemented\n");
3943 SetConsoleScreenBufferSize(std_output
, orig_sb_size
);
3944 HeapFree(GetProcessHeap(), 0, cfi
);
3947 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3949 SetLastError(0xdeadbeef);
3950 ret
= pGetConsoleFontInfo(GetStdHandle(STD_INPUT_HANDLE
), FALSE
, 0, cfi
);
3951 ok(!ret
, "got %d, expected zero\n", ret
);
3952 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3954 SetLastError(0xdeadbeef);
3955 ret
= pGetConsoleFontInfo(std_output
, FALSE
, 0, cfi
);
3956 ok(!ret
, "got %d, expected zero\n", ret
);
3957 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
3959 GetConsoleScreenBufferInfo(std_output
, &csbi
);
3960 win_width
= csbi
.srWindow
.Right
- csbi
.srWindow
.Left
+ 1;
3961 win_height
= csbi
.srWindow
.Bottom
- csbi
.srWindow
.Top
+ 1;
3963 GetCurrentConsoleFont(std_output
, FALSE
, &cfi
[0]);
3964 index
= cfi
[0].nFont
;
3965 orig_font
= GetConsoleFontSize(std_output
, index
);
3967 memset(cfi
, 0, memsize
);
3968 ret
= pGetConsoleFontInfo(std_output
, FALSE
, num_fonts
, cfi
);
3969 ok(ret
, "got %d, expected non-zero\n", ret
);
3970 ok(cfi
[index
].dwFontSize
.X
== win_width
, "got %d, expected %d\n",
3971 cfi
[index
].dwFontSize
.X
, win_width
);
3972 ok(cfi
[index
].dwFontSize
.Y
== win_height
, "got %d, expected %d\n",
3973 cfi
[index
].dwFontSize
.Y
, win_height
);
3975 for (i
= 0; i
< num_fonts
; i
++)
3977 ok(cfi
[i
].nFont
== i
, "element out of order, got nFont %ld, expected %ld\n", cfi
[i
].nFont
, i
);
3978 tmp_font
= GetConsoleFontSize(std_output
, cfi
[i
].nFont
);
3979 tmp_w
= (double)orig_font
.X
/ tmp_font
.X
* win_width
;
3980 tmp_h
= (double)orig_font
.Y
/ tmp_font
.Y
* win_height
;
3981 ok(cfi
[i
].dwFontSize
.X
== tmp_w
, "got %d, expected %d\n", cfi
[i
].dwFontSize
.X
, tmp_w
);
3982 ok(cfi
[i
].dwFontSize
.Y
== tmp_h
, "got %d, expected %d\n", cfi
[i
].dwFontSize
.Y
, tmp_h
);
3985 SetLastError(0xdeadbeef);
3986 ret
= pGetConsoleFontInfo(NULL
, TRUE
, 0, cfi
);
3987 ok(!ret
, "got %d, expected zero\n", ret
);
3988 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3990 SetLastError(0xdeadbeef);
3991 ret
= pGetConsoleFontInfo(GetStdHandle(STD_INPUT_HANDLE
), TRUE
, 0, cfi
);
3992 ok(!ret
, "got %d, expected zero\n", ret
);
3993 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
3995 SetLastError(0xdeadbeef);
3996 ret
= pGetConsoleFontInfo(std_output
, TRUE
, 0, cfi
);
3997 ok(!ret
, "got %d, expected zero\n", ret
);
3998 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
4000 memset(cfi
, 0, memsize
);
4001 ret
= pGetConsoleFontInfo(std_output
, TRUE
, num_fonts
, cfi
);
4002 ok(ret
, "got %d, expected non-zero\n", ret
);
4003 ok(cfi
[index
].dwFontSize
.X
== csbi
.dwMaximumWindowSize
.X
, "got %d, expected %d\n",
4004 cfi
[index
].dwFontSize
.X
, csbi
.dwMaximumWindowSize
.X
);
4005 ok(cfi
[index
].dwFontSize
.Y
== csbi
.dwMaximumWindowSize
.Y
, "got %d, expected %d\n",
4006 cfi
[index
].dwFontSize
.Y
, csbi
.dwMaximumWindowSize
.Y
);
4008 for (i
= 0; i
< num_fonts
; i
++)
4010 ok(cfi
[i
].nFont
== i
, "element out of order, got nFont %ld, expected %ld\n", cfi
[i
].nFont
, i
);
4011 tmp_font
= GetConsoleFontSize(std_output
, cfi
[i
].nFont
);
4012 tmp_w
= (double)orig_font
.X
/ tmp_font
.X
* csbi
.dwMaximumWindowSize
.X
;
4013 tmp_h
= (double)orig_font
.Y
/ tmp_font
.Y
* csbi
.dwMaximumWindowSize
.Y
;
4014 ok(cfi
[i
].dwFontSize
.X
== tmp_w
, "got %d, expected %d\n", cfi
[i
].dwFontSize
.X
, tmp_w
);
4015 ok(cfi
[i
].dwFontSize
.Y
== tmp_h
, "got %d, expected %d\n", cfi
[i
].dwFontSize
.Y
, tmp_h
);
4018 HeapFree(GetProcessHeap(), 0, cfi
);
4019 SetConsoleScreenBufferSize(std_output
, orig_sb_size
);
4022 static void test_SetConsoleFont(HANDLE std_output
)
4025 BOOL (WINAPI
*pSetConsoleFont
)(HANDLE
, DWORD
);
4027 DWORD (WINAPI
*pGetNumberOfConsoleFonts
)(void);
4030 hmod
= GetModuleHandleA("kernel32.dll");
4031 pSetConsoleFont
= (void *)GetProcAddress(hmod
, "SetConsoleFont");
4032 if (!pSetConsoleFont
)
4034 win_skip("SetConsoleFont is not available\n");
4038 SetLastError(0xdeadbeef);
4039 ret
= pSetConsoleFont(NULL
, 0);
4040 ok(!ret
, "got %d, expected zero\n", ret
);
4041 if (GetLastError() == LOWORD(E_NOTIMPL
) /* win10 1709+ */ ||
4042 broken(GetLastError() == ERROR_GEN_FAILURE
) /* win10 1607 */)
4044 skip("SetConsoleFont is not implemented\n");
4047 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
4049 SetLastError(0xdeadbeef);
4050 ret
= pSetConsoleFont(GetStdHandle(STD_INPUT_HANDLE
), 0);
4051 ok(!ret
, "got %d, expected zero\n", ret
);
4052 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
4054 pGetNumberOfConsoleFonts
= (void *)GetProcAddress(hmod
, "GetNumberOfConsoleFonts");
4055 if (!pGetNumberOfConsoleFonts
)
4057 win_skip("GetNumberOfConsoleFonts is not available\n");
4061 num_fonts
= pGetNumberOfConsoleFonts();
4063 SetLastError(0xdeadbeef);
4064 ret
= pSetConsoleFont(std_output
, num_fonts
);
4065 ok(!ret
, "got %d, expected zero\n", ret
);
4066 todo_wine
ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
4069 static void test_GetConsoleScreenBufferInfoEx(HANDLE std_output
)
4072 BOOL (WINAPI
*pGetConsoleScreenBufferInfoEx
)(HANDLE
, CONSOLE_SCREEN_BUFFER_INFOEX
*);
4073 CONSOLE_SCREEN_BUFFER_INFOEX csbix
;
4074 HANDLE pipe1
, pipe2
;
4076 HANDLE std_input
= GetStdHandle(STD_INPUT_HANDLE
);
4078 hmod
= GetModuleHandleA("kernel32.dll");
4079 pGetConsoleScreenBufferInfoEx
= (void *)GetProcAddress(hmod
, "GetConsoleScreenBufferInfoEx");
4080 if (!pGetConsoleScreenBufferInfoEx
)
4082 win_skip("GetConsoleScreenBufferInfoEx is not available\n");
4086 SetLastError(0xdeadbeef);
4087 ret
= pGetConsoleScreenBufferInfoEx(NULL
, &csbix
);
4088 ok(!ret
, "got %d, expected zero\n", ret
);
4089 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
4091 SetLastError(0xdeadbeef);
4092 ret
= pGetConsoleScreenBufferInfoEx(std_input
, &csbix
);
4093 ok(!ret
, "got %d, expected zero\n", ret
);
4094 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
4096 SetLastError(0xdeadbeef);
4097 ret
= pGetConsoleScreenBufferInfoEx(std_output
, &csbix
);
4098 ok(!ret
, "got %d, expected zero\n", ret
);
4099 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
4101 csbix
.cbSize
= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
);
4103 SetLastError(0xdeadbeef);
4104 ret
= pGetConsoleScreenBufferInfoEx(NULL
, &csbix
);
4105 ok(!ret
, "got %d, expected zero\n", ret
);
4106 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
4108 SetLastError(0xdeadbeef);
4109 ret
= pGetConsoleScreenBufferInfoEx(std_input
, &csbix
);
4110 ok(!ret
, "got %d, expected zero\n", ret
);
4111 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
4113 CreatePipe(&pipe1
, &pipe2
, NULL
, 0);
4114 SetLastError(0xdeadbeef);
4115 ret
= pGetConsoleScreenBufferInfoEx(std_input
, &csbix
);
4116 ok(!ret
, "got %d, expected zero\n", ret
);
4117 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
4121 SetLastError(0xdeadbeef);
4122 ret
= pGetConsoleScreenBufferInfoEx(std_output
, &csbix
);
4123 ok(ret
, "got %d, expected non-zero\n", ret
);
4124 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
4127 static void test_FreeConsole(void)
4129 HANDLE handle
, unbound_output
= NULL
, unbound_input
= NULL
;
4130 DWORD size
, mode
, type
;
4137 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
!= NULL
, "ConsoleHandle is NULL\n");
4138 ok(!SetConsoleCtrlHandler(mydummych
, FALSE
), "dummy ctrl handler shouldn't be set\n");
4139 ret
= SetConsoleCtrlHandler(mydummych
, TRUE
);
4140 ok(ret
, "SetConsoleCtrlHandler failed: %lu\n", GetLastError());
4143 unbound_input
= create_unbound_handle(FALSE
, TRUE
);
4144 unbound_output
= create_unbound_handle(TRUE
, TRUE
);
4147 ret
= FreeConsole();
4148 ok(ret
, "FreeConsole failed: %lu\n", GetLastError());
4150 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
== NULL
, "ConsoleHandle = %p\n",
4151 RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
);
4153 handle
= CreateFileA("CONOUT$", GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4154 ok(handle
== INVALID_HANDLE_VALUE
&&
4155 (GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_ACCESS_DENIED
/* winxp */)),
4156 "CreateFileA failed: %lu\n", GetLastError());
4158 handle
= CreateFileA("CONIN$", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4159 ok(handle
== INVALID_HANDLE_VALUE
&&
4160 (GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_ACCESS_DENIED
/* winxp */)),
4161 "CreateFileA failed: %lu\n", GetLastError());
4163 handle
= CreateFileA("CON", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4164 ok(handle
== INVALID_HANDLE_VALUE
&&
4165 (GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_ACCESS_DENIED
/* winxp */)),
4166 "CreateFileA failed: %lu\n", GetLastError());
4168 handle
= CreateFileA("CON", GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4169 ok(handle
== INVALID_HANDLE_VALUE
&&
4170 (GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == ERROR_FILE_NOT_FOUND
/* winxp */)),
4171 "CreateFileA failed: %lu\n", GetLastError());
4173 handle
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
4174 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
4175 CONSOLE_TEXTMODE_BUFFER
, NULL
);
4176 ok(handle
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_INVALID_HANDLE
,
4177 "CreateConsoleScreenBuffer returned: %p (%lu)\n", handle
, GetLastError());
4179 SetLastError(0xdeadbeef);
4180 cp
= GetConsoleCP();
4181 ok(!cp
, "cp = %x\n", cp
);
4182 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error %lu\n", GetLastError());
4184 SetLastError(0xdeadbeef);
4185 cp
= GetConsoleOutputCP();
4186 ok(!cp
, "cp = %x\n", cp
);
4187 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error %lu\n", GetLastError());
4189 SetLastError(0xdeadbeef);
4190 ret
= SetConsoleCP(GetOEMCP());
4191 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "SetConsoleCP returned %x(%lu)\n", ret
, GetLastError());
4193 SetLastError(0xdeadbeef);
4194 ret
= SetConsoleOutputCP(GetOEMCP());
4195 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "SetConsoleCP returned %x(%lu)\n", ret
, GetLastError());
4197 if (skip_nt
) return;
4199 SetLastError(0xdeadbeef);
4200 memset( title
, 0xc0, sizeof(title
) );
4201 size
= GetConsoleTitleW( title
, ARRAY_SIZE(title
) );
4202 ok(!size
, "GetConsoleTitleW returned %lu\n", size
);
4203 ok(title
[0] == 0xc0c0, "title byffer changed\n");
4204 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error %lu\n", GetLastError());
4206 SetLastError(0xdeadbeef);
4207 ret
= SetConsoleTitleW( L
"test" );
4208 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "SetConsoleTitleW returned %x(%lu)\n", ret
, GetLastError());
4210 SetLastError(0xdeadbeef);
4211 hwnd
= GetConsoleWindow();
4212 ok(!hwnd
, "hwnd = %p\n", hwnd
);
4213 ok(GetLastError() == ERROR_INVALID_HANDLE
, "last error %lu\n", GetLastError());
4215 ret
= GenerateConsoleCtrlEvent(CTRL_C_EVENT
, 0);
4216 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
, "GenerateConsoleCtrlEvent returned %x(%lu)\n",
4217 ret
, GetLastError());
4219 SetStdHandle( STD_INPUT_HANDLE
, (HANDLE
)0xdeadbeef );
4220 handle
= GetConsoleInputWaitHandle();
4221 ok(handle
== (HANDLE
)0xdeadbeef, "GetConsoleInputWaitHandle returned %p\n", handle
);
4222 SetStdHandle( STD_INPUT_HANDLE
, NULL
);
4223 handle
= GetConsoleInputWaitHandle();
4224 ok(!handle
, "GetConsoleInputWaitHandle returned %p\n", handle
);
4226 ret
= ReadFile(unbound_input
, buf
, sizeof(buf
), &size
, NULL
);
4227 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
4228 "ReadFile returned %x %lu\n", ret
, GetLastError());
4230 ret
= FlushFileBuffers(unbound_input
);
4231 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
4232 "ReadFile returned %x %lu\n", ret
, GetLastError());
4234 ret
= WriteFile(unbound_input
, "test", 4, &size
, NULL
);
4235 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
4236 "ReadFile returned %x %lu\n", ret
, GetLastError());
4238 ret
= GetConsoleMode(unbound_input
, &mode
);
4239 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
4240 "GetConsoleMode returned %x %lu\n", ret
, GetLastError());
4241 ret
= GetConsoleMode(unbound_output
, &mode
);
4242 ok(!ret
&& GetLastError() == ERROR_INVALID_HANDLE
,
4243 "GetConsoleMode returned %x %lu\n", ret
, GetLastError());
4245 type
= GetFileType(unbound_input
);
4246 ok(type
== FILE_TYPE_CHAR
, "GetFileType returned %lu\n", type
);
4247 type
= GetFileType(unbound_output
);
4248 ok(type
== FILE_TYPE_CHAR
, "GetFileType returned %lu\n", type
);
4251 ok(!SetConsoleCtrlHandler(mydummych
, FALSE
), "FreeConsole() should have reset ctrl handlers' list\n");
4253 CloseHandle(unbound_input
);
4254 CloseHandle(unbound_output
);
4257 static void test_SetConsoleScreenBufferInfoEx(HANDLE std_output
)
4261 HANDLE std_input
= CreateFileA("CONIN$", GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4262 BOOL (WINAPI
*pSetConsoleScreenBufferInfoEx
)(HANDLE
, CONSOLE_SCREEN_BUFFER_INFOEX
*);
4263 BOOL (WINAPI
*pGetConsoleScreenBufferInfoEx
)(HANDLE
, CONSOLE_SCREEN_BUFFER_INFOEX
*);
4264 CONSOLE_SCREEN_BUFFER_INFOEX info
;
4266 hmod
= GetModuleHandleA("kernel32.dll");
4267 pSetConsoleScreenBufferInfoEx
= (void *)GetProcAddress(hmod
, "SetConsoleScreenBufferInfoEx");
4268 pGetConsoleScreenBufferInfoEx
= (void *)GetProcAddress(hmod
, "GetConsoleScreenBufferInfoEx");
4269 if (!pSetConsoleScreenBufferInfoEx
|| !pGetConsoleScreenBufferInfoEx
)
4271 win_skip("SetConsoleScreenBufferInfoEx is not available\n");
4275 memset(&info
, 0, sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
));
4276 info
.cbSize
= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
);
4277 pGetConsoleScreenBufferInfoEx(std_output
, &info
);
4279 SetLastError(0xdeadbeef);
4280 ret
= pSetConsoleScreenBufferInfoEx(NULL
, &info
);
4281 ok(!ret
, "got %d, expected zero\n", ret
);
4282 ok(GetLastError() == ERROR_INVALID_HANDLE
, "got %lu, expected 6\n", GetLastError());
4284 SetLastError(0xdeadbeef);
4285 ret
= pSetConsoleScreenBufferInfoEx(std_output
, &info
);
4286 ok(ret
, "got %d, expected one\n", ret
);
4287 ok(GetLastError() == 0xdeadbeef, "got %lu, expected 0xdeadbeef\n", GetLastError());
4289 SetLastError(0xdeadbeef);
4290 ret
= pSetConsoleScreenBufferInfoEx(std_input
, &info
);
4291 ok(!ret
, "got %d, expected zero\n", ret
);
4292 ok(GetLastError() == ERROR_INVALID_HANDLE
|| GetLastError() == ERROR_ACCESS_DENIED
,
4293 "got %lu, expected 5 or 6\n", GetLastError());
4296 SetLastError(0xdeadbeef);
4297 ret
= pSetConsoleScreenBufferInfoEx(std_output
, &info
);
4298 ok(!ret
, "got %d, expected zero\n", ret
);
4299 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "got %lu, expected 87\n", GetLastError());
4301 CloseHandle(std_input
);
4304 static void test_GetConsoleOriginalTitleA(void)
4306 char title
[] = "Original Console Title";
4308 DWORD ret
, title_len
= strlen(title
);
4310 ret
= GetConsoleOriginalTitleA(NULL
, 0);
4311 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4313 ret
= GetConsoleOriginalTitleA(buf
, 0);
4314 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4316 ret
= GetConsoleOriginalTitleA(buf
, ARRAY_SIZE(buf
));
4317 ok(ret
, "GetConsoleOriginalTitleA failed: %lu\n", GetLastError());
4318 ok(!strcmp(buf
, title
), "got %s, expected %s\n", wine_dbgstr_a(buf
), wine_dbgstr_a(title
));
4319 ok(ret
== title_len
, "got %lu, expected %lu\n", ret
, title_len
);
4321 ret
= SetConsoleTitleA("test");
4322 ok(ret
, "SetConsoleTitleA failed: %lu\n", GetLastError());
4324 ret
= GetConsoleOriginalTitleA(buf
, ARRAY_SIZE(buf
));
4325 ok(ret
, "GetConsoleOriginalTitleA failed: %lu\n", GetLastError());
4326 ok(!strcmp(buf
, title
), "got %s, expected %s\n", wine_dbgstr_a(buf
), wine_dbgstr_a(title
));
4327 ok(ret
== title_len
, "got %lu, expected %lu\n", ret
, title_len
);
4330 static void test_GetConsoleOriginalTitleW(void)
4332 WCHAR title
[] = L
"Original Console Title";
4334 DWORD ret
, title_len
= lstrlenW(title
);
4336 ret
= GetConsoleOriginalTitleW(NULL
, 0);
4337 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4339 ret
= GetConsoleOriginalTitleW(buf
, 0);
4340 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4342 ret
= GetConsoleOriginalTitleW(buf
, ARRAY_SIZE(buf
));
4343 ok(ret
, "GetConsoleOriginalTitleW failed: %lu\n", GetLastError());
4345 ok(!wcscmp(buf
, title
), "got %s, expected %s\n", wine_dbgstr_w(buf
), wine_dbgstr_w(title
));
4346 ok(ret
== title_len
, "got %lu, expected %lu\n", ret
, title_len
);
4348 ret
= SetConsoleTitleW(L
"test");
4349 ok(ret
, "SetConsoleTitleW failed: %lu\n", GetLastError());
4351 ret
= GetConsoleOriginalTitleW(buf
, ARRAY_SIZE(buf
));
4352 ok(ret
, "GetConsoleOriginalTitleW failed: %lu\n", GetLastError());
4353 ok(!wcscmp(buf
, title
), "got %s, expected %s\n", wine_dbgstr_w(buf
), wine_dbgstr_w(title
));
4354 ok(ret
== title_len
, "got %lu, expected %lu\n", ret
, title_len
);
4356 ret
= GetConsoleOriginalTitleW(buf
, 5);
4357 ok(ret
, "GetConsoleOriginalTitleW failed: %lu\n", GetLastError());
4358 ok(!wcscmp(buf
, L
"Orig"), "got %s, expected 'Orig'\n", wine_dbgstr_w(buf
));
4359 ok(ret
== title_len
, "got %lu, expected %lu\n", ret
, title_len
);
4362 static void test_GetConsoleOriginalTitleW_empty(void)
4367 ret
= GetConsoleOriginalTitleW(buf
, ARRAY_SIZE(buf
));
4368 ok(!ret
, "GetConsoleOriginalTitleW failed: %lu\n", GetLastError());
4371 static void test_GetConsoleOriginalTitle(void)
4373 STARTUPINFOA si
= { sizeof(si
) };
4374 PROCESS_INFORMATION info
;
4375 char **argv
, buf
[MAX_PATH
];
4376 char title
[] = "Original Console Title";
4379 winetest_get_mainargs(&argv
);
4380 sprintf(buf
, "\"%s\" console title_test", argv
[0]);
4382 ret
= CreateProcessA(NULL
, buf
, NULL
, NULL
, TRUE
, CREATE_NEW_CONSOLE
, NULL
, NULL
, &si
, &info
);
4383 ok(ret
, "CreateProcess failed: %lu\n", GetLastError());
4384 CloseHandle(info
.hThread
);
4385 wait_child_process(info
.hProcess
);
4386 CloseHandle(info
.hProcess
);
4388 strcat(buf
, " empty");
4390 ret
= CreateProcessA(NULL
, buf
, NULL
, NULL
, TRUE
, CREATE_NEW_CONSOLE
, NULL
, NULL
, &si
, &info
);
4391 ok(ret
, "CreateProcess failed: %lu\n", GetLastError());
4392 CloseHandle(info
.hThread
);
4393 wait_child_process(info
.hProcess
);
4394 CloseHandle(info
.hProcess
);
4397 static void test_GetConsoleTitleA(void)
4399 char buf
[64], str
[] = "test";
4402 ret
= SetConsoleTitleA(str
);
4403 ok(ret
, "SetConsoleTitleA failed: %lu\n", GetLastError());
4405 ret
= GetConsoleTitleA(NULL
, 0);
4406 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4408 ret
= GetConsoleTitleA(buf
, 0);
4409 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4411 ret
= GetConsoleTitleA(buf
, ARRAY_SIZE(buf
));
4412 ok(ret
, "GetConsoleTitleW failed: %lu\n", GetLastError());
4413 ok(ret
== strlen(str
), "Got string length %lu, expected %Iu\n", ret
, strlen(str
));
4414 ok(!strcmp(buf
, str
), "Title = %s\n", wine_dbgstr_a(buf
));
4416 ret
= SetConsoleTitleA("");
4417 ok(ret
, "SetConsoleTitleA failed: %lu\n", GetLastError());
4419 ret
= GetConsoleTitleA(buf
, ARRAY_SIZE(buf
));
4420 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4423 static void test_GetConsoleTitleW(void)
4425 WCHAR buf
[64], str
[] = L
"test";
4428 ret
= SetConsoleTitleW(str
);
4429 ok(ret
, "SetConsoleTitleW failed: %lu\n", GetLastError());
4431 ret
= GetConsoleTitleW(NULL
, 0);
4432 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4434 ret
= GetConsoleTitleW(buf
, 0);
4435 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4437 ret
= GetConsoleTitleW(buf
, ARRAY_SIZE(buf
));
4438 ok(ret
, "GetConsoleTitleW failed: %lu\n", GetLastError());
4439 ok(ret
== wcslen(str
), "Got string length %lu, expected %Iu\n", ret
, wcslen(str
));
4440 ok(!wcscmp(buf
, str
), "Title = %s\n", wine_dbgstr_w(buf
));
4442 ret
= GetConsoleTitleW(buf
, 2);
4443 ok(ret
, "GetConsoleTitleW failed: %lu\n", GetLastError());
4444 ok(ret
== wcslen(str
), "Got string length %lu, expected %Iu\n", ret
, wcslen(str
));
4445 if (!skip_nt
) ok(!wcscmp(buf
, L
"t"), "Title = %s\n", wine_dbgstr_w(buf
));
4447 ret
= GetConsoleTitleW(buf
, 4);
4448 ok(ret
, "GetConsoleTitleW failed: %lu\n", GetLastError());
4449 ok(ret
== wcslen(str
), "Got string length %lu, expected %Iu\n", ret
, wcslen(str
));
4450 if (!skip_nt
) ok(!wcscmp(buf
, L
"tes"), "Title = %s\n", wine_dbgstr_w(buf
));
4452 ret
= SetConsoleTitleW(L
"");
4453 ok(ret
, "SetConsoleTitleW failed: %lu\n", GetLastError());
4455 ret
= GetConsoleTitleW(buf
, ARRAY_SIZE(buf
));
4456 ok(!ret
, "Unexpected string length; error %lu\n", GetLastError());
4459 static void test_file_info(HANDLE input
, HANDLE output
)
4461 FILE_STANDARD_INFORMATION std_info
;
4462 FILE_FS_DEVICE_INFORMATION fs_info
;
4469 if (skip_nt
) return;
4471 status
= NtQueryInformationFile(input
, &io
, &std_info
, sizeof(std_info
), FileStandardInformation
);
4472 ok(status
== STATUS_INVALID_DEVICE_REQUEST
, "NtQueryInformationFile returned: %#lx\n", status
);
4474 status
= NtQueryInformationFile(output
, &io
, &std_info
, sizeof(std_info
), FileStandardInformation
);
4475 ok(status
== STATUS_INVALID_DEVICE_REQUEST
, "NtQueryInformationFile returned: %#lx\n", status
);
4477 ret
= GetFileSizeEx(input
, &size
);
4478 ok(!ret
&& GetLastError() == ERROR_INVALID_FUNCTION
,
4479 "GetFileSizeEx returned %x(%lu)\n", ret
, GetLastError());
4481 ret
= GetFileSizeEx(output
, &size
);
4482 ok(!ret
&& GetLastError() == ERROR_INVALID_FUNCTION
,
4483 "GetFileSizeEx returned %x(%lu)\n", ret
, GetLastError());
4485 status
= NtQueryVolumeInformationFile(input
, &io
, &fs_info
, sizeof(fs_info
), FileFsDeviceInformation
);
4486 ok(!status
, "NtQueryVolumeInformationFile failed: %#lx\n", status
);
4487 ok(fs_info
.DeviceType
== FILE_DEVICE_CONSOLE
, "DeviceType = %lu\n", fs_info
.DeviceType
);
4488 ok(fs_info
.Characteristics
== FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
,
4489 "Characteristics = %lx\n", fs_info
.Characteristics
);
4491 status
= NtQueryVolumeInformationFile(output
, &io
, &fs_info
, sizeof(fs_info
), FileFsDeviceInformation
);
4492 ok(!status
, "NtQueryVolumeInformationFile failed: %#lx\n", status
);
4493 ok(fs_info
.DeviceType
== FILE_DEVICE_CONSOLE
, "DeviceType = %lu\n", fs_info
.DeviceType
);
4494 ok(fs_info
.Characteristics
== FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
,
4495 "Characteristics = %lx\n", fs_info
.Characteristics
);
4497 type
= GetFileType(input
);
4498 ok(type
== FILE_TYPE_CHAR
, "GetFileType returned %lu\n", type
);
4499 type
= GetFileType(output
);
4500 ok(type
== FILE_TYPE_CHAR
, "GetFileType returned %lu\n", type
);
4503 static void test_AttachConsole_child(DWORD console_pid
)
4505 HANDLE pipe_in
, pipe_out
;
4512 res
= CreatePipe(&pipe_in
, &pipe_out
, NULL
, 0);
4513 ok(res
, "CreatePipe failed: %lu\n", GetLastError());
4515 res
= AttachConsole(console_pid
);
4516 ok(!res
&& GetLastError() == ERROR_ACCESS_DENIED
,
4517 "AttachConsole returned: %x(%lu)\n", res
, GetLastError());
4519 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
!= NULL
, "ConsoleHandle is NULL\n");
4520 res
= FreeConsole();
4521 ok(res
, "FreeConsole failed: %lu\n", GetLastError());
4522 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
== NULL
, "ConsoleHandle = %p\n",
4523 RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
);
4525 SetStdHandle(STD_ERROR_HANDLE
, pipe_out
);
4527 ok(!SetConsoleCtrlHandler(mydummych
, FALSE
), "dummy ctrl handler shouldn't be set\n");
4528 res
= SetConsoleCtrlHandler(mydummych
, TRUE
);
4529 ok(res
, "SetConsoleCtrlHandler failed: %lu\n", GetLastError());
4531 res
= AttachConsole(console_pid
);
4532 ok(res
, "AttachConsole failed: %lu\n", GetLastError());
4534 ok(pipe_out
!= GetStdHandle(STD_ERROR_HANDLE
), "std handle not set to console\n");
4535 ok(RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
!= NULL
, "ConsoleHandle is NULL\n");
4537 console
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4538 ok(console
!= INVALID_HANDLE_VALUE
, "Could not open console\n");
4540 res
= ReadConsoleOutputCharacterA(console
, buf
, 6, c
, &len
);
4541 ok(res
, "ReadConsoleOutputCharacterA failed: %lu\n", GetLastError());
4542 ok(len
== 6, "len = %lu\n", len
);
4543 ok(!memcmp(buf
, "Parent", 6), "Unexpected console output\n");
4546 ok(!SetConsoleCtrlHandler(mydummych
, FALSE
), "AttachConsole() should have reset ctrl handlers' list\n");
4548 res
= FreeConsole();
4549 ok(res
, "FreeConsole failed: %lu\n", GetLastError());
4551 SetStdHandle(STD_INPUT_HANDLE
, pipe_in
);
4552 SetStdHandle(STD_OUTPUT_HANDLE
, pipe_out
);
4554 res
= AttachConsole(ATTACH_PARENT_PROCESS
);
4555 ok(res
, "AttachConsole failed: %lu\n", GetLastError());
4557 if (pGetConsoleProcessList
)
4559 DWORD list
[2] = { 0xbabebabe };
4560 DWORD pid
= GetCurrentProcessId();
4562 SetLastError(0xdeadbeef);
4563 len
= pGetConsoleProcessList(list
, 1);
4564 ok(len
== 2, "Expected 2 processes, got %ld\n", len
);
4565 ok(list
[0] == 0xbabebabe, "Unexpected value in list %lu\n", list
[0]);
4567 len
= pGetConsoleProcessList(list
, 2);
4568 ok(len
== 2, "Expected 2 processes, got %ld\n", len
);
4569 ok(list
[0] == console_pid
|| list
[1] == console_pid
, "Parent PID not in list\n");
4570 ok(list
[0] == pid
|| list
[1] == pid
, "PID not in list\n");
4571 ok(GetLastError() == 0xdeadbeef, "Unexpected last error: %lu\n", GetLastError());
4574 ok(pipe_in
!= GetStdHandle(STD_INPUT_HANDLE
), "std handle not set to console\n");
4575 ok(pipe_out
!= GetStdHandle(STD_OUTPUT_HANDLE
), "std handle not set to console\n");
4577 console
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
4578 ok(console
!= INVALID_HANDLE_VALUE
, "Could not open console\n");
4580 res
= ReadConsoleOutputCharacterA(console
, buf
, 6, c
, &len
);
4581 ok(res
, "ReadConsoleOutputCharacterA failed: %lu\n", GetLastError());
4582 ok(len
== 6, "len = %lu\n", len
);
4583 ok(!memcmp(buf
, "Parent", 6), "Unexpected console output\n");
4585 simple_write_console(console
, "Child");
4586 CloseHandle(console
);
4588 res
= FreeConsole();
4589 ok(res
, "FreeConsole failed: %lu\n", GetLastError());
4591 res
= CloseHandle(pipe_in
);
4592 ok(res
, "pipe_in is no longer valid\n");
4593 res
= CloseHandle(pipe_out
);
4594 ok(res
, "pipe_out is no longer valid\n");
4597 static void test_AttachConsole(HANDLE console
)
4599 STARTUPINFOA si
= { sizeof(si
) };
4600 PROCESS_INFORMATION info
;
4601 char **argv
, buf
[MAX_PATH
];
4606 simple_write_console(console
, "Parent console");
4608 winetest_get_mainargs(&argv
);
4609 sprintf(buf
, "\"%s\" console attach_console %lx", argv
[0], GetCurrentProcessId());
4610 res
= CreateProcessA(NULL
, buf
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &info
);
4611 ok(res
, "CreateProcess failed: %lu\n", GetLastError());
4612 CloseHandle(info
.hThread
);
4614 wait_child_process(info
.hProcess
);
4615 CloseHandle(info
.hProcess
);
4617 res
= ReadConsoleOutputCharacterA(console
, buf
, 5, c
, &len
);
4618 ok(res
, "ReadConsoleOutputCharacterA failed: %lu\n", GetLastError());
4619 ok(len
== 5, "len = %lu\n", len
);
4620 ok(!memcmp(buf
, "Child", 5), "Unexpected console output\n");
4623 static void test_AllocConsole_child(void)
4625 HANDLE unbound_output
;
4626 HANDLE prev_output
, prev_error
;
4631 GetStartupInfoW(&si
);
4633 prev_output
= GetStdHandle(STD_OUTPUT_HANDLE
);
4634 res
= DuplicateHandle(GetCurrentProcess(), prev_output
, GetCurrentProcess(), &unbound_output
,
4635 0, FALSE
, DUPLICATE_SAME_ACCESS
);
4636 ok(res
, "DuplicateHandle failed: %lu\n", GetLastError());
4638 res
= GetConsoleMode(unbound_output
, &mode
);
4639 ok(res
, "GetConsoleMode failed: %lu\n", GetLastError());
4641 prev_error
= GetStdHandle(STD_ERROR_HANDLE
);
4642 if (si
.dwFlags
& STARTF_USESTDHANDLES
)
4644 res
= GetConsoleMode(prev_error
, &mode
);
4645 ok(!res
&& GetLastError() == ERROR_INVALID_HANDLE
, "GetConsoleMode failed: %lu\n", GetLastError());
4650 ok(GetStdHandle(STD_OUTPUT_HANDLE
) == prev_output
, "GetStdHandle(STD_OUTPUT_HANDLE) = %p\n", GetStdHandle(STD_OUTPUT_HANDLE
));
4651 ok(GetStdHandle(STD_ERROR_HANDLE
) == prev_error
, "GetStdHandle(STD_ERROR_HANDLE) = %p\n", GetStdHandle(STD_ERROR_HANDLE
));
4652 res
= GetConsoleMode(unbound_output
, &mode
);
4653 ok(!res
&& GetLastError() == ERROR_INVALID_HANDLE
, "GetConsoleMode failed: %lu\n", GetLastError());
4655 ok(!SetConsoleCtrlHandler(mydummych
, FALSE
), "dummy ctrl handler shouldn't be set\n");
4656 res
= SetConsoleCtrlHandler(mydummych
, TRUE
);
4657 ok(res
, "SetConsoleCtrlHandler failed: %lu\n", GetLastError());
4658 res
= AllocConsole();
4659 ok(res
, "AllocConsole failed: %lu\n", GetLastError());
4661 if (si
.dwFlags
& STARTF_USESTDHANDLES
)
4663 ok(GetStdHandle(STD_OUTPUT_HANDLE
) == prev_output
, "GetStdHandle(STD_OUTPUT_HANDLE) = %p\n", GetStdHandle(STD_OUTPUT_HANDLE
));
4664 ok(GetStdHandle(STD_ERROR_HANDLE
) == prev_error
, "GetStdHandle(STD_ERROR_HANDLE) = %p\n", GetStdHandle(STD_ERROR_HANDLE
));
4667 res
= GetConsoleMode(unbound_output
, &mode
);
4668 ok(res
, "GetConsoleMode failed: %lu\n", GetLastError());
4671 ok(!SetConsoleCtrlHandler(mydummych
, FALSE
), "AllocConsole() should have reset ctrl handlers' list\n");
4674 SetStdHandle(STD_OUTPUT_HANDLE
, NULL
);
4675 SetStdHandle(STD_ERROR_HANDLE
, NULL
);
4676 res
= AllocConsole();
4677 ok(res
, "AllocConsole failed: %lu\n", GetLastError());
4679 ok(GetStdHandle(STD_OUTPUT_HANDLE
) != NULL
, "GetStdHandle(STD_OUTPUT_HANDLE) = %p\n", GetStdHandle(STD_OUTPUT_HANDLE
));
4680 ok(GetStdHandle(STD_ERROR_HANDLE
) != NULL
, "GetStdHandle(STD_ERROR_HANDLE) = %p\n", GetStdHandle(STD_ERROR_HANDLE
));
4682 res
= GetConsoleMode(unbound_output
, &mode
);
4683 ok(res
, "GetConsoleMode failed: %lu\n", GetLastError());
4684 res
= GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE
), &mode
);
4685 ok(res
, "GetConsoleMode failed: %lu\n", GetLastError());
4686 res
= GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE
), &mode
);
4687 ok(res
, "GetConsoleMode failed: %lu\n", GetLastError());
4689 res
= CloseHandle(unbound_output
);
4690 ok(res
, "CloseHandle failed: %lu\n", GetLastError());
4693 static void test_AllocConsole(void)
4695 SECURITY_ATTRIBUTES inheritable_attr
= { sizeof(inheritable_attr
), NULL
, TRUE
};
4696 STARTUPINFOA si
= { sizeof(si
) };
4697 PROCESS_INFORMATION info
;
4698 char **argv
, buf
[MAX_PATH
];
4699 HANDLE pipe_read
, pipe_write
;
4702 if (skip_nt
) return;
4704 winetest_get_mainargs(&argv
);
4705 sprintf(buf
, "\"%s\" console alloc_console", argv
[0]);
4706 res
= CreateProcessA(NULL
, buf
, NULL
, NULL
, FALSE
, CREATE_NEW_CONSOLE
, NULL
, NULL
, &si
, &info
);
4707 ok(res
, "CreateProcess failed: %lu\n", GetLastError());
4708 CloseHandle(info
.hThread
);
4709 wait_child_process(info
.hProcess
);
4710 CloseHandle(info
.hProcess
);
4712 res
= CreatePipe(&pipe_read
, &pipe_write
, &inheritable_attr
, 0);
4713 ok(res
, "CreatePipe failed: %lu\n", GetLastError());
4715 si
.dwFlags
= STARTF_USESTDHANDLES
;
4716 si
.hStdError
= pipe_write
;
4717 res
= CreateProcessA(NULL
, buf
, NULL
, NULL
, TRUE
, CREATE_NEW_CONSOLE
, NULL
, NULL
, &si
, &info
);
4718 ok(res
, "CreateProcess failed: %lu\n", GetLastError());
4719 CloseHandle(info
.hThread
);
4720 wait_child_process(info
.hProcess
);
4721 CloseHandle(info
.hProcess
);
4723 CloseHandle(pipe_read
);
4724 CloseHandle(pipe_write
);
4727 static void test_pseudo_console_child(HANDLE input
, HANDLE output
)
4729 CONSOLE_SCREEN_BUFFER_INFO sb_info
;
4730 CONSOLE_CURSOR_INFO cursor_info
;
4735 ret
= GetConsoleMode(input
, &mode
);
4736 ok(ret
, "GetConsoleMode failed: %lu\n", GetLastError());
4737 ok(mode
== (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
|
4738 ENABLE_INSERT_MODE
| ENABLE_QUICK_EDIT_MODE
| ENABLE_EXTENDED_FLAGS
| ENABLE_AUTO_POSITION
),
4739 "mode = %lx\n", mode
);
4741 ret
= SetConsoleMode(input
, mode
& ~ENABLE_AUTO_POSITION
);
4742 ok(ret
, "SetConsoleMode failed: %lu\n", GetLastError());
4744 ret
= GetConsoleMode(input
, &mode
);
4745 ok(ret
, "GetConsoleMode failed: %lu\n", GetLastError());
4746 ok(mode
== (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
|
4747 ENABLE_INSERT_MODE
| ENABLE_QUICK_EDIT_MODE
| ENABLE_EXTENDED_FLAGS
), "mode = %lx\n", mode
);
4749 ret
= SetConsoleMode(input
, mode
| ENABLE_AUTO_POSITION
);
4750 ok(ret
, "SetConsoleMode failed: %lu\n", GetLastError());
4752 ret
= GetConsoleMode(output
, &mode
);
4753 ok(ret
, "GetConsoleMode failed: %lu\n", GetLastError());
4754 mode
&= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING
;
4755 ok(mode
== (ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
), "mode = %lx\n", mode
);
4757 ret
= SetConsoleMode(output
, mode
& ~ENABLE_WRAP_AT_EOL_OUTPUT
);
4758 ok(ret
, "SetConsoleMode failed: %lu\n", GetLastError());
4760 ret
= GetConsoleMode(output
, &mode
);
4761 ok(ret
, "GetConsoleMode failed: %lu\n", GetLastError());
4762 ok(mode
== ENABLE_PROCESSED_OUTPUT
, "mode = %lx\n", mode
);
4764 ret
= SetConsoleMode(output
, mode
| ENABLE_WRAP_AT_EOL_OUTPUT
);
4765 ok(ret
, "SetConsoleMode failed: %lu\n", GetLastError());
4767 ret
= GetConsoleScreenBufferInfo(output
, &sb_info
);
4768 ok(ret
, "GetConsoleScreenBufferInfo failed: %lu\n", GetLastError());
4769 ok(sb_info
.dwSize
.X
== 40, "dwSize.X = %u\n", sb_info
.dwSize
.X
);
4770 ok(sb_info
.dwSize
.Y
== 30, "dwSize.Y = %u\n", sb_info
.dwSize
.Y
);
4771 ok(sb_info
.dwCursorPosition
.X
== 0, "dwCursorPosition.X = %u\n", sb_info
.dwCursorPosition
.X
);
4772 ok(sb_info
.dwCursorPosition
.Y
== 0, "dwCursorPosition.Y = %u\n", sb_info
.dwCursorPosition
.Y
);
4773 ok(sb_info
.wAttributes
== 7, "wAttributes = %x\n", sb_info
.wAttributes
);
4774 ok(sb_info
.srWindow
.Left
== 0, "srWindow.Left = %u\n", sb_info
.srWindow
.Left
);
4775 ok(sb_info
.srWindow
.Top
== 0, "srWindow.Top = %u\n", sb_info
.srWindow
.Top
);
4776 ok(sb_info
.srWindow
.Right
== 39, "srWindow.Right = %u\n", sb_info
.srWindow
.Right
);
4777 ok(sb_info
.srWindow
.Bottom
== 29, "srWindow.Bottom = %u\n", sb_info
.srWindow
.Bottom
);
4778 ok(sb_info
.dwMaximumWindowSize
.X
== 40, "dwMaximumWindowSize.X = %u\n", sb_info
.dwMaximumWindowSize
.X
);
4779 ok(sb_info
.dwMaximumWindowSize
.Y
== 30, "dwMaximumWindowSize.Y = %u\n", sb_info
.dwMaximumWindowSize
.Y
);
4781 ret
= GetConsoleCursorInfo(output
, &cursor_info
);
4782 ok(ret
, "GetConsoleCursorInfo failed: %lu\n", GetLastError());
4783 ok(cursor_info
.dwSize
== 25, "dwSize = %lu\n", cursor_info
.dwSize
);
4784 ok(cursor_info
.bVisible
== TRUE
, "bVisible = %x\n", cursor_info
.bVisible
);
4786 hwnd
= GetConsoleWindow();
4787 ok(IsWindow(hwnd
), "no console window\n");
4789 test_GetConsoleTitleA();
4790 test_GetConsoleTitleW();
4791 test_WriteConsoleInputW(input
);
4794 static DWORD WINAPI
read_pipe_proc( void *handle
)
4798 while (ReadFile(handle
, buf
, sizeof(buf
), &size
, NULL
));
4799 ok(GetLastError() == ERROR_BROKEN_PIPE
, "ReadFile returned %lu\n", GetLastError());
4800 CloseHandle(handle
);
4804 static void test_pseudo_console(void)
4806 STARTUPINFOEXA startup
= {{ sizeof(startup
) }};
4807 HANDLE console_pipe
, console_pipe2
, thread
;
4808 char **argv
, cmdline
[MAX_PATH
];
4809 PROCESS_INFORMATION info
;
4810 HPCON pseudo_console
;
4816 if (!pCreatePseudoConsole
)
4818 win_skip("CreatePseudoConsole not available\n");
4822 console_pipe
= CreateNamedPipeW(L
"\\\\.\\pipe\\pseudoconsoleconn", PIPE_ACCESS_DUPLEX
,
4823 PIPE_WAIT
| PIPE_TYPE_BYTE
, 1, 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT
, NULL
);
4824 ok(console_pipe
!= INVALID_HANDLE_VALUE
, "CreateNamedPipeW failed: %lu\n", GetLastError());
4826 console_pipe2
= CreateFileW(L
"\\\\.\\pipe\\pseudoconsoleconn", GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
4827 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, NULL
);
4828 ok(console_pipe2
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %lu\n", GetLastError());
4830 thread
= CreateThread( NULL
, 0, read_pipe_proc
, console_pipe
, 0, NULL
);
4831 CloseHandle(thread
);
4835 hres
= pCreatePseudoConsole(size
, console_pipe2
, console_pipe2
, 0, &pseudo_console
);
4836 ok(hres
== E_INVALIDARG
, "CreatePseudoConsole failed: %08lx\n", hres
);
4840 hres
= pCreatePseudoConsole(size
, console_pipe2
, console_pipe2
, 0, &pseudo_console
);
4841 ok(hres
== E_INVALIDARG
, "CreatePseudoConsole failed: %08lx\n", hres
);
4845 hres
= pCreatePseudoConsole(size
, console_pipe2
, console_pipe2
, 0, &pseudo_console
);
4846 ok(hres
== S_OK
, "CreatePseudoConsole failed: %08lx\n", hres
);
4847 CloseHandle(console_pipe2
);
4849 InitializeProcThreadAttributeList(NULL
, 1, 0, &attr_size
);
4850 startup
.lpAttributeList
= HeapAlloc(GetProcessHeap(), 0, attr_size
);
4851 InitializeProcThreadAttributeList(startup
.lpAttributeList
, 1, 0, &attr_size
);
4852 UpdateProcThreadAttribute(startup
.lpAttributeList
, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
, pseudo_console
,
4853 sizeof(pseudo_console
), NULL
, NULL
);
4855 winetest_get_mainargs(&argv
);
4856 sprintf(cmdline
, "\"%s\" %s --pseudo-console", argv
[0], argv
[1]);
4857 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, EXTENDED_STARTUPINFO_PRESENT
, NULL
, NULL
, &startup
.StartupInfo
, &info
);
4858 ok(ret
, "CreateProcessW failed: %lu\n", GetLastError());
4860 CloseHandle(info
.hThread
);
4861 HeapFree(GetProcessHeap(), 0, startup
.lpAttributeList
);
4862 wait_child_process(info
.hProcess
);
4863 CloseHandle(info
.hProcess
);
4865 pClosePseudoConsole(pseudo_console
);
4868 /* copy an executable, but changing its subsystem */
4869 static void copy_change_subsystem(const char* in
, const char* out
, DWORD subsyst
)
4874 IMAGE_NT_HEADERS
*nthdr
;
4876 ret
= CopyFileA(in
, out
, FALSE
);
4877 ok(ret
, "Failed to copy executable %s in %s (%lu)\n", in
, out
, GetLastError());
4879 hFile
= CreateFileA(out
, GENERIC_READ
| GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
4880 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4881 ok(hFile
!= INVALID_HANDLE_VALUE
, "Couldn't open file %s (%lu)\n", out
, GetLastError());
4882 hMap
= CreateFileMappingW(hFile
, NULL
, PAGE_READWRITE
, 0, 0, NULL
);
4883 ok(hMap
!= NULL
, "Couldn't create map (%lu)\n", GetLastError());
4884 mapping
= MapViewOfFile(hMap
, FILE_MAP_ALL_ACCESS
, 0, 0, 0);
4885 ok(mapping
!= NULL
, "Couldn't map (%lu)\n", GetLastError());
4886 nthdr
= RtlImageNtHeader(mapping
);
4887 ok(nthdr
!= NULL
, "Cannot get NT headers out of %s\n", out
);
4888 if (nthdr
) nthdr
->OptionalHeader
.Subsystem
= subsyst
;
4889 ret
= UnmapViewOfFile(mapping
);
4890 ok(ret
, "Couldn't unmap (%lu)\n", GetLastError());
4895 enum inheritance_model
{NULL_STD
, CONSOLE_STD
, STARTUPINFO_STD
};
4897 static DWORD
check_child_console_bits(const char* exec
, DWORD flags
, enum inheritance_model inherit
)
4899 SECURITY_ATTRIBUTES sa
= {0, NULL
, TRUE
};
4900 STARTUPINFOA si
= { sizeof(si
) };
4901 PROCESS_INFORMATION info
;
4907 BOOL inherit_handles
= FALSE
;
4909 sprintf(buf
, "\"%s\" console check_console", exec
);
4913 SetStdHandle(STD_INPUT_HANDLE
, NULL
);
4914 SetStdHandle(STD_OUTPUT_HANDLE
, NULL
);
4915 SetStdHandle(STD_ERROR_HANDLE
, NULL
);
4918 handle
= CreateFileA("CONIN$", GENERIC_READ
, 0, &sa
, OPEN_EXISTING
, 0, 0);
4919 ok(handle
!= INVALID_HANDLE_VALUE
, "Couldn't create input to console\n");
4920 SetStdHandle(STD_INPUT_HANDLE
, handle
);
4921 handle
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, &sa
, OPEN_EXISTING
, 0, 0);
4922 ok(handle
!= INVALID_HANDLE_VALUE
, "Couldn't create input to console\n");
4923 SetStdHandle(STD_OUTPUT_HANDLE
, handle
);
4924 SetStdHandle(STD_ERROR_HANDLE
, handle
);
4926 case STARTUPINFO_STD
:
4927 si
.dwFlags
|= STARTF_USESTDHANDLES
;
4928 si
.hStdInput
= CreateFileA("CONIN$", GENERIC_READ
, 0, &sa
, OPEN_EXISTING
, 0, 0);
4929 ok(si
.hStdInput
!= INVALID_HANDLE_VALUE
, "Couldn't create input to console\n");
4930 si
.hStdOutput
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, &sa
, OPEN_EXISTING
, 0, 0);
4931 ok(si
.hStdInput
!= INVALID_HANDLE_VALUE
, "Couldn't create output to console\n");
4932 si
.hStdError
= INVALID_HANDLE_VALUE
;
4933 inherit_handles
= TRUE
;
4936 res
= CreateProcessA(NULL
, buf
, NULL
, NULL
, inherit_handles
, flags
, NULL
, NULL
, &si
, &info
);
4937 ok(res
, "CreateProcess failed: %lu %s\n", GetLastError(), buf
);
4938 CloseHandle(info
.hThread
);
4939 ret
= WaitForSingleObject(info
.hProcess
, 30000);
4940 ok(ret
== WAIT_OBJECT_0
, "Could not wait for the child process: %ld le=%lu\n",
4941 ret
, GetLastError());
4942 res
= GetExitCodeProcess(info
.hProcess
, &exit_code
);
4943 ok(res
&& exit_code
<= 255, "Couldn't get exit_code\n");
4944 CloseHandle(info
.hProcess
);
4950 CloseHandle(GetStdHandle(STD_INPUT_HANDLE
));
4951 CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE
));
4953 case STARTUPINFO_STD
:
4954 CloseHandle(si
.hStdInput
);
4955 CloseHandle(si
.hStdOutput
);
4961 #define CP_WITH_CONSOLE 0x01 /* attached to a console */
4962 #define CP_WITH_HANDLE 0x02 /* child has a console handle */
4963 #define CP_WITH_WINDOW 0x04 /* child has a console window */
4964 #define CP_ALONE 0x08 /* whether child is the single process attached to console */
4965 #define CP_GROUP_LEADER 0x10 /* whether the child is the process group leader */
4966 #define CP_INPUT_VALID 0x20 /* whether StdHandle(INPUT) is a valid console handle */
4967 #define CP_OUTPUT_VALID 0x40 /* whether StdHandle(OUTPUT) is a valid console handle */
4968 #define CP_ENABLED_CTRLC 0x80 /* whether the ctrl-c handling isn't blocked */
4970 #define CP_OWN_CONSOLE (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_INPUT_VALID | CP_OUTPUT_VALID | CP_ALONE)
4971 #define CP_INH_CONSOLE (CP_WITH_CONSOLE | CP_WITH_HANDLE | CP_INPUT_VALID | CP_OUTPUT_VALID)
4973 static void test_CreateProcessCUI(void)
4976 static char guiexec
[MAX_PATH
];
4977 static char cuiexec
[MAX_PATH
];
4981 BOOL saved_console_flags
;
4987 enum inheritance_model inherit
;
4991 no_console_tests
[] =
4993 /* 0*/ {FALSE
, 0, NULL_STD
, 0},
4994 {FALSE
, DETACHED_PROCESS
, NULL_STD
, 0},
4995 {FALSE
, CREATE_NEW_CONSOLE
, NULL_STD
, 0},
4996 {FALSE
, CREATE_NO_WINDOW
, NULL_STD
, 0},
4997 {FALSE
, DETACHED_PROCESS
| CREATE_NO_WINDOW
, NULL_STD
, 0},
4998 /* 5*/ {FALSE
, CREATE_NEW_CONSOLE
| CREATE_NO_WINDOW
, NULL_STD
, 0},
5000 {TRUE
, 0, NULL_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
},
5001 {TRUE
, DETACHED_PROCESS
, NULL_STD
, 0},
5002 {TRUE
, CREATE_NEW_CONSOLE
, NULL_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
},
5003 {TRUE
, CREATE_NO_WINDOW
, NULL_STD
, CP_OWN_CONSOLE
},
5004 /*10*/ {TRUE
, DETACHED_PROCESS
| CREATE_NO_WINDOW
, NULL_STD
, 0},
5005 {TRUE
, CREATE_NEW_CONSOLE
| CREATE_NO_WINDOW
, NULL_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
},
5007 with_console_tests
[] =
5009 /* 0*/ {FALSE
, 0, NULL_STD
, 0},
5010 {FALSE
, DETACHED_PROCESS
, NULL_STD
, 0},
5011 {FALSE
, CREATE_NEW_CONSOLE
, NULL_STD
, 0},
5012 {FALSE
, CREATE_NO_WINDOW
, NULL_STD
, 0},
5013 {FALSE
, DETACHED_PROCESS
| CREATE_NO_WINDOW
, NULL_STD
, 0},
5014 /* 5*/ {FALSE
, CREATE_NEW_CONSOLE
| CREATE_NO_WINDOW
, NULL_STD
, 0},
5016 {FALSE
, 0, CONSOLE_STD
, 0},
5017 {FALSE
, DETACHED_PROCESS
, CONSOLE_STD
, 0},
5018 {FALSE
, CREATE_NEW_CONSOLE
, CONSOLE_STD
, 0},
5019 {FALSE
, CREATE_NO_WINDOW
, CONSOLE_STD
, 0},
5020 /*10*/ {FALSE
, DETACHED_PROCESS
| CREATE_NO_WINDOW
, CONSOLE_STD
, 0},
5021 {FALSE
, CREATE_NEW_CONSOLE
| CREATE_NO_WINDOW
, CONSOLE_STD
, 0},
5023 {FALSE
, 0, STARTUPINFO_STD
, 0},
5024 {FALSE
, DETACHED_PROCESS
, STARTUPINFO_STD
, 0},
5025 {FALSE
, CREATE_NEW_CONSOLE
, STARTUPINFO_STD
, 0},
5026 /*15*/ {FALSE
, CREATE_NO_WINDOW
, STARTUPINFO_STD
, 0},
5027 {FALSE
, DETACHED_PROCESS
| CREATE_NO_WINDOW
, STARTUPINFO_STD
, 0},
5028 {FALSE
, CREATE_NEW_CONSOLE
| CREATE_NO_WINDOW
, STARTUPINFO_STD
, 0},
5030 {TRUE
, 0, NULL_STD
, CP_WITH_CONSOLE
| CP_WITH_HANDLE
| CP_WITH_WINDOW
},
5031 {TRUE
, DETACHED_PROCESS
, NULL_STD
, 0},
5032 /*20*/ {TRUE
, CREATE_NEW_CONSOLE
, NULL_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
},
5033 {TRUE
, CREATE_NO_WINDOW
, NULL_STD
, CP_OWN_CONSOLE
},
5034 {TRUE
, DETACHED_PROCESS
| CREATE_NO_WINDOW
, NULL_STD
, 0},
5035 {TRUE
, CREATE_NEW_CONSOLE
| CREATE_NO_WINDOW
, NULL_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
},
5037 {TRUE
, 0, CONSOLE_STD
, CP_INH_CONSOLE
| CP_WITH_WINDOW
},
5038 /*25*/ {TRUE
, DETACHED_PROCESS
, CONSOLE_STD
, 0},
5039 {TRUE
, CREATE_NEW_CONSOLE
, CONSOLE_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
},
5040 {TRUE
, CREATE_NO_WINDOW
, CONSOLE_STD
, CP_OWN_CONSOLE
},
5041 {TRUE
, DETACHED_PROCESS
| CREATE_NO_WINDOW
, CONSOLE_STD
, 0},
5042 {TRUE
, CREATE_NEW_CONSOLE
| CREATE_NO_WINDOW
, CONSOLE_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
},
5044 /*30*/ {TRUE
, 0, STARTUPINFO_STD
, CP_INH_CONSOLE
| CP_WITH_WINDOW
},
5045 {TRUE
, DETACHED_PROCESS
, STARTUPINFO_STD
, CP_INPUT_VALID
| CP_OUTPUT_VALID
, .is_broken
= 0x100},
5046 {TRUE
, CREATE_NEW_CONSOLE
, STARTUPINFO_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
, .is_broken
= CP_WITH_CONSOLE
| CP_WITH_HANDLE
| CP_WITH_WINDOW
| CP_ALONE
},
5047 {TRUE
, CREATE_NO_WINDOW
, STARTUPINFO_STD
, CP_OWN_CONSOLE
, .is_broken
= CP_WITH_CONSOLE
| CP_WITH_HANDLE
| CP_ALONE
},
5048 {TRUE
, DETACHED_PROCESS
| CREATE_NO_WINDOW
, STARTUPINFO_STD
, CP_INPUT_VALID
| CP_OUTPUT_VALID
, .is_broken
= 0x100},
5049 /*35*/ {TRUE
, CREATE_NEW_CONSOLE
| CREATE_NO_WINDOW
, STARTUPINFO_STD
, CP_OWN_CONSOLE
| CP_WITH_WINDOW
, .is_broken
= CP_WITH_CONSOLE
| CP_WITH_HANDLE
| CP_WITH_WINDOW
| CP_ALONE
},
5051 static struct group_flags_tests
5056 enum inheritance_model inherit
;
5061 group_flags_tests
[] =
5063 /* 0 */ {TRUE
, 0, CONSOLE_STD
, TRUE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
},
5064 {TRUE
, CREATE_NEW_PROCESS_GROUP
, CONSOLE_STD
, TRUE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
| CP_GROUP_LEADER
},
5065 {TRUE
, 0, CONSOLE_STD
, FALSE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
| CP_ENABLED_CTRLC
},
5066 {TRUE
, CREATE_NEW_PROCESS_GROUP
, CONSOLE_STD
, FALSE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
| CP_GROUP_LEADER
},
5067 {TRUE
, 0, STARTUPINFO_STD
, TRUE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
},
5068 /* 5 */ {TRUE
, CREATE_NEW_PROCESS_GROUP
, STARTUPINFO_STD
, TRUE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
| CP_GROUP_LEADER
},
5069 {TRUE
, 0, STARTUPINFO_STD
, FALSE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
| CP_ENABLED_CTRLC
},
5070 {TRUE
, CREATE_NEW_PROCESS_GROUP
, STARTUPINFO_STD
, FALSE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
| CP_GROUP_LEADER
},
5071 {FALSE
, 0, CONSOLE_STD
, TRUE
, 0},
5072 {FALSE
, CREATE_NEW_PROCESS_GROUP
, CONSOLE_STD
, TRUE
, CP_GROUP_LEADER
},
5073 /* 10 */ {FALSE
, 0, CONSOLE_STD
, FALSE
, CP_ENABLED_CTRLC
},
5074 {FALSE
, CREATE_NEW_PROCESS_GROUP
, CONSOLE_STD
, FALSE
, CP_GROUP_LEADER
},
5075 {FALSE
, 0, STARTUPINFO_STD
, TRUE
, 0},
5076 {FALSE
, CREATE_NEW_PROCESS_GROUP
, STARTUPINFO_STD
, TRUE
, CP_GROUP_LEADER
},
5077 {FALSE
, 0, STARTUPINFO_STD
, FALSE
, CP_ENABLED_CTRLC
},
5078 /* 15 */ {FALSE
, CREATE_NEW_PROCESS_GROUP
, STARTUPINFO_STD
, FALSE
, CP_GROUP_LEADER
},
5079 {TRUE
, CREATE_NEW_PROCESS_GROUP
| CREATE_NEW_CONSOLE
, CONSOLE_STD
, TRUE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
| CP_GROUP_LEADER
| CP_ALONE
},
5080 {FALSE
, CREATE_NEW_PROCESS_GROUP
| CREATE_NEW_CONSOLE
, CONSOLE_STD
, TRUE
, CP_GROUP_LEADER
},
5081 {TRUE
, CREATE_NEW_PROCESS_GROUP
| CREATE_NEW_CONSOLE
, CONSOLE_STD
, FALSE
, CP_INH_CONSOLE
| CP_WITH_WINDOW
| CP_GROUP_LEADER
| CP_ALONE
| CP_ENABLED_CTRLC
},
5082 {FALSE
, CREATE_NEW_PROCESS_GROUP
| CREATE_NEW_CONSOLE
, CONSOLE_STD
, FALSE
, CP_GROUP_LEADER
| CP_ENABLED_CTRLC
},
5083 /* 20 */ {TRUE
, CREATE_NEW_PROCESS_GROUP
| DETACHED_PROCESS
, CONSOLE_STD
, TRUE
, CP_GROUP_LEADER
},
5084 {FALSE
, CREATE_NEW_PROCESS_GROUP
| DETACHED_PROCESS
, CONSOLE_STD
, TRUE
, CP_GROUP_LEADER
},
5085 {TRUE
, CREATE_NEW_PROCESS_GROUP
| DETACHED_PROCESS
, CONSOLE_STD
, FALSE
, CP_GROUP_LEADER
},
5086 {FALSE
, CREATE_NEW_PROCESS_GROUP
| DETACHED_PROCESS
, CONSOLE_STD
, FALSE
, CP_GROUP_LEADER
},
5089 hstd
[0] = GetStdHandle(STD_INPUT_HANDLE
);
5090 hstd
[1] = GetStdHandle(STD_OUTPUT_HANDLE
);
5091 hstd
[2] = GetStdHandle(STD_ERROR_HANDLE
);
5093 winetest_get_mainargs(&argv
);
5094 GetTempPathA(ARRAY_SIZE(guiexec
), guiexec
);
5095 strcat(guiexec
, "console_gui.exe");
5096 copy_change_subsystem(argv
[0], guiexec
, IMAGE_SUBSYSTEM_WINDOWS_GUI
);
5097 GetTempPathA(ARRAY_SIZE(cuiexec
), cuiexec
);
5098 strcat(cuiexec
, "console_cui.exe");
5099 copy_change_subsystem(argv
[0], cuiexec
, IMAGE_SUBSYSTEM_WINDOWS_CUI
);
5103 for (i
= 0; i
< ARRAY_SIZE(no_console_tests
); i
++)
5105 res
= check_child_console_bits(no_console_tests
[i
].use_cui
? cuiexec
: guiexec
,
5106 no_console_tests
[i
].cp_flags
,
5107 no_console_tests
[i
].inherit
);
5108 ok(res
== no_console_tests
[i
].expected
, "[%d] Unexpected result %x (%lx)\n",
5109 i
, res
, no_console_tests
[i
].expected
);
5114 for (i
= 0; i
< ARRAY_SIZE(with_console_tests
); i
++)
5116 res
= check_child_console_bits(with_console_tests
[i
].use_cui
? cuiexec
: guiexec
,
5117 with_console_tests
[i
].cp_flags
,
5118 with_console_tests
[i
].inherit
);
5119 ok(res
== with_console_tests
[i
].expected
||
5120 broken(with_console_tests
[i
].is_broken
&& res
== (with_console_tests
[i
].is_broken
& 0xff)),
5121 "[%d] Unexpected result %x (%lx)\n",
5122 i
, res
, with_console_tests
[i
].expected
);
5125 saved_console_flags
= RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
;
5127 for (i
= 0; i
< ARRAY_SIZE(group_flags_tests
); i
++)
5129 res
= SetConsoleCtrlHandler(NULL
, group_flags_tests
[i
].noctrl_flag
);
5130 ok(res
, "Couldn't set ctrl handler\n");
5131 res
= check_child_console_bits(group_flags_tests
[i
].use_cui
? cuiexec
: guiexec
,
5132 group_flags_tests
[i
].cp_flags
,
5133 group_flags_tests
[i
].inherit
);
5134 ok(res
== group_flags_tests
[i
].expected
||
5135 /* Win7 doesn't report group id */
5136 broken(res
== (group_flags_tests
[i
].expected
& ~CP_GROUP_LEADER
)),
5137 "[%d] Unexpected result %x (%lx)\n",
5138 i
, res
, group_flags_tests
[i
].expected
);
5141 RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
= saved_console_flags
;
5143 DeleteFileA(guiexec
);
5144 DeleteFileA(cuiexec
);
5146 SetStdHandle(STD_INPUT_HANDLE
, hstd
[0]);
5147 SetStdHandle(STD_OUTPUT_HANDLE
, hstd
[1]);
5148 SetStdHandle(STD_ERROR_HANDLE
, hstd
[2]);
5151 #define NO_EVENT 0xfe
5153 static HANDLE mch_child_kill_event
;
5154 static DWORD mch_child_event
= NO_EVENT
;
5155 static BOOL WINAPI
mch_child(DWORD event
)
5157 mch_child_event
= event
;
5158 SetEvent(mch_child_kill_event
);
5162 static void test_CtrlHandlerSubsystem(void)
5164 static char guiexec
[MAX_PATH
];
5165 static char cuiexec
[MAX_PATH
];
5172 enum pgid
{PGID_PARENT
, PGID_ZERO
, PGID_CHILD
} pgid_kind
;
5174 unsigned child_event
;
5178 /* 0 */ {FALSE
, 0, PGID_PARENT
, NO_EVENT
},
5179 {FALSE
, 0, PGID_ZERO
, NO_EVENT
},
5180 {FALSE
, CREATE_NEW_PROCESS_GROUP
, PGID_CHILD
, NO_EVENT
},
5181 {FALSE
, CREATE_NEW_PROCESS_GROUP
, PGID_PARENT
, NO_EVENT
},
5182 {FALSE
, CREATE_NEW_PROCESS_GROUP
, PGID_ZERO
, NO_EVENT
},
5183 /* 5 */ {TRUE
, 0, PGID_PARENT
, CTRL_C_EVENT
},
5184 {TRUE
, 0, PGID_ZERO
, CTRL_C_EVENT
},
5185 {TRUE
, CREATE_NEW_PROCESS_GROUP
, PGID_CHILD
, NO_EVENT
},
5186 {TRUE
, CREATE_NEW_PROCESS_GROUP
, PGID_PARENT
, NO_EVENT
},
5187 {TRUE
, CREATE_NEW_PROCESS_GROUP
, PGID_ZERO
, NO_EVENT
},
5188 /* 10 */ {TRUE
, CREATE_NEW_CONSOLE
, PGID_PARENT
, NO_EVENT
},
5189 {TRUE
, CREATE_NEW_CONSOLE
, PGID_ZERO
, NO_EVENT
},
5190 {TRUE
, DETACHED_PROCESS
, PGID_PARENT
, NO_EVENT
},
5191 {TRUE
, DETACHED_PROCESS
, PGID_ZERO
, NO_EVENT
},
5193 SECURITY_ATTRIBUTES inheritable_attr
= { sizeof(inheritable_attr
), NULL
, TRUE
};
5194 STARTUPINFOA si
= { sizeof(si
) };
5195 PROCESS_INFORMATION info
;
5200 DWORD saved_console_flags
;
5206 winetest_get_mainargs(&argv
);
5207 GetTempPathA(ARRAY_SIZE(guiexec
), guiexec
);
5208 strcat(guiexec
, "console_gui.exe");
5209 copy_change_subsystem(argv
[0], guiexec
, IMAGE_SUBSYSTEM_WINDOWS_GUI
);
5210 GetTempPathA(ARRAY_SIZE(cuiexec
), cuiexec
);
5211 strcat(cuiexec
, "console_cui.exe");
5212 copy_change_subsystem(argv
[0], cuiexec
, IMAGE_SUBSYSTEM_WINDOWS_CUI
);
5214 event_child
= CreateEventA(&inheritable_attr
, FALSE
, FALSE
, NULL
);
5215 ok(event_child
!= NULL
, "Couldn't create event\n");
5217 saved_console_flags
= RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
;
5219 /* protect self against ctrl-c, but don't mask it on child */
5220 ret
= SetConsoleCtrlHandler(NULL
, FALSE
);
5221 ret
= SetConsoleCtrlHandler(mydummych
, TRUE
);
5222 ok(ret
, "Couldn't set ctrl-c handler flag\n");
5224 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++)
5226 winetest_push_context("test #%u", i
);
5228 res
= snprintf(buf
, ARRAY_SIZE(buf
), "\"%s\" console ctrl_handler %p", tests
[i
].use_cui
? cuiexec
: guiexec
, event_child
);
5229 ok((LONG
)res
>= 0 && res
< ARRAY_SIZE(buf
), "Truncated string %s (%lu)\n", buf
, res
);
5231 ret
= CreateProcessA(NULL
, buf
, NULL
, NULL
, TRUE
, tests
[i
].cp_flags
,
5232 NULL
, NULL
, &si
, &info
);
5233 ok(ret
, "CreateProcess failed: %lu %s\n", GetLastError(), tests
[i
].use_cui
? cuiexec
: guiexec
);
5235 res
= WaitForSingleObject(event_child
, 5000);
5236 ok(res
== WAIT_OBJECT_0
, "Child didn't init %lu %p\n", res
, event_child
);
5238 switch (tests
[i
].pgid_kind
)
5241 pgid
= RtlGetCurrentPeb()->ProcessParameters
->ProcessGroupId
;
5244 ok((tests
[i
].cp_flags
& CREATE_NEW_PROCESS_GROUP
) != 0,
5245 "PGID should only be used with new process groupw\n");
5246 pgid
= info
.dwProcessId
;
5252 ok(0, "Unexpected pgid kind %u\n", tests
[i
].pgid_kind
);
5256 ret
= GenerateConsoleCtrlEvent(CTRL_C_EVENT
, pgid
);
5257 ok(ret
|| broken(GetLastError() == ERROR_INVALID_PARAMETER
) /* Win7 */,
5258 "GenerateConsoleCtrlEvent failed: %lu\n", GetLastError());
5260 res
= WaitForSingleObject(info
.hProcess
, 2000);
5261 ok(res
== WAIT_OBJECT_0
, "Expecting child to be terminated\n");
5265 ret
= GetExitCodeProcess(info
.hProcess
, &exit_code
);
5266 ok(ret
, "Couldn't get exit code\n");
5268 ok(tests
[i
].child_event
== exit_code
, "Unexpected exit code %#lx, instead of %#x\n",
5269 exit_code
, tests
[i
].child_event
);
5272 CloseHandle(info
.hProcess
);
5273 CloseHandle(info
.hThread
);
5274 winetest_pop_context();
5277 CloseHandle(event_child
);
5279 RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
= saved_console_flags
;
5280 ret
= SetConsoleCtrlHandler(mydummych
, FALSE
);
5281 ok(ret
, "Couldn't remove ctrl-c handler flag\n");
5283 DeleteFileA(guiexec
);
5284 DeleteFileA(cuiexec
);
5289 HANDLE hConIn
, hConOut
, revert_output
= NULL
, unbound_output
;
5290 BOOL ret
, test_current
;
5291 CONSOLE_SCREEN_BUFFER_INFO sbi
;
5292 BOOL using_pseudo_console
;
5297 init_function_pointers();
5299 argc
= winetest_get_mainargs(&argv
);
5301 if (argc
> 3 && !strcmp(argv
[2], "attach_console"))
5304 sscanf(argv
[3], "%lx", &parent_pid
);
5305 test_AttachConsole_child(parent_pid
);
5309 if (argc
== 3 && !strcmp(argv
[2], "alloc_console"))
5311 test_AllocConsole_child();
5315 if (argc
== 4 && !strcmp(argv
[2], "ctrl_handler"))
5319 SetConsoleCtrlHandler(mch_child
, TRUE
);
5320 mch_child_kill_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
5321 ok(mch_child_kill_event
!= NULL
, "Couldn't create event\n");
5322 sscanf(argv
[3], "%p", &event
);
5323 ret
= SetEvent(event
);
5324 ok(ret
, "SetEvent failed\n");
5326 WaitForSingleObject(mch_child_kill_event
, 1000); /* enough for all events to be distributed? */
5327 ExitProcess(mch_child_event
);
5330 if (argc
== 3 && !strcmp(argv
[2], "check_console"))
5332 DWORD exit_code
= 0, pcslist
;
5333 if (GetConsoleCP() != 0) exit_code
|= CP_WITH_CONSOLE
;
5334 if (RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
) exit_code
|= CP_WITH_HANDLE
;
5335 if (IsWindow(GetConsoleWindow())) exit_code
|= CP_WITH_WINDOW
;
5336 if (pGetConsoleProcessList
&& GetConsoleProcessList(&pcslist
, 1) == 1)
5337 exit_code
|= CP_ALONE
;
5338 if (RtlGetCurrentPeb()->ProcessParameters
->Size
>=
5339 offsetof(RTL_USER_PROCESS_PARAMETERS
, ProcessGroupId
) +
5340 sizeof(RtlGetCurrentPeb()->ProcessParameters
->ProcessGroupId
) &&
5341 RtlGetCurrentPeb()->ProcessParameters
->ProcessGroupId
== GetCurrentProcessId())
5342 exit_code
|= CP_GROUP_LEADER
;
5343 if (GetFileType(GetStdHandle(STD_INPUT_HANDLE
)) == FILE_TYPE_CHAR
)
5344 exit_code
|= CP_INPUT_VALID
;
5345 if (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE
)) == FILE_TYPE_CHAR
)
5346 exit_code
|= CP_OUTPUT_VALID
;
5347 if (!(RtlGetCurrentPeb()->ProcessParameters
->ConsoleFlags
& 1))
5348 exit_code
|= CP_ENABLED_CTRLC
;
5349 ExitProcess(exit_code
);
5352 if (argc
>= 3 && !strcmp(argv
[2], "title_test"))
5356 test_GetConsoleOriginalTitleA();
5357 test_GetConsoleOriginalTitleW();
5360 test_GetConsoleOriginalTitleW_empty();
5364 test_current
= argc
>= 3 && !strcmp(argv
[2], "--current");
5365 using_pseudo_console
= argc
>= 3 && !strcmp(argv
[2], "--pseudo-console");
5367 if (!test_current
&& !using_pseudo_console
)
5369 static const char font_name
[] = "Lucida Console";
5371 char old_font
[LF_FACESIZE
];
5372 BOOL
delete = FALSE
;
5375 /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
5376 * correctly for characters that don't have a glyph in the console font. So,
5377 * we first set the console font to Lucida Console (which has a wider
5378 * selection of glyphs available than the default raster fonts). We want
5379 * to be able to restore the original font afterwards, so don't change
5380 * if we can't read the original font.
5382 err
= RegOpenKeyExA(HKEY_CURRENT_USER
, "Console", 0,
5383 KEY_QUERY_VALUE
| KEY_SET_VALUE
, &console_key
);
5384 if (err
== ERROR_SUCCESS
)
5386 size
= sizeof(old_font
);
5387 err
= RegQueryValueExA(console_key
, "FaceName", NULL
, NULL
,
5388 (LPBYTE
) old_font
, &size
);
5389 if (err
== ERROR_SUCCESS
|| err
== ERROR_FILE_NOT_FOUND
)
5391 delete = (err
== ERROR_FILE_NOT_FOUND
);
5392 err
= RegSetValueExA(console_key
, "FaceName", 0, REG_SZ
,
5393 (const BYTE
*) font_name
, sizeof(font_name
));
5394 if (err
!= ERROR_SUCCESS
)
5395 trace("Unable to change default console font, error %ld\n", err
);
5399 trace("Unable to query default console font, error %ld\n", err
);
5400 RegCloseKey(console_key
);
5406 trace("Unable to open HKCU\\Console, error %ld\n", err
);
5410 /* Now detach and open a fresh console to play with */
5412 ok(AllocConsole(), "Couldn't alloc console\n");
5414 /* Restore default console font if needed */
5415 if (console_key
!= NULL
)
5418 err
= RegDeleteValueA(console_key
, "FaceName");
5420 err
= RegSetValueExA(console_key
, "FaceName", 0, REG_SZ
,
5421 (const BYTE
*) old_font
, strlen(old_font
) + 1);
5422 ok(err
== ERROR_SUCCESS
, "Unable to restore default console font, error %ld\n", err
);
5426 unbound_output
= create_unbound_handle(TRUE
, FALSE
);
5427 if (!unbound_output
)
5429 win_skip("Skipping NT path tests, not supported on this Windows version\n");
5436 revert_output
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
5437 sb
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
5438 CONSOLE_TEXTMODE_BUFFER
, NULL
);
5439 ok(sb
!= INVALID_HANDLE_VALUE
, "Could not allocate screen buffer: %lu\n", GetLastError());
5440 SetConsoleActiveScreenBuffer(sb
);
5443 hConIn
= CreateFileA("CONIN$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
5444 hConOut
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
5446 /* now verify everything's ok */
5447 ok(hConIn
!= INVALID_HANDLE_VALUE
, "Opening ConIn\n");
5448 ok(hConOut
!= INVALID_HANDLE_VALUE
, "Opening ConOut\n");
5450 if (using_pseudo_console
)
5452 test_pseudo_console_child(hConIn
, hConOut
);
5456 ret
= GetConsoleScreenBufferInfo(hConOut
, &sbi
);
5457 ok(ret
, "Getting sb info\n");
5460 /* Reduce the size of the buffer to the visible area plus 3 lines to speed
5463 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
);
5464 sbi
.dwSize
.Y
= size
= (sbi
.srWindow
.Bottom
+ 1) + 3;
5465 ret
= SetConsoleScreenBufferSize(hConOut
, sbi
.dwSize
);
5466 ok(ret
, "Setting sb info\n");
5467 ret
= GetConsoleScreenBufferInfo(hConOut
, &sbi
);
5468 ok(ret
, "Getting sb info\n");
5469 ok(sbi
.dwSize
.Y
== size
, "Unexpected buffer size: %d instead of %ld\n", sbi
.dwSize
.Y
, size
);
5472 test_ReadConsole(hConIn
);
5473 /* Non interactive tests */
5474 testCursor(hConOut
, sbi
.dwSize
);
5475 /* test parameters (FIXME: test functionality) */
5476 testCursorInfo(hConOut
);
5477 /* will test wrapped (on/off) & processed (on/off) strings output */
5478 testWrite(hConOut
, sbi
.dwSize
);
5479 /* will test line scrolling at the bottom of the screen */
5480 /* testBottomScroll(); */
5481 /* will test all the scrolling operations */
5482 testScroll(hConOut
, sbi
.dwSize
);
5483 /* will test sb creation / modification / codepage handling */
5484 if (!test_current
) testScreenBuffer(hConOut
);
5485 test_new_screen_buffer_properties(hConOut
);
5486 test_new_screen_buffer_color_attributes(hConOut
);
5487 /* Test waiting for a console handle */
5488 testWaitForConsoleInput(hConIn
);
5489 test_wait(hConIn
, hConOut
);
5493 /* clear duplicated console font table */
5494 CloseHandle(hConIn
);
5495 CloseHandle(hConOut
);
5497 ok(AllocConsole(), "Couldn't alloc console\n");
5498 hConIn
= CreateFileA("CONIN$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
5499 hConOut
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
5500 ok(hConIn
!= INVALID_HANDLE_VALUE
, "Opening ConIn\n");
5501 ok(hConOut
!= INVALID_HANDLE_VALUE
, "Opening ConOut\n");
5505 /* still to be done: access rights & access on objects */
5507 if (!pGetConsoleInputExeNameA
|| !pSetConsoleInputExeNameA
)
5508 win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
5510 test_GetSetConsoleInputExeName();
5512 if (!test_current
) test_GetConsoleProcessList();
5513 test_OpenConsoleW();
5516 test_VerifyConsoleIoHandle(hConOut
);
5517 test_GetSetStdHandle();
5518 test_DuplicateConsoleHandle();
5519 test_GetNumberOfConsoleInputEvents(hConIn
);
5520 test_WriteConsoleInputA(hConIn
);
5521 test_WriteConsoleInputW(hConIn
);
5522 test_FlushConsoleInputBuffer(hConIn
, hConOut
);
5523 test_WriteConsoleOutputCharacterA(hConOut
);
5524 test_WriteConsoleOutputCharacterW(hConOut
);
5525 test_WriteConsoleOutputAttribute(hConOut
);
5526 test_WriteConsoleOutput(hConOut
);
5527 test_FillConsoleOutputCharacterA(hConOut
);
5528 test_FillConsoleOutputCharacterW(hConOut
);
5529 test_FillConsoleOutputAttribute(hConOut
);
5530 test_ReadConsoleOutputCharacterA(hConOut
);
5531 test_ReadConsoleOutputCharacterW(hConOut
);
5532 test_ReadConsoleOutputAttribute(hConOut
);
5533 test_ReadConsoleOutput(hConOut
);
5536 test_GetCurrentConsoleFont(hConOut
);
5537 test_GetCurrentConsoleFontEx(hConOut
);
5538 test_SetCurrentConsoleFontEx(hConOut
);
5539 test_GetConsoleFontSize(hConOut
);
5540 test_GetLargestConsoleWindowSize(hConOut
);
5541 test_GetConsoleFontInfo(hConOut
);
5542 test_SetConsoleFont(hConOut
);
5544 test_GetConsoleScreenBufferInfoEx(hConOut
);
5545 test_SetConsoleScreenBufferInfoEx(hConOut
);
5546 test_file_info(hConIn
, hConOut
);
5547 test_GetConsoleOriginalTitle();
5548 test_GetConsoleTitleA();
5549 test_GetConsoleTitleW();
5552 test_pseudo_console();
5553 test_AttachConsole(hConOut
);
5554 test_AllocConsole();
5556 test_CreateProcessCUI();
5557 test_CtrlHandlerSubsystem();
5559 else if (revert_output
) SetConsoleActiveScreenBuffer(revert_output
);
5561 CloseHandle(unbound_output
);