2 * Unit tests for console API
4 * Copyright (c) 2003,2004 Eric Pouech
5 * Copyright (c) 2007 Kirill K. Smirnov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
26 static BOOL (WINAPI
*pGetConsoleInputExeNameA
)(DWORD
, LPSTR
);
27 static DWORD (WINAPI
*pGetConsoleProcessList
)(LPDWORD
, DWORD
);
28 static HANDLE (WINAPI
*pOpenConsoleW
)(LPCWSTR
,DWORD
,BOOL
,DWORD
);
29 static BOOL (WINAPI
*pSetConsoleInputExeNameA
)(LPCSTR
);
31 /* DEFAULT_ATTRIB is used for all initial filling of the console.
32 * all modifications are made with TEST_ATTRIB so that we could check
33 * what has to be modified or not
35 #define TEST_ATTRIB (BACKGROUND_BLUE | FOREGROUND_GREEN)
36 #define DEFAULT_ATTRIB (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED)
37 /* when filling the screen with non-blank chars, this macro defines
38 * what character should be at position 'c'
40 #define CONTENT(c) ('A' + (((c).Y * 17 + (c).X) % 23))
42 #define okCURSOR(hCon, c) do { \
43 CONSOLE_SCREEN_BUFFER_INFO __sbi; \
44 BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
45 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
46 ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
47 (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
50 #define okCHAR(hCon, c, ch, attr) do { \
51 char __ch; WORD __attr; DWORD __len; BOOL expect; \
52 expect = ReadConsoleOutputCharacter((hCon), &__ch, 1, (c), &__len) == 1 && __len == 1 && __ch == (ch); \
53 ok(expect, "At (%d,%d): expecting char '%c'/%02x got '%c'/%02x\n", (c).X, (c).Y, (ch), (ch), __ch, __ch); \
54 expect = ReadConsoleOutputAttribute((hCon), &__attr, 1, (c), &__len) == 1 && __len == 1 && __attr == (attr); \
55 ok(expect, "At (%d,%d): expecting attr %04x got %04x\n", (c).X, (c).Y, (attr), __attr); \
58 static void init_function_pointers(void)
62 #define KERNEL32_GET_PROC(func) \
63 p##func = (void *)GetProcAddress(hKernel32, #func); \
64 if(!p##func) trace("GetProcAddress(hKernel32, '%s') failed\n", #func);
66 hKernel32
= GetModuleHandleA("kernel32.dll");
67 KERNEL32_GET_PROC(GetConsoleInputExeNameA
);
68 KERNEL32_GET_PROC(GetConsoleProcessList
);
69 KERNEL32_GET_PROC(OpenConsoleW
);
70 KERNEL32_GET_PROC(SetConsoleInputExeNameA
);
72 #undef KERNEL32_GET_PROC
75 /* FIXME: this could be optimized on a speed point of view */
76 static void resetContent(HANDLE hCon
, COORD sbSize
, BOOL content
)
79 WORD attr
= DEFAULT_ATTRIB
;
83 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
85 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
87 ch
= (content
) ? CONTENT(c
) : ' ';
88 WriteConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
89 WriteConsoleOutputCharacterA(hCon
, &ch
, 1, c
, &len
);
94 static void testCursor(HANDLE hCon
, COORD sbSize
)
99 ok(SetConsoleCursorPosition(0, c
) == 0, "No handle\n");
100 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %u\n",
101 ERROR_INVALID_HANDLE
, GetLastError());
104 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
109 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in lower-right\n");
114 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
115 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %u\n",
116 ERROR_INVALID_PARAMETER
, GetLastError());
120 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
121 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %u\n",
122 ERROR_INVALID_PARAMETER
, GetLastError());
126 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
127 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %u\n",
128 ERROR_INVALID_PARAMETER
, GetLastError());
132 ok(SetConsoleCursorPosition(hCon
, c
) == 0, "Cursor is outside\n");
133 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError: expecting %u got %u\n",
134 ERROR_INVALID_PARAMETER
, GetLastError());
137 static void testCursorInfo(HANDLE hCon
)
140 CONSOLE_CURSOR_INFO info
;
142 SetLastError(0xdeadbeef);
143 ret
= GetConsoleCursorInfo(NULL
, NULL
);
144 ok(!ret
, "Expected failure\n");
145 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %u\n",
146 ERROR_INVALID_HANDLE
, GetLastError());
148 SetLastError(0xdeadbeef);
150 ret
= GetConsoleCursorInfo(NULL
, &info
);
151 ok(!ret
, "Expected failure\n");
152 ok(info
.dwSize
== -1, "Expected no change for dwSize\n");
153 ok(GetLastError() == ERROR_INVALID_HANDLE
, "GetLastError: expecting %u got %u\n",
154 ERROR_INVALID_HANDLE
, GetLastError());
156 /* Test the correct call first to distinguish between win9x and the rest */
157 SetLastError(0xdeadbeef);
158 ret
= GetConsoleCursorInfo(hCon
, &info
);
159 ok(ret
, "Expected success\n");
160 ok(info
.dwSize
== 25 ||
161 info
.dwSize
== 12 /* win9x */,
162 "Expected 12 or 25, got %d\n", info
.dwSize
);
163 ok(info
.bVisible
, "Expected the cursor to be visible\n");
164 ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %u\n",
165 0xdeadbeef, GetLastError());
167 /* Don't test NULL CONSOLE_CURSOR_INFO, it crashes on win9x and win7 */
170 static void testEmptyWrite(HANDLE hCon
)
174 const char* mytest
= "";
177 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
180 ok(WriteConsole(hCon
, NULL
, 0, &len
, NULL
) != 0 && len
== 0, "WriteConsole\n");
183 /* Passing a NULL lpBuffer with sufficiently large non-zero length succeeds
184 * on native Windows and result in memory-like contents being written to
185 * the console. Calling WriteConsoleW like this will crash on Wine. */
189 ok(!WriteConsole(hCon
, NULL
, 16, &len
, NULL
) && len
== -1, "WriteConsole\n");
192 /* Cursor advances for this call. */
194 ok(WriteConsole(hCon
, NULL
, 128, &len
, NULL
) != 0 && len
== 128, "WriteConsole\n");
198 ok(WriteConsole(hCon
, mytest
, 0, &len
, NULL
) != 0 && len
== 0, "WriteConsole\n");
201 /* WriteConsole does not halt on a null terminator and is happy to write
202 * memory contents beyond the actual size of the buffer. */
204 ok(WriteConsole(hCon
, mytest
, 16, &len
, NULL
) != 0 && len
== 16, "WriteConsole\n");
209 static void testWriteSimple(HANDLE hCon
)
213 const char* mytest
= "abcdefg";
214 const int mylen
= strlen(mytest
);
216 /* single line write */
218 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left\n");
220 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
222 for (c
.X
= 0; c
.X
< mylen
; c
.X
++)
224 okCHAR(hCon
, c
, mytest
[c
.X
], TEST_ATTRIB
);
228 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
231 static void testWriteNotWrappedNotProcessed(HANDLE hCon
, COORD sbSize
)
235 const char* mytest
= "123";
236 const int mylen
= strlen(mytest
);
240 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, mode
& ~(ENABLE_PROCESSED_OUTPUT
|ENABLE_WRAP_AT_EOL_OUTPUT
)),
241 "clearing wrap at EOL & processed output\n");
243 /* write line, wrapping disabled, buffer exceeds sb width */
244 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
245 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
247 ret
= WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
);
248 ok(ret
!= 0 && len
== mylen
, "Couldn't write, ret = %d, len = %d\n", ret
, len
);
250 for (p
= mylen
- 3; p
< mylen
; p
++)
252 c
.X
= sbSize
.X
- 3 + p
% 3;
253 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
257 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
259 p
= sbSize
.X
- 3 + mylen
% 3;
262 /* write line, wrapping disabled, strings end on end of line */
263 c
.X
= sbSize
.X
- mylen
; c
.Y
= 0;
264 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
266 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
269 static void testWriteNotWrappedProcessed(HANDLE hCon
, COORD sbSize
)
273 const char* mytest
= "abcd\nf\tg";
274 const int mylen
= strlen(mytest
);
275 const int mylen2
= strchr(mytest
, '\n') - mytest
;
279 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, (mode
| ENABLE_PROCESSED_OUTPUT
) & ~ENABLE_WRAP_AT_EOL_OUTPUT
),
280 "clearing wrap at EOL & setting processed output\n");
282 /* write line, wrapping disabled, buffer exceeds sb width */
283 c
.X
= sbSize
.X
- 5; c
.Y
= 0;
284 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-5\n");
286 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
288 for (c
.X
= sbSize
.X
- 5; c
.X
< sbSize
.X
- 1; c
.X
++)
290 okCHAR(hCon
, c
, mytest
[c
.X
- sbSize
.X
+ 5], TEST_ATTRIB
);
293 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
294 /* Win9x and WinMe change the attribs for '\n' up to 'f' */
295 if (attr
== TEST_ATTRIB
)
297 win_skip("Win9x/WinMe don't respect ~ENABLE_WRAP_AT_EOL_OUTPUT\n");
301 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
304 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
305 for (c
.X
= 1; c
.X
< 8; c
.X
++)
306 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
307 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
309 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
313 /* write line, wrapping disabled, strings end on end of line */
314 c
.X
= sbSize
.X
- 4; c
.Y
= 0;
315 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-4\n");
317 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
319 for (c
.X
= sbSize
.X
- 4; c
.X
< sbSize
.X
; c
.X
++)
321 okCHAR(hCon
, c
, mytest
[c
.X
- sbSize
.X
+ 4], TEST_ATTRIB
);
324 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
325 for (c
.X
= 1; c
.X
< 8; c
.X
++)
326 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
327 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
329 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
333 /* write line, wrapping disabled, strings end after end of line */
334 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
335 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-4\n");
337 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
339 for (p
= mylen2
- 3; p
< mylen2
; p
++)
341 c
.X
= sbSize
.X
- 3 + p
% 3;
342 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
345 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
346 for (c
.X
= 1; c
.X
< 8; c
.X
++)
347 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
348 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
350 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
355 static void testWriteWrappedNotProcessed(HANDLE hCon
, COORD sbSize
)
359 const char* mytest
= "abcd\nf\tg";
360 const int mylen
= strlen(mytest
);
363 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
,(mode
| ENABLE_WRAP_AT_EOL_OUTPUT
) & ~(ENABLE_PROCESSED_OUTPUT
)),
364 "setting wrap at EOL & clearing processed output\n");
366 /* write line, wrapping enabled, buffer doesn't exceed sb width */
367 c
.X
= sbSize
.X
- 9; c
.Y
= 0;
368 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-9\n");
370 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
372 for (p
= 0; p
< mylen
; p
++)
374 c
.X
= sbSize
.X
- 9 + p
;
375 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
377 c
.X
= sbSize
.X
- 9 + mylen
;
378 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
380 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
382 /* write line, wrapping enabled, buffer does exceed sb width */
383 c
.X
= sbSize
.X
- 3; c
.Y
= 0;
384 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
388 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
391 static void testWriteWrappedProcessed(HANDLE hCon
, COORD sbSize
)
395 const char* mytest
= "abcd\nf\tg";
396 const int mylen
= strlen(mytest
);
400 ok(GetConsoleMode(hCon
, &mode
) && SetConsoleMode(hCon
, mode
| (ENABLE_WRAP_AT_EOL_OUTPUT
|ENABLE_PROCESSED_OUTPUT
)),
401 "setting wrap at EOL & processed output\n");
403 /* write line, wrapping enabled, buffer doesn't exceed sb width */
404 c
.X
= sbSize
.X
- 9; c
.Y
= 0;
405 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-9\n");
407 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
408 for (p
= 0; p
< 4; p
++)
410 c
.X
= sbSize
.X
- 9 + p
;
411 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
413 c
.X
= sbSize
.X
- 9 + p
;
414 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
415 if (attr
== TEST_ATTRIB
)
416 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n");
418 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
420 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
421 for (c
.X
= 1; c
.X
< 8; c
.X
++)
422 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
423 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
425 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
428 /* write line, wrapping enabled, buffer does exceed sb width */
429 c
.X
= sbSize
.X
- 3; c
.Y
= 2;
430 ok(SetConsoleCursorPosition(hCon
, c
) != 0, "Cursor in upper-left-3\n");
432 ok(WriteConsole(hCon
, mytest
, mylen
, &len
, NULL
) != 0 && len
== mylen
, "WriteConsole\n");
433 for (p
= 0; p
< 3; p
++)
435 c
.X
= sbSize
.X
- 3 + p
;
436 okCHAR(hCon
, c
, mytest
[p
], TEST_ATTRIB
);
439 okCHAR(hCon
, c
, mytest
[3], TEST_ATTRIB
);
441 ReadConsoleOutputAttribute(hCon
, &attr
, 1, c
, &len
);
442 if (attr
== TEST_ATTRIB
)
443 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n");
445 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
448 okCHAR(hCon
, c
, mytest
[5], TEST_ATTRIB
);
449 for (c
.X
= 1; c
.X
< 8; c
.X
++)
450 okCHAR(hCon
, c
, ' ', TEST_ATTRIB
);
451 okCHAR(hCon
, c
, mytest
[7], TEST_ATTRIB
);
453 okCHAR(hCon
, c
, ' ', DEFAULT_ATTRIB
);
457 static void testWrite(HANDLE hCon
, COORD sbSize
)
459 /* FIXME: should in fact insure that the sb is at least 10 character wide */
460 ok(SetConsoleTextAttribute(hCon
, TEST_ATTRIB
), "Setting default text color\n");
461 resetContent(hCon
, sbSize
, FALSE
);
462 testEmptyWrite(hCon
);
463 resetContent(hCon
, sbSize
, FALSE
);
464 testWriteSimple(hCon
);
465 resetContent(hCon
, sbSize
, FALSE
);
466 testWriteNotWrappedNotProcessed(hCon
, sbSize
);
467 resetContent(hCon
, sbSize
, FALSE
);
468 testWriteNotWrappedProcessed(hCon
, sbSize
);
469 resetContent(hCon
, sbSize
, FALSE
);
470 testWriteWrappedNotProcessed(hCon
, sbSize
);
471 resetContent(hCon
, sbSize
, FALSE
);
472 testWriteWrappedProcessed(hCon
, sbSize
);
475 static void testScroll(HANDLE hCon
, COORD sbSize
)
477 SMALL_RECT scroll
, clip
;
485 #define IN_SRECT(r,c) ((r).Left <= (c).X && (c).X <= (r).Right && (r).Top <= (c).Y && (c).Y <= (r).Bottom)
486 #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)
488 /* no clipping, src & dst rect don't overlap */
489 resetContent(hCon
, sbSize
, TRUE
);
492 scroll
.Right
= W
- 1;
494 scroll
.Bottom
= H
- 1;
497 ci
.Char
.UnicodeChar
= '#';
498 ci
.Attributes
= TEST_ATTRIB
;
501 clip
.Right
= sbSize
.X
- 1;
503 clip
.Bottom
= sbSize
.Y
- 1;
505 ok(ScrollConsoleScreenBuffer(hCon
, &scroll
, NULL
, dst
, &ci
), "Scrolling SB\n");
507 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
509 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
511 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
515 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
517 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
518 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
519 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
523 /* no clipping, src & dst rect do overlap */
524 resetContent(hCon
, sbSize
, TRUE
);
527 scroll
.Right
= W
- 1;
529 scroll
.Bottom
= H
- 1;
532 ci
.Char
.UnicodeChar
= '#';
533 ci
.Attributes
= TEST_ATTRIB
;
536 clip
.Right
= sbSize
.X
- 1;
538 clip
.Bottom
= sbSize
.Y
- 1;
540 ok(ScrollConsoleScreenBuffer(hCon
, &scroll
, NULL
, dst
, &ci
), "Scrolling SB\n");
542 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
544 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
546 if (dst
.X
<= c
.X
&& c
.X
< dst
.X
+ W
&& dst
.Y
<= c
.Y
&& c
.Y
< dst
.Y
+ H
)
550 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
552 else if (c
.X
< W
&& c
.Y
< H
) okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
553 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
557 /* clipping, src & dst rect don't overlap */
558 resetContent(hCon
, sbSize
, TRUE
);
561 scroll
.Right
= W
- 1;
563 scroll
.Bottom
= H
- 1;
566 ci
.Char
.UnicodeChar
= '#';
567 ci
.Attributes
= TEST_ATTRIB
;
570 clip
.Right
= min(W
+ W
/ 2, sbSize
.X
- 1);
572 clip
.Bottom
= min(H
+ H
/ 2, sbSize
.Y
- 1);
574 SetLastError(0xdeadbeef);
575 ret
= ScrollConsoleScreenBuffer(hCon
, &scroll
, &clip
, dst
, &ci
);
578 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
580 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
582 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
586 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
588 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
589 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
590 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
596 /* Win9x will fail, Only accept ERROR_NOT_ENOUGH_MEMORY */
597 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY
,
598 "Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
601 /* clipping, src & dst rect do overlap */
602 resetContent(hCon
, sbSize
, TRUE
);
605 scroll
.Right
= W
- 1;
607 scroll
.Bottom
= H
- 1;
610 ci
.Char
.UnicodeChar
= '#';
611 ci
.Attributes
= TEST_ATTRIB
;
614 clip
.Right
= min(W
+ W
/ 2, sbSize
.X
- 1);
616 clip
.Bottom
= min(H
+ H
/ 2, sbSize
.Y
- 1);
618 ok(ScrollConsoleScreenBuffer(hCon
, &scroll
, &clip
, dst
, &ci
), "Scrolling SB\n");
620 for (c
.Y
= 0; c
.Y
< sbSize
.Y
; c
.Y
++)
622 for (c
.X
= 0; c
.X
< sbSize
.X
; c
.X
++)
624 if (IN_SRECT2(scroll
, dst
, c
) && IN_SRECT(clip
, c
))
628 okCHAR(hCon
, c
, CONTENT(tc
), DEFAULT_ATTRIB
);
630 else if (IN_SRECT(scroll
, c
) && IN_SRECT(clip
, c
))
631 okCHAR(hCon
, c
, '#', TEST_ATTRIB
);
632 else okCHAR(hCon
, c
, CONTENT(c
), DEFAULT_ATTRIB
);
637 static int mch_count
;
638 /* we need the event as Wine console event generation isn't synchronous
639 * (ie GenerateConsoleCtrlEvent returns before all ctrl-handlers in all
640 * processes have been called).
642 static HANDLE mch_event
;
643 static BOOL WINAPI
mch(DWORD event
)
650 static void testCtrlHandler(void)
652 ok(!SetConsoleCtrlHandler(mch
, FALSE
), "Shouldn't succeed\n");
653 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Bad error %u\n", GetLastError());
654 ok(SetConsoleCtrlHandler(mch
, TRUE
), "Couldn't set handler\n");
655 /* wine requires the event for the test, as we cannot insure, so far, that event
656 * are processed synchronously in GenerateConsoleCtrlEvent()
658 mch_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
660 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT
, 0), "Couldn't send ctrl-c event\n");
661 /* FIXME: it isn't synchronous on wine but it can still happen before we test */
662 if (0) ok(mch_count
== 1, "Event isn't synchronous\n");
663 ok(WaitForSingleObject(mch_event
, 3000) == WAIT_OBJECT_0
, "event sending didn't work\n");
664 CloseHandle(mch_event
);
666 /* Turning off ctrl-c handling doesn't work on win9x such way ... */
667 ok(SetConsoleCtrlHandler(NULL
, TRUE
), "Couldn't turn off ctrl-c handling\n");
668 mch_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
670 if(!(GetVersion() & 0x80000000))
671 /* ... and next line leads to an unhandled exception on 9x. Avoid it on 9x. */
672 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT
, 0), "Couldn't send ctrl-c event\n");
673 ok(WaitForSingleObject(mch_event
, 3000) == WAIT_TIMEOUT
&& mch_count
== 0, "Event shouldn't have been sent\n");
674 CloseHandle(mch_event
);
675 ok(SetConsoleCtrlHandler(mch
, FALSE
), "Couldn't remove handler\n");
676 ok(!SetConsoleCtrlHandler(mch
, FALSE
), "Shouldn't succeed\n");
677 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Bad error %u\n", GetLastError());
681 * Test console screen buffer:
682 * 1) Try to set invalid handle.
683 * 2) Try to set non-console handles.
684 * 3) Use CONOUT$ file as active SB.
686 * 5) Test output codepage to show it is not a property of SB.
687 * 6) Test switching to old SB if we close all handles to current SB - works
688 * in Windows, TODO in wine.
690 * What is not tested but should be:
691 * 1) ScreenBufferInfo
693 static void testScreenBuffer(HANDLE hConOut
)
695 HANDLE hConOutRW
, hConOutRO
, hConOutWT
;
696 HANDLE hFileOutRW
, hFileOutRO
, hFileOutWT
;
698 char test_str1
[] = "Test for SB1";
699 char test_str2
[] = "Test for SB2";
700 char test_cp866
[] = {0xe2, 0xa5, 0xe1, 0xe2, 0};
701 char test_cp1251
[] = {0xf2, 0xe5, 0xf1, 0xf2, 0};
702 WCHAR test_unicode
[] = {0x0442, 0x0435, 0x0441, 0x0442, 0};
710 if (!IsValidCodePage(866))
712 skip("Codepage 866 not available\n");
716 /* In the beginning set output codepage to 866 */
717 oldcp
= GetConsoleOutputCP();
718 SetLastError(0xdeadbeef);
719 ret
= SetConsoleOutputCP(866);
720 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
722 win_skip("SetConsoleOutputCP is not implemented\n");
725 ok(ret
, "Cannot set output codepage to 866\n");
727 hConOutRW
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
728 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
729 CONSOLE_TEXTMODE_BUFFER
, NULL
);
730 ok(hConOutRW
!= INVALID_HANDLE_VALUE
,
731 "Cannot create a new screen buffer for ReadWrite\n");
732 hConOutRO
= CreateConsoleScreenBuffer(GENERIC_READ
,
733 FILE_SHARE_READ
, NULL
,
734 CONSOLE_TEXTMODE_BUFFER
, NULL
);
735 ok(hConOutRO
!= INVALID_HANDLE_VALUE
,
736 "Cannot create a new screen buffer for ReadOnly\n");
737 hConOutWT
= CreateConsoleScreenBuffer(GENERIC_WRITE
,
738 FILE_SHARE_WRITE
, NULL
,
739 CONSOLE_TEXTMODE_BUFFER
, NULL
);
740 ok(hConOutWT
!= INVALID_HANDLE_VALUE
,
741 "Cannot create a new screen buffer for WriteOnly\n");
743 hFileOutRW
= CreateFileA("NUL", GENERIC_READ
| GENERIC_WRITE
,
744 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
745 OPEN_EXISTING
, 0, NULL
);
746 ok(hFileOutRW
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for ReadWrite\n");
747 hFileOutRO
= CreateFileA("NUL", GENERIC_READ
, FILE_SHARE_READ
,
748 NULL
, OPEN_EXISTING
, 0, NULL
);
749 ok(hFileOutRO
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for ReadOnly\n");
750 hFileOutWT
= CreateFileA("NUL", GENERIC_WRITE
, FILE_SHARE_WRITE
,
751 NULL
, OPEN_EXISTING
, 0, NULL
);
752 ok(hFileOutWT
!= INVALID_HANDLE_VALUE
, "Cannot open NUL for WriteOnly\n");
754 /* Trying to set invalid handle */
756 ok(!SetConsoleActiveScreenBuffer(INVALID_HANDLE_VALUE
),
757 "Shouldn't succeed\n");
758 ok(GetLastError() == ERROR_INVALID_HANDLE
,
759 "GetLastError: expecting %u got %u\n",
760 ERROR_INVALID_HANDLE
, GetLastError());
762 /* Trying to set non-console handles */
764 ok(!SetConsoleActiveScreenBuffer(hFileOutRW
), "Shouldn't succeed\n");
765 ok(GetLastError() == ERROR_INVALID_HANDLE
,
766 "GetLastError: expecting %u got %u\n",
767 ERROR_INVALID_HANDLE
, GetLastError());
770 ok(!SetConsoleActiveScreenBuffer(hFileOutRO
), "Shouldn't succeed\n");
771 ok(GetLastError() == ERROR_INVALID_HANDLE
,
772 "GetLastError: expecting %u got %u\n",
773 ERROR_INVALID_HANDLE
, GetLastError());
776 ok(!SetConsoleActiveScreenBuffer(hFileOutWT
), "Shouldn't succeed\n");
777 ok(GetLastError() == ERROR_INVALID_HANDLE
,
778 "GetLastError: expecting %u got %u\n",
779 ERROR_INVALID_HANDLE
, GetLastError());
781 CloseHandle(hFileOutRW
);
782 CloseHandle(hFileOutRO
);
783 CloseHandle(hFileOutWT
);
785 /* Trying to set SB handles with various access modes */
787 ok(!SetConsoleActiveScreenBuffer(hConOutRO
), "Shouldn't succeed\n");
788 ok(GetLastError() == ERROR_INVALID_HANDLE
,
789 "GetLastError: expecting %u got %u\n",
790 ERROR_INVALID_HANDLE
, GetLastError());
792 ok(SetConsoleActiveScreenBuffer(hConOutWT
), "Couldn't set new WriteOnly SB\n");
794 ok(SetConsoleActiveScreenBuffer(hConOutRW
), "Couldn't set new ReadWrite SB\n");
796 CloseHandle(hConOutWT
);
797 CloseHandle(hConOutRO
);
799 /* Now we have two ReadWrite SB, active must be hConOutRW */
800 /* Open current SB via CONOUT$ */
801 hConOutNew
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0,
802 NULL
, OPEN_EXISTING
, 0, 0);
803 ok(hConOutNew
!= INVALID_HANDLE_VALUE
, "CONOUT$ is not opened\n");
808 SetConsoleCursorPosition(hConOut
, c
);
810 SetConsoleCursorPosition(hConOutRW
, c
);
811 okCURSOR(hConOutNew
, c
);
813 okCURSOR(hConOut
, c
);
818 /* Write using hConOutNew... */
819 SetConsoleCursorPosition(hConOutNew
, c
);
820 ret
= WriteConsoleA(hConOutNew
, test_str2
, lstrlenA(test_str2
), &len
, NULL
);
821 ok (ret
&& len
== lstrlenA(test_str2
), "WriteConsoleA failed\n");
822 /* ... and read it back via hConOutRW */
823 ret
= ReadConsoleOutputCharacterA(hConOutRW
, str_buf
, lstrlenA(test_str2
), c
, &len
);
824 ok(ret
&& len
== lstrlenA(test_str2
), "ReadConsoleOutputCharacterA failed\n");
825 str_buf
[lstrlenA(test_str2
)] = 0;
826 ok(!lstrcmpA(str_buf
, test_str2
), "got '%s' expected '%s'\n", str_buf
, test_str2
);
829 /* Now test output codepage handling. Current is 866 as we set earlier. */
830 SetConsoleCursorPosition(hConOutRW
, c
);
831 ret
= WriteConsoleA(hConOutRW
, test_cp866
, lstrlenA(test_cp866
), &len
, NULL
);
832 ok(ret
&& len
== lstrlenA(test_cp866
), "WriteConsoleA failed\n");
833 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenA(test_cp866
), c
, &len
);
834 ok(ret
&& len
== lstrlenA(test_cp866
), "ReadConsoleOutputCharacterW failed\n");
835 str_wbuf
[lstrlenA(test_cp866
)] = 0;
836 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
839 * cp866 is OK, let's switch to cp1251.
840 * We expect that this codepage will be used in every SB - active and not.
842 ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n");
843 SetConsoleCursorPosition(hConOutRW
, c
);
844 ret
= WriteConsoleA(hConOutRW
, test_cp1251
, lstrlenA(test_cp1251
), &len
, NULL
);
845 ok(ret
&& len
== lstrlenA(test_cp1251
), "WriteConsoleA failed\n");
846 ret
= ReadConsoleOutputCharacterW(hConOutRW
, str_wbuf
, lstrlenA(test_cp1251
), c
, &len
);
847 ok(ret
&& len
== lstrlenA(test_cp1251
), "ReadConsoleOutputCharacterW failed\n");
848 str_wbuf
[lstrlenA(test_cp1251
)] = 0;
849 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
851 /* Check what has happened to hConOut. */
852 SetConsoleCursorPosition(hConOut
, c
);
853 ret
= WriteConsoleA(hConOut
, test_cp1251
, lstrlenA(test_cp1251
), &len
, NULL
);
854 ok(ret
&& len
== lstrlenA(test_cp1251
), "WriteConsoleA failed\n");
855 ret
= ReadConsoleOutputCharacterW(hConOut
, str_wbuf
, lstrlenA(test_cp1251
), c
, &len
);
856 ok(ret
&& len
== lstrlenA(test_cp1251
), "ReadConsoleOutputCharacterW failed\n");
857 str_wbuf
[lstrlenA(test_cp1251
)] = 0;
858 ok(!lstrcmpW(str_wbuf
, test_unicode
), "string does not match the pattern\n");
860 /* Close all handles of current console SB */
861 CloseHandle(hConOutNew
);
862 CloseHandle(hConOutRW
);
864 /* Now active SB should be hConOut */
865 hConOutNew
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0,
866 NULL
, OPEN_EXISTING
, 0, 0);
867 ok(hConOutNew
!= INVALID_HANDLE_VALUE
, "CONOUT$ is not opened\n");
869 /* Write using hConOutNew... */
870 SetConsoleCursorPosition(hConOutNew
, c
);
871 ret
= WriteConsoleA(hConOutNew
, test_str1
, lstrlenA(test_str1
), &len
, NULL
);
872 ok (ret
&& len
== lstrlenA(test_str1
), "WriteConsoleA failed\n");
873 /* ... and read it back via hConOut */
874 ret
= ReadConsoleOutputCharacterA(hConOut
, str_buf
, lstrlenA(test_str1
), c
, &len
);
875 ok(ret
&& len
== lstrlenA(test_str1
), "ReadConsoleOutputCharacterA failed\n");
876 str_buf
[lstrlenA(test_str1
)] = 0;
877 todo_wine
ok(!lstrcmpA(str_buf
, test_str1
), "got '%s' expected '%s'\n", str_buf
, test_str1
);
878 CloseHandle(hConOutNew
);
880 /* This is not really needed under Windows */
881 SetConsoleActiveScreenBuffer(hConOut
);
883 /* restore codepage */
884 SetConsoleOutputCP(oldcp
);
887 static void test_GetSetConsoleInputExeName(void)
891 char buffer
[MAX_PATH
], module
[MAX_PATH
], *p
;
892 static char input_exe
[MAX_PATH
] = "winetest.exe";
894 SetLastError(0xdeadbeef);
895 ret
= pGetConsoleInputExeNameA(0, NULL
);
896 error
= GetLastError();
897 ok(ret
, "GetConsoleInputExeNameA failed\n");
898 ok(error
== ERROR_BUFFER_OVERFLOW
, "got %u expected ERROR_BUFFER_OVERFLOW\n", error
);
900 SetLastError(0xdeadbeef);
901 ret
= pGetConsoleInputExeNameA(0, buffer
);
902 error
= GetLastError();
903 ok(ret
, "GetConsoleInputExeNameA failed\n");
904 ok(error
== ERROR_BUFFER_OVERFLOW
, "got %u expected ERROR_BUFFER_OVERFLOW\n", error
);
906 GetModuleFileNameA(GetModuleHandle(NULL
), module
, sizeof(module
));
907 p
= strrchr(module
, '\\') + 1;
909 ret
= pGetConsoleInputExeNameA(sizeof(buffer
)/sizeof(buffer
[0]), buffer
);
910 ok(ret
, "GetConsoleInputExeNameA failed\n");
911 todo_wine
ok(!lstrcmpA(buffer
, p
), "got %s expected %s\n", buffer
, p
);
913 SetLastError(0xdeadbeef);
914 ret
= pSetConsoleInputExeNameA(NULL
);
915 error
= GetLastError();
916 ok(!ret
, "SetConsoleInputExeNameA failed\n");
917 ok(error
== ERROR_INVALID_PARAMETER
, "got %u expected ERROR_INVALID_PARAMETER\n", error
);
919 SetLastError(0xdeadbeef);
920 ret
= pSetConsoleInputExeNameA("");
921 error
= GetLastError();
922 ok(!ret
, "SetConsoleInputExeNameA failed\n");
923 ok(error
== ERROR_INVALID_PARAMETER
, "got %u expected ERROR_INVALID_PARAMETER\n", error
);
925 ret
= pSetConsoleInputExeNameA(input_exe
);
926 ok(ret
, "SetConsoleInputExeNameA failed\n");
928 ret
= pGetConsoleInputExeNameA(sizeof(buffer
)/sizeof(buffer
[0]), buffer
);
929 ok(ret
, "GetConsoleInputExeNameA failed\n");
930 ok(!lstrcmpA(buffer
, input_exe
), "got %s expected %s\n", buffer
, input_exe
);
933 static void test_GetConsoleProcessList(void)
935 DWORD ret
, *list
= NULL
;
937 if (!pGetConsoleProcessList
)
939 win_skip("GetConsoleProcessList is not available\n");
943 SetLastError(0xdeadbeef);
944 ret
= pGetConsoleProcessList(NULL
, 0);
945 ok(ret
== 0, "Expected failure\n");
946 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
947 "Expected ERROR_INVALID_PARAMETER, got %d\n",
950 SetLastError(0xdeadbeef);
951 ret
= pGetConsoleProcessList(NULL
, 1);
952 ok(ret
== 0, "Expected failure\n");
953 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
954 "Expected ERROR_INVALID_PARAMETER, got %d\n",
957 /* We should only have 1 process but only for these specific unit tests as
958 * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would
959 * give us two processes for example.
961 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD
));
963 SetLastError(0xdeadbeef);
964 ret
= pGetConsoleProcessList(list
, 0);
965 ok(ret
== 0, "Expected failure\n");
966 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
967 "Expected ERROR_INVALID_PARAMETER, got %d\n",
970 SetLastError(0xdeadbeef);
971 ret
= pGetConsoleProcessList(list
, 1);
973 ok(ret
== 1, "Expected 1, got %d\n", ret
);
975 HeapFree(GetProcessHeap(), 0, list
);
977 list
= HeapAlloc(GetProcessHeap(), 0, ret
* sizeof(DWORD
));
979 SetLastError(0xdeadbeef);
980 ret
= pGetConsoleProcessList(list
, ret
);
982 ok(ret
== 1, "Expected 1, got %d\n", ret
);
986 DWORD pid
= GetCurrentProcessId();
987 ok(list
[0] == pid
, "Expected %d, got %d\n", pid
, list
[0]);
990 HeapFree(GetProcessHeap(), 0, list
);
993 static void test_OpenConsoleW(void)
995 static const WCHAR coninW
[] = {'C','O','N','I','N','$',0};
996 static const WCHAR conoutW
[] = {'C','O','N','O','U','T','$',0};
997 static const WCHAR emptyW
[] = {0};
998 static const WCHAR invalidW
[] = {'I','N','V','A','L','I','D',0};
1007 } invalid_table
[] = {
1008 {NULL
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1009 {NULL
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1010 {NULL
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1011 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1012 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1013 {NULL
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
},
1014 {emptyW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1015 {emptyW
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1016 {emptyW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1017 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1018 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1019 {emptyW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
},
1020 {invalidW
, 0, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1021 {invalidW
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1022 {invalidW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1023 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_INVALID_PARAMETER
},
1024 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1025 {invalidW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
, ERROR_INVALID_PARAMETER
},
1026 {coninW
, 0, FALSE
, 0, ERROR_SHARING_VIOLATION
},
1027 {coninW
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1028 {coninW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1029 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_SHARING_VIOLATION
},
1030 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, ERROR_SHARING_VIOLATION
},
1031 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, ERROR_SHARING_VIOLATION
},
1032 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1033 {coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
, ERROR_INVALID_PARAMETER
},
1034 {conoutW
, 0, FALSE
, 0, ERROR_SHARING_VIOLATION
},
1035 {conoutW
, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER
},
1036 {conoutW
, 0, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1037 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, 0, ERROR_SHARING_VIOLATION
},
1038 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_NEW
, ERROR_SHARING_VIOLATION
},
1039 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, CREATE_ALWAYS
, ERROR_SHARING_VIOLATION
},
1040 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_ALWAYS
, ERROR_INVALID_PARAMETER
},
1041 {conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, TRUNCATE_EXISTING
, ERROR_INVALID_PARAMETER
},
1049 win_skip("OpenConsoleW is not available\n");
1053 for (index
= 0; index
< sizeof(invalid_table
)/sizeof(invalid_table
[0]); index
++)
1055 SetLastError(0xdeadbeef);
1056 ret
= pOpenConsoleW(invalid_table
[index
].name
, invalid_table
[index
].access
,
1057 invalid_table
[index
].inherit
, invalid_table
[index
].creation
);
1058 ok(ret
== INVALID_HANDLE_VALUE
,
1059 "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1061 ok(GetLastError() == invalid_table
[index
].gle
,
1062 "Expected GetLastError() to return %u for index %d, got %u\n",
1063 invalid_table
[index
].gle
, index
, GetLastError());
1066 /* OpenConsoleW should not touch the last error on success. */
1067 SetLastError(0xdeadbeef);
1068 ret
= pOpenConsoleW(coninW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
);
1069 ok(ret
!= INVALID_HANDLE_VALUE
,
1070 "Expected OpenConsoleW to return a valid handle\n");
1071 ok(GetLastError() == 0xdeadbeef,
1072 "Expected the last error to be untouched, got %u\n", GetLastError());
1073 if (ret
!= INVALID_HANDLE_VALUE
)
1076 SetLastError(0xdeadbeef);
1077 ret
= pOpenConsoleW(conoutW
, GENERIC_READ
| GENERIC_WRITE
, FALSE
, OPEN_EXISTING
);
1078 ok(ret
!= INVALID_HANDLE_VALUE
,
1079 "Expected OpenConsoleW to return a valid handle\n");
1080 ok(GetLastError() == 0xdeadbeef,
1081 "Expected the last error to be untouched, got %u\n", GetLastError());
1082 if (ret
!= INVALID_HANDLE_VALUE
)
1088 HANDLE hConIn
, hConOut
;
1090 CONSOLE_SCREEN_BUFFER_INFO sbi
;
1092 init_function_pointers();
1094 /* be sure we have a clean console (and that's our own)
1095 * FIXME: this will make the test fail (currently) if we don't run
1097 * Another solution would be to rerun the test under wineconsole with
1098 * the curses backend
1101 /* first, we detach and open a fresh console to play with */
1103 ok(AllocConsole(), "Couldn't alloc console\n");
1104 hConIn
= CreateFileA("CONIN$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1105 hConOut
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
1107 /* now verify everything's ok */
1108 ok(hConIn
!= INVALID_HANDLE_VALUE
, "Opening ConIn\n");
1109 ok(hConOut
!= INVALID_HANDLE_VALUE
, "Opening ConOut\n");
1111 ret
= GetConsoleScreenBufferInfo(hConOut
, &sbi
);
1112 ok(ret
, "Getting sb info\n");
1115 /* Non interactive tests */
1116 testCursor(hConOut
, sbi
.dwSize
);
1117 /* test parameters (FIXME: test functionality) */
1118 testCursorInfo(hConOut
);
1119 /* will test wrapped (on/off) & processed (on/off) strings output */
1120 testWrite(hConOut
, sbi
.dwSize
);
1121 /* will test line scrolling at the bottom of the screen */
1122 /* testBottomScroll(); */
1123 /* will test all the scrolling operations */
1124 testScroll(hConOut
, sbi
.dwSize
);
1125 /* will test sb creation / modification / codepage handling */
1126 testScreenBuffer(hConOut
);
1128 /* still to be done: access rights & access on objects */
1130 if (!pGetConsoleInputExeNameA
|| !pSetConsoleInputExeNameA
)
1131 win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
1133 test_GetSetConsoleInputExeName();
1135 test_GetConsoleProcessList();
1136 test_OpenConsoleW();