2 * Unit tests for console API
4 * Copyright (c) 2003,2004 Eric Pouech
5 * Copyright (c) 2007 Kirill K. Smirnov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
26 static BOOL (WINAPI *pGetConsoleInputExeNameA)(DWORD, LPSTR);
27 static DWORD (WINAPI *pGetConsoleProcessList)(LPDWORD, DWORD);
28 static HANDLE (WINAPI *pOpenConsoleW)(LPCWSTR,DWORD,BOOL,DWORD);
29 static BOOL (WINAPI *pSetConsoleInputExeNameA)(LPCSTR);
30 static BOOL (WINAPI *pVerifyConsoleIoHandle)(HANDLE handle);
32 /* DEFAULT_ATTRIB is used for all initial filling of the console.
33 * all modifications are made with TEST_ATTRIB so that we could check
34 * what has to be modified or not
36 #define TEST_ATTRIB (BACKGROUND_BLUE | FOREGROUND_GREEN)
37 #define DEFAULT_ATTRIB (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED)
38 /* when filling the screen with non-blank chars, this macro defines
39 * what character should be at position 'c'
41 #define CONTENT(c) ('A' + (((c).Y * 17 + (c).X) % 23))
43 #define okCURSOR(hCon, c) do { \
44 CONSOLE_SCREEN_BUFFER_INFO __sbi; \
45 BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
46 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
47 ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
48 (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
51 #define okCHAR(hCon, c, ch, attr) do { \
52 char __ch; WORD __attr; DWORD __len; BOOL expect; \
53 expect = ReadConsoleOutputCharacter((hCon), &__ch, 1, (c), &__len) == 1 && __len == 1 && __ch == (ch); \
54 ok(expect, "At (%d,%d): expecting char '%c'/%02x got '%c'/%02x\n", (c).X, (c).Y, (ch), (ch), __ch, __ch); \
55 expect = ReadConsoleOutputAttribute((hCon), &__attr, 1, (c), &__len) == 1 && __len == 1 && __attr == (attr); \
56 ok(expect, "At (%d,%d): expecting attr %04x got %04x\n", (c).X, (c).Y, (attr), __attr); \
59 static void init_function_pointers(void)
63 #define KERNEL32_GET_PROC(func) \
64 p##func = (void *)GetProcAddress(hKernel32, #func); \
65 if(!p##func) trace("GetProcAddress(hKernel32, '%s') failed\n", #func);
67 hKernel32 = GetModuleHandleA("kernel32.dll");
68 KERNEL32_GET_PROC(GetConsoleInputExeNameA);
69 KERNEL32_GET_PROC(GetConsoleProcessList);
70 KERNEL32_GET_PROC(OpenConsoleW);
71 KERNEL32_GET_PROC(SetConsoleInputExeNameA);
72 KERNEL32_GET_PROC(VerifyConsoleIoHandle);
74 #undef KERNEL32_GET_PROC
77 /* FIXME: this could be optimized on a speed point of view */
78 static void resetContent(HANDLE hCon, COORD sbSize, BOOL content)
81 WORD attr = DEFAULT_ATTRIB;
85 for (c.X = 0; c.X < sbSize.X; c.X++)
87 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
89 ch = (content) ? CONTENT(c) : ' ';
90 WriteConsoleOutputAttribute(hCon, &attr, 1, c, &len);
91 WriteConsoleOutputCharacterA(hCon, &ch, 1, c, &len);
96 static void testCursor(HANDLE hCon, COORD sbSize)
101 ok(SetConsoleCursorPosition(0, c) == 0, "No handle\n");
102 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
103 ERROR_INVALID_HANDLE, GetLastError());
106 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
111 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in lower-right\n");
116 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
117 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n",
118 ERROR_INVALID_PARAMETER, GetLastError());
122 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
123 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n",
124 ERROR_INVALID_PARAMETER, GetLastError());
128 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
129 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n",
130 ERROR_INVALID_PARAMETER, GetLastError());
134 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
135 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n",
136 ERROR_INVALID_PARAMETER, GetLastError());
139 static void testCursorInfo(HANDLE hCon)
142 CONSOLE_CURSOR_INFO info;
144 SetLastError(0xdeadbeef);
145 ret = GetConsoleCursorInfo(NULL, NULL);
146 ok(!ret, "Expected failure\n");
147 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
148 ERROR_INVALID_HANDLE, GetLastError());
150 SetLastError(0xdeadbeef);
152 ret = GetConsoleCursorInfo(NULL, &info);
153 ok(!ret, "Expected failure\n");
154 ok(info.dwSize == -1, "Expected no change for dwSize\n");
155 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
156 ERROR_INVALID_HANDLE, GetLastError());
158 /* Test the correct call first to distinguish between win9x and the rest */
159 SetLastError(0xdeadbeef);
160 ret = GetConsoleCursorInfo(hCon, &info);
161 ok(ret, "Expected success\n");
162 ok(info.dwSize == 25 ||
163 info.dwSize == 12 /* win9x */,
164 "Expected 12 or 25, got %d\n", info.dwSize);
165 ok(info.bVisible, "Expected the cursor to be visible\n");
166 ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %u\n",
167 0xdeadbeef, GetLastError());
169 /* Don't test NULL CONSOLE_CURSOR_INFO, it crashes on win9x and win7 */
172 static void testEmptyWrite(HANDLE hCon)
174 static const char emptybuf[16];
179 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
182 ok(WriteConsole(hCon, NULL, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
185 /* Passing a NULL lpBuffer with sufficiently large non-zero length succeeds
186 * on native Windows and result in memory-like contents being written to
187 * the console. Calling WriteConsoleW like this will crash on Wine. */
191 ok(!WriteConsole(hCon, NULL, 16, &len, NULL) && len == -1, "WriteConsole\n");
194 /* Cursor advances for this call. */
196 ok(WriteConsole(hCon, NULL, 128, &len, NULL) != 0 && len == 128, "WriteConsole\n");
200 ok(WriteConsole(hCon, emptybuf, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
203 /* WriteConsole does not halt on a null terminator and is happy to write
204 * memory contents beyond the actual size of the buffer. */
206 ok(WriteConsole(hCon, emptybuf, 16, &len, NULL) != 0 && len == 16, "WriteConsole\n");
211 static void testWriteSimple(HANDLE hCon)
215 const char* mytest = "abcdefg";
216 const int mylen = strlen(mytest);
218 /* single line write */
220 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
222 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
224 for (c.X = 0; c.X < mylen; c.X++)
226 okCHAR(hCon, c, mytest[c.X], TEST_ATTRIB);
230 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
233 static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize)
237 const char* mytest = "123";
238 const int mylen = strlen(mytest);
242 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode & ~(ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT)),
243 "clearing wrap at EOL & processed output\n");
245 /* write line, wrapping disabled, buffer exceeds sb width */
246 c.X = sbSize.X - 3; c.Y = 0;
247 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
249 ret = WriteConsole(hCon, mytest, mylen, &len, NULL);
250 ok(ret != 0 && len == mylen, "Couldn't write, ret = %d, len = %d\n", ret, len);
252 for (p = mylen - 3; p < mylen; p++)
254 c.X = sbSize.X - 3 + p % 3;
255 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
259 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
261 p = sbSize.X - 3 + mylen % 3;
264 /* write line, wrapping disabled, strings end on end of line */
265 c.X = sbSize.X - mylen; c.Y = 0;
266 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
268 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
271 static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
275 const char* mytest = "abcd\nf\tg";
276 const int mylen = strlen(mytest);
277 const int mylen2 = strchr(mytest, '\n') - mytest;
281 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, (mode | ENABLE_PROCESSED_OUTPUT) & ~ENABLE_WRAP_AT_EOL_OUTPUT),
282 "clearing wrap at EOL & setting processed output\n");
284 /* write line, wrapping disabled, buffer exceeds sb width */
285 c.X = sbSize.X - 5; c.Y = 0;
286 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-5\n");
288 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
290 for (c.X = sbSize.X - 5; c.X < sbSize.X - 1; c.X++)
292 okCHAR(hCon, c, mytest[c.X - sbSize.X + 5], TEST_ATTRIB);
295 ReadConsoleOutputAttribute(hCon, &attr, 1, c, &len);
296 /* Win9x and WinMe change the attribs for '\n' up to 'f' */
297 if (attr == TEST_ATTRIB)
299 win_skip("Win9x/WinMe don't respect ~ENABLE_WRAP_AT_EOL_OUTPUT\n");
303 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
306 okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
307 for (c.X = 1; c.X < 8; c.X++)
308 okCHAR(hCon, c, ' ', TEST_ATTRIB);
309 okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
311 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
315 /* write line, wrapping disabled, strings end on end of line */
316 c.X = sbSize.X - 4; c.Y = 0;
317 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4\n");
319 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
321 for (c.X = sbSize.X - 4; c.X < sbSize.X; c.X++)
323 okCHAR(hCon, c, mytest[c.X - sbSize.X + 4], TEST_ATTRIB);
326 okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
327 for (c.X = 1; c.X < 8; c.X++)
328 okCHAR(hCon, c, ' ', TEST_ATTRIB);
329 okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
331 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
335 /* write line, wrapping disabled, strings end after end of line */
336 c.X = sbSize.X - 3; c.Y = 0;
337 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4\n");
339 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
341 for (p = mylen2 - 3; p < mylen2; p++)
343 c.X = sbSize.X - 3 + p % 3;
344 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
347 okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
348 for (c.X = 1; c.X < 8; c.X++)
349 okCHAR(hCon, c, ' ', TEST_ATTRIB);
350 okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
352 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
357 static void testWriteWrappedNotProcessed(HANDLE hCon, COORD sbSize)
361 const char* mytest = "abcd\nf\tg";
362 const int mylen = strlen(mytest);
365 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon,(mode | ENABLE_WRAP_AT_EOL_OUTPUT) & ~(ENABLE_PROCESSED_OUTPUT)),
366 "setting wrap at EOL & clearing processed output\n");
368 /* write line, wrapping enabled, buffer doesn't exceed sb width */
369 c.X = sbSize.X - 9; c.Y = 0;
370 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n");
372 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
374 for (p = 0; p < mylen; p++)
376 c.X = sbSize.X - 9 + p;
377 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
379 c.X = sbSize.X - 9 + mylen;
380 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
382 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
384 /* write line, wrapping enabled, buffer does exceed sb width */
385 c.X = sbSize.X - 3; c.Y = 0;
386 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
390 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
393 static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize)
397 const char* mytest = "abcd\nf\tg";
398 const int mylen = strlen(mytest);
402 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode | (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)),
403 "setting wrap at EOL & processed output\n");
405 /* write line, wrapping enabled, buffer doesn't exceed sb width */
406 c.X = sbSize.X - 9; c.Y = 0;
407 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n");
409 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
410 for (p = 0; p < 4; p++)
412 c.X = sbSize.X - 9 + p;
413 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
415 c.X = sbSize.X - 9 + p;
416 ReadConsoleOutputAttribute(hCon, &attr, 1, c, &len);
417 if (attr == TEST_ATTRIB)
418 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n");
420 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
422 okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
423 for (c.X = 1; c.X < 8; c.X++)
424 okCHAR(hCon, c, ' ', TEST_ATTRIB);
425 okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
427 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
430 /* write line, wrapping enabled, buffer does exceed sb width */
431 c.X = sbSize.X - 3; c.Y = 2;
432 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
434 ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
435 for (p = 0; p < 3; p++)
437 c.X = sbSize.X - 3 + p;
438 okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
441 okCHAR(hCon, c, mytest[3], TEST_ATTRIB);
443 ReadConsoleOutputAttribute(hCon, &attr, 1, c, &len);
444 if (attr == TEST_ATTRIB)
445 win_skip("Win9x/WinMe changes attribs for '\\n' up to 'f'\n");
447 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
450 okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
451 for (c.X = 1; c.X < 8; c.X++)
452 okCHAR(hCon, c, ' ', TEST_ATTRIB);
453 okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
455 okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
459 static void testWrite(HANDLE hCon, COORD sbSize)
461 /* FIXME: should in fact insure that the sb is at least 10 character wide */
462 ok(SetConsoleTextAttribute(hCon, TEST_ATTRIB), "Setting default text color\n");
463 resetContent(hCon, sbSize, FALSE);
464 testEmptyWrite(hCon);
465 resetContent(hCon, sbSize, FALSE);
466 testWriteSimple(hCon);
467 resetContent(hCon, sbSize, FALSE);
468 testWriteNotWrappedNotProcessed(hCon, sbSize);
469 resetContent(hCon, sbSize, FALSE);
470 testWriteNotWrappedProcessed(hCon, sbSize);
471 resetContent(hCon, sbSize, FALSE);
472 testWriteWrappedNotProcessed(hCon, sbSize);
473 resetContent(hCon, sbSize, FALSE);
474 testWriteWrappedProcessed(hCon, sbSize);
477 static void testScroll(HANDLE hCon, COORD sbSize)
479 SMALL_RECT scroll, clip;
487 #define IN_SRECT(r,c) ((r).Left <= (c).X && (c).X <= (r).Right && (r).Top <= (c).Y && (c).Y <= (r).Bottom)
488 #define IN_SRECT2(r,d,c) ((d).X <= (c).X && (c).X <= (d).X + (r).Right - (r).Left && (d).Y <= (c).Y && (c).Y <= (d).Y + (r).Bottom - (r).Top)
490 /* no clipping, src & dst rect don't overlap */
491 resetContent(hCon, sbSize, TRUE);
494 scroll.Right = W - 1;
496 scroll.Bottom = H - 1;
499 ci.Char.UnicodeChar = '#';
500 ci.Attributes = TEST_ATTRIB;
503 clip.Right = sbSize.X - 1;
505 clip.Bottom = sbSize.Y - 1;
507 ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
509 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
511 for (c.X = 0; c.X < sbSize.X; c.X++)
513 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
517 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
519 else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c))
520 okCHAR(hCon, c, '#', TEST_ATTRIB);
521 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
525 /* no clipping, src & dst rect do overlap */
526 resetContent(hCon, sbSize, TRUE);
529 scroll.Right = W - 1;
531 scroll.Bottom = H - 1;
534 ci.Char.UnicodeChar = '#';
535 ci.Attributes = TEST_ATTRIB;
538 clip.Right = sbSize.X - 1;
540 clip.Bottom = sbSize.Y - 1;
542 ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
544 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
546 for (c.X = 0; c.X < sbSize.X; c.X++)
548 if (dst.X <= c.X && c.X < dst.X + W && dst.Y <= c.Y && c.Y < dst.Y + H)
552 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
554 else if (c.X < W && c.Y < H) okCHAR(hCon, c, '#', TEST_ATTRIB);
555 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
559 /* clipping, src & dst rect don't overlap */
560 resetContent(hCon, sbSize, TRUE);
563 scroll.Right = W - 1;
565 scroll.Bottom = H - 1;
568 ci.Char.UnicodeChar = '#';
569 ci.Attributes = TEST_ATTRIB;
572 clip.Right = min(W + W / 2, sbSize.X - 1);
574 clip.Bottom = min(H + H / 2, sbSize.Y - 1);
576 SetLastError(0xdeadbeef);
577 ret = ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci);
580 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
582 for (c.X = 0; c.X < sbSize.X; c.X++)
584 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
588 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
590 else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c))
591 okCHAR(hCon, c, '#', TEST_ATTRIB);
592 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
598 /* Win9x will fail, Only accept ERROR_NOT_ENOUGH_MEMORY */
599 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY,
600 "Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
603 /* clipping, src & dst rect do overlap */
604 resetContent(hCon, sbSize, TRUE);
607 scroll.Right = W - 1;
609 scroll.Bottom = H - 1;
612 ci.Char.UnicodeChar = '#';
613 ci.Attributes = TEST_ATTRIB;
616 clip.Right = min(W + W / 2, sbSize.X - 1);
618 clip.Bottom = min(H + H / 2, sbSize.Y - 1);
620 ok(ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci), "Scrolling SB\n");
622 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
624 for (c.X = 0; c.X < sbSize.X; c.X++)
626 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
630 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
632 else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c))
633 okCHAR(hCon, c, '#', TEST_ATTRIB);
634 else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
639 static int mch_count;
640 /* we need the event as Wine console event generation isn't synchronous
641 * (ie GenerateConsoleCtrlEvent returns before all ctrl-handlers in all
642 * processes have been called).
644 static HANDLE mch_event;
645 static BOOL WINAPI mch(DWORD event)
652 static void testCtrlHandler(void)
654 ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n");
655 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %u\n", GetLastError());
656 ok(SetConsoleCtrlHandler(mch, TRUE), "Couldn't set handler\n");
657 /* wine requires the event for the test, as we cannot insure, so far, that event
658 * are processed synchronously in GenerateConsoleCtrlEvent()
660 mch_event = CreateEventA(NULL, TRUE, FALSE, NULL);
662 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n");
663 /* FIXME: it isn't synchronous on wine but it can still happen before we test */
664 if (0) ok(mch_count == 1, "Event isn't synchronous\n");
665 ok(WaitForSingleObject(mch_event, 3000) == WAIT_OBJECT_0, "event sending didn't work\n");
666 CloseHandle(mch_event);
668 /* Turning off ctrl-c handling doesn't work on win9x such way ... */
669 ok(SetConsoleCtrlHandler(NULL, TRUE), "Couldn't turn off ctrl-c handling\n");
670 mch_event = CreateEventA(NULL, TRUE, FALSE, NULL);
672 if(!(GetVersion() & 0x80000000))
673 /* ... and next line leads to an unhandled exception on 9x. Avoid it on 9x. */
674 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n");
675 ok(WaitForSingleObject(mch_event, 3000) == WAIT_TIMEOUT && mch_count == 0, "Event shouldn't have been sent\n");
676 CloseHandle(mch_event);
677 ok(SetConsoleCtrlHandler(mch, FALSE), "Couldn't remove handler\n");
678 ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n");
679 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %u\n", GetLastError());
683 * Test console screen buffer:
684 * 1) Try to set invalid handle.
685 * 2) Try to set non-console handles.
686 * 3) Use CONOUT$ file as active SB.
688 * 5) Test output codepage to show it is not a property of SB.
689 * 6) Test switching to old SB if we close all handles to current SB - works
690 * in Windows, TODO in wine.
692 * What is not tested but should be:
693 * 1) ScreenBufferInfo
695 static void testScreenBuffer(HANDLE hConOut)
697 HANDLE hConOutRW, hConOutRO, hConOutWT;
698 HANDLE hFileOutRW, hFileOutRO, hFileOutWT;
700 char test_str1[] = "Test for SB1";
701 char test_str2[] = "Test for SB2";
702 char test_cp866[] = {0xe2, 0xa5, 0xe1, 0xe2, 0};
703 char test_cp1251[] = {0xf2, 0xe5, 0xf1, 0xf2, 0};
704 WCHAR test_unicode[] = {0x0442, 0x0435, 0x0441, 0x0442, 0};
712 if (!IsValidCodePage(866))
714 skip("Codepage 866 not available\n");
718 /* In the beginning set output codepage to 866 */
719 oldcp = GetConsoleOutputCP();
720 SetLastError(0xdeadbeef);
721 ret = SetConsoleOutputCP(866);
722 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
724 win_skip("SetConsoleOutputCP is not implemented\n");
727 ok(ret, "Cannot set output codepage to 866\n");
729 hConOutRW = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
730 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
731 CONSOLE_TEXTMODE_BUFFER, NULL);
732 ok(hConOutRW != INVALID_HANDLE_VALUE,
733 "Cannot create a new screen buffer for ReadWrite\n");
734 hConOutRO = CreateConsoleScreenBuffer(GENERIC_READ,
735 FILE_SHARE_READ, NULL,
736 CONSOLE_TEXTMODE_BUFFER, NULL);
737 ok(hConOutRO != INVALID_HANDLE_VALUE,
738 "Cannot create a new screen buffer for ReadOnly\n");
739 hConOutWT = CreateConsoleScreenBuffer(GENERIC_WRITE,
740 FILE_SHARE_WRITE, NULL,
741 CONSOLE_TEXTMODE_BUFFER, NULL);
742 ok(hConOutWT != INVALID_HANDLE_VALUE,
743 "Cannot create a new screen buffer for WriteOnly\n");
745 hFileOutRW = CreateFileA("NUL", GENERIC_READ | GENERIC_WRITE,
746 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
747 OPEN_EXISTING, 0, NULL);
748 ok(hFileOutRW != INVALID_HANDLE_VALUE, "Cannot open NUL for ReadWrite\n");
749 hFileOutRO = CreateFileA("NUL", GENERIC_READ, FILE_SHARE_READ,
750 NULL, OPEN_EXISTING, 0, NULL);
751 ok(hFileOutRO != INVALID_HANDLE_VALUE, "Cannot open NUL for ReadOnly\n");
752 hFileOutWT = CreateFileA("NUL", GENERIC_WRITE, FILE_SHARE_WRITE,
753 NULL, OPEN_EXISTING, 0, NULL);
754 ok(hFileOutWT != INVALID_HANDLE_VALUE, "Cannot open NUL for WriteOnly\n");
756 /* Trying to set invalid handle */
758 ok(!SetConsoleActiveScreenBuffer(INVALID_HANDLE_VALUE),
759 "Shouldn't succeed\n");
760 ok(GetLastError() == ERROR_INVALID_HANDLE,
761 "GetLastError: expecting %u got %u\n",
762 ERROR_INVALID_HANDLE, GetLastError());
764 /* Trying to set non-console handles */
766 ok(!SetConsoleActiveScreenBuffer(hFileOutRW), "Shouldn't succeed\n");
767 ok(GetLastError() == ERROR_INVALID_HANDLE,
768 "GetLastError: expecting %u got %u\n",
769 ERROR_INVALID_HANDLE, GetLastError());
772 ok(!SetConsoleActiveScreenBuffer(hFileOutRO), "Shouldn't succeed\n");
773 ok(GetLastError() == ERROR_INVALID_HANDLE,
774 "GetLastError: expecting %u got %u\n",
775 ERROR_INVALID_HANDLE, GetLastError());
778 ok(!SetConsoleActiveScreenBuffer(hFileOutWT), "Shouldn't succeed\n");
779 ok(GetLastError() == ERROR_INVALID_HANDLE,
780 "GetLastError: expecting %u got %u\n",
781 ERROR_INVALID_HANDLE, GetLastError());
783 CloseHandle(hFileOutRW);
784 CloseHandle(hFileOutRO);
785 CloseHandle(hFileOutWT);
787 /* Trying to set SB handles with various access modes */
789 ok(!SetConsoleActiveScreenBuffer(hConOutRO), "Shouldn't succeed\n");
790 ok(GetLastError() == ERROR_INVALID_HANDLE,
791 "GetLastError: expecting %u got %u\n",
792 ERROR_INVALID_HANDLE, GetLastError());
794 ok(SetConsoleActiveScreenBuffer(hConOutWT), "Couldn't set new WriteOnly SB\n");
796 ok(SetConsoleActiveScreenBuffer(hConOutRW), "Couldn't set new ReadWrite SB\n");
798 CloseHandle(hConOutWT);
799 CloseHandle(hConOutRO);
801 /* Now we have two ReadWrite SB, active must be hConOutRW */
802 /* Open current SB via CONOUT$ */
803 hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0,
804 NULL, OPEN_EXISTING, 0, 0);
805 ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n");
810 SetConsoleCursorPosition(hConOut, c);
812 SetConsoleCursorPosition(hConOutRW, c);
813 okCURSOR(hConOutNew, c);
815 okCURSOR(hConOut, c);
820 /* Write using hConOutNew... */
821 SetConsoleCursorPosition(hConOutNew, c);
822 ret = WriteConsoleA(hConOutNew, test_str2, lstrlenA(test_str2), &len, NULL);
823 ok (ret && len == lstrlenA(test_str2), "WriteConsoleA failed\n");
824 /* ... and read it back via hConOutRW */
825 ret = ReadConsoleOutputCharacterA(hConOutRW, str_buf, lstrlenA(test_str2), c, &len);
826 ok(ret && len == lstrlenA(test_str2), "ReadConsoleOutputCharacterA failed\n");
827 str_buf[lstrlenA(test_str2)] = 0;
828 ok(!lstrcmpA(str_buf, test_str2), "got '%s' expected '%s'\n", str_buf, test_str2);
831 /* Now test output codepage handling. Current is 866 as we set earlier. */
832 SetConsoleCursorPosition(hConOutRW, c);
833 ret = WriteConsoleA(hConOutRW, test_cp866, lstrlenA(test_cp866), &len, NULL);
834 ok(ret && len == lstrlenA(test_cp866), "WriteConsoleA failed\n");
835 ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp866), c, &len);
836 ok(ret && len == lstrlenA(test_cp866), "ReadConsoleOutputCharacterW failed\n");
837 str_wbuf[lstrlenA(test_cp866)] = 0;
838 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
841 * cp866 is OK, let's switch to cp1251.
842 * We expect that this codepage will be used in every SB - active and not.
844 ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n");
845 SetConsoleCursorPosition(hConOutRW, c);
846 ret = WriteConsoleA(hConOutRW, test_cp1251, lstrlenA(test_cp1251), &len, NULL);
847 ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n");
848 ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp1251), c, &len);
849 ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n");
850 str_wbuf[lstrlenA(test_cp1251)] = 0;
851 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
853 /* Check what has happened to hConOut. */
854 SetConsoleCursorPosition(hConOut, c);
855 ret = WriteConsoleA(hConOut, test_cp1251, lstrlenA(test_cp1251), &len, NULL);
856 ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n");
857 ret = ReadConsoleOutputCharacterW(hConOut, str_wbuf, lstrlenA(test_cp1251), c, &len);
858 ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n");
859 str_wbuf[lstrlenA(test_cp1251)] = 0;
860 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
862 /* Close all handles of current console SB */
863 CloseHandle(hConOutNew);
864 CloseHandle(hConOutRW);
866 /* Now active SB should be hConOut */
867 hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0,
868 NULL, OPEN_EXISTING, 0, 0);
869 ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n");
871 /* Write using hConOutNew... */
872 SetConsoleCursorPosition(hConOutNew, c);
873 ret = WriteConsoleA(hConOutNew, test_str1, lstrlenA(test_str1), &len, NULL);
874 ok (ret && len == lstrlenA(test_str1), "WriteConsoleA failed\n");
875 /* ... and read it back via hConOut */
876 ret = ReadConsoleOutputCharacterA(hConOut, str_buf, lstrlenA(test_str1), c, &len);
877 ok(ret && len == lstrlenA(test_str1), "ReadConsoleOutputCharacterA failed\n");
878 str_buf[lstrlenA(test_str1)] = 0;
879 todo_wine ok(!lstrcmpA(str_buf, test_str1), "got '%s' expected '%s'\n", str_buf, test_str1);
880 CloseHandle(hConOutNew);
882 /* This is not really needed under Windows */
883 SetConsoleActiveScreenBuffer(hConOut);
885 /* restore codepage */
886 SetConsoleOutputCP(oldcp);
889 static void test_GetSetConsoleInputExeName(void)
893 char buffer[MAX_PATH], module[MAX_PATH], *p;
894 static char input_exe[MAX_PATH] = "winetest.exe";
896 SetLastError(0xdeadbeef);
897 ret = pGetConsoleInputExeNameA(0, NULL);
898 error = GetLastError();
899 ok(ret, "GetConsoleInputExeNameA failed\n");
900 ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
902 SetLastError(0xdeadbeef);
903 ret = pGetConsoleInputExeNameA(0, buffer);
904 error = GetLastError();
905 ok(ret, "GetConsoleInputExeNameA failed\n");
906 ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
908 GetModuleFileNameA(GetModuleHandle(NULL), module, sizeof(module));
909 p = strrchr(module, '\\') + 1;
911 ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
912 ok(ret, "GetConsoleInputExeNameA failed\n");
913 todo_wine ok(!lstrcmpA(buffer, p), "got %s expected %s\n", buffer, p);
915 SetLastError(0xdeadbeef);
916 ret = pSetConsoleInputExeNameA(NULL);
917 error = GetLastError();
918 ok(!ret, "SetConsoleInputExeNameA failed\n");
919 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
921 SetLastError(0xdeadbeef);
922 ret = pSetConsoleInputExeNameA("");
923 error = GetLastError();
924 ok(!ret, "SetConsoleInputExeNameA failed\n");
925 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
927 ret = pSetConsoleInputExeNameA(input_exe);
928 ok(ret, "SetConsoleInputExeNameA failed\n");
930 ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
931 ok(ret, "GetConsoleInputExeNameA failed\n");
932 ok(!lstrcmpA(buffer, input_exe), "got %s expected %s\n", buffer, input_exe);
935 static void test_GetConsoleProcessList(void)
937 DWORD ret, *list = NULL;
939 if (!pGetConsoleProcessList)
941 win_skip("GetConsoleProcessList is not available\n");
945 SetLastError(0xdeadbeef);
946 ret = pGetConsoleProcessList(NULL, 0);
947 ok(ret == 0, "Expected failure\n");
948 ok(GetLastError() == ERROR_INVALID_PARAMETER,
949 "Expected ERROR_INVALID_PARAMETER, got %d\n",
952 SetLastError(0xdeadbeef);
953 ret = pGetConsoleProcessList(NULL, 1);
954 ok(ret == 0, "Expected failure\n");
955 ok(GetLastError() == ERROR_INVALID_PARAMETER,
956 "Expected ERROR_INVALID_PARAMETER, got %d\n",
959 /* We should only have 1 process but only for these specific unit tests as
960 * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would
961 * give us two processes for example.
963 list = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));
965 SetLastError(0xdeadbeef);
966 ret = pGetConsoleProcessList(list, 0);
967 ok(ret == 0, "Expected failure\n");
968 ok(GetLastError() == ERROR_INVALID_PARAMETER,
969 "Expected ERROR_INVALID_PARAMETER, got %d\n",
972 SetLastError(0xdeadbeef);
973 ret = pGetConsoleProcessList(list, 1);
975 ok(ret == 1, "Expected 1, got %d\n", ret);
977 HeapFree(GetProcessHeap(), 0, list);
979 list = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(DWORD));
981 SetLastError(0xdeadbeef);
982 ret = pGetConsoleProcessList(list, ret);
984 ok(ret == 1, "Expected 1, got %d\n", ret);
988 DWORD pid = GetCurrentProcessId();
989 ok(list[0] == pid, "Expected %d, got %d\n", pid, list[0]);
992 HeapFree(GetProcessHeap(), 0, list);
995 static void test_OpenConsoleW(void)
997 static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
998 static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
999 static const WCHAR emptyW[] = {0};
1000 static const WCHAR invalidW[] = {'I','N','V','A','L','I','D',0};
1009 } invalid_table[] = {
1010 {NULL, 0, FALSE, 0, ERROR_INVALID_PARAMETER},
1011 {NULL, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1012 {NULL, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1013 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER},
1014 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1015 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER},
1016 {emptyW, 0, FALSE, 0, ERROR_INVALID_PARAMETER},
1017 {emptyW, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1018 {emptyW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1019 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER},
1020 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1021 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER},
1022 {invalidW, 0, FALSE, 0, ERROR_INVALID_PARAMETER},
1023 {invalidW, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1024 {invalidW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1025 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER},
1026 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1027 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER},
1028 {coninW, 0, FALSE, 0, ERROR_SHARING_VIOLATION},
1029 {coninW, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1030 {coninW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1031 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_SHARING_VIOLATION},
1032 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, ERROR_SHARING_VIOLATION},
1033 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, ERROR_SHARING_VIOLATION},
1034 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1035 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
1036 {conoutW, 0, FALSE, 0, ERROR_SHARING_VIOLATION},
1037 {conoutW, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, ERROR_INVALID_PARAMETER},
1038 {conoutW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1039 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_SHARING_VIOLATION},
1040 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, ERROR_SHARING_VIOLATION},
1041 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, ERROR_SHARING_VIOLATION},
1042 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER},
1043 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
1051 win_skip("OpenConsoleW is not available\n");
1055 for (index = 0; index < sizeof(invalid_table)/sizeof(invalid_table[0]); index++)
1057 SetLastError(0xdeadbeef);
1058 ret = pOpenConsoleW(invalid_table[index].name, invalid_table[index].access,
1059 invalid_table[index].inherit, invalid_table[index].creation);
1060 ok(ret == INVALID_HANDLE_VALUE,
1061 "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1063 ok(GetLastError() == invalid_table[index].gle,
1064 "Expected GetLastError() to return %u for index %d, got %u\n",
1065 invalid_table[index].gle, index, GetLastError());
1068 /* OpenConsoleW should not touch the last error on success. */
1069 SetLastError(0xdeadbeef);
1070 ret = pOpenConsoleW(coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1071 ok(ret != INVALID_HANDLE_VALUE,
1072 "Expected OpenConsoleW to return a valid handle\n");
1073 ok(GetLastError() == 0xdeadbeef,
1074 "Expected the last error to be untouched, got %u\n", GetLastError());
1075 if (ret != INVALID_HANDLE_VALUE)
1078 SetLastError(0xdeadbeef);
1079 ret = pOpenConsoleW(conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1080 ok(ret != INVALID_HANDLE_VALUE,
1081 "Expected OpenConsoleW to return a valid handle\n");
1082 ok(GetLastError() == 0xdeadbeef,
1083 "Expected the last error to be untouched, got %u\n", GetLastError());
1084 if (ret != INVALID_HANDLE_VALUE)
1088 static void test_VerifyConsoleIoHandle( HANDLE handle )
1093 if (!pVerifyConsoleIoHandle)
1095 win_skip("VerifyConsoleIoHandle is not available\n");
1099 /* invalid handle */
1100 SetLastError(0xdeadbeef);
1101 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee0);
1102 error = GetLastError();
1103 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1104 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1106 /* invalid handle + 1 */
1107 SetLastError(0xdeadbeef);
1108 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee1);
1109 error = GetLastError();
1110 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1111 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1113 /* invalid handle + 2 */
1114 SetLastError(0xdeadbeef);
1115 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee2);
1116 error = GetLastError();
1117 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1118 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1120 /* invalid handle + 3 */
1121 SetLastError(0xdeadbeef);
1122 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee3);
1123 error = GetLastError();
1124 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1125 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1128 SetLastError(0xdeadbeef);
1129 ret = pVerifyConsoleIoHandle(handle);
1130 error = GetLastError();
1131 ok(ret, "expected VerifyConsoleIoHandle to succeed\n");
1132 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1135 static void test_GetSetStdHandle(void)
1141 /* get invalid std handle */
1142 SetLastError(0xdeadbeef);
1143 handle = GetStdHandle(42);
1144 error = GetLastError();
1145 ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1146 "wrong GetLastError() %d\n", error);
1147 ok(handle == INVALID_HANDLE_VALUE, "expected INVALID_HANDLE_VALUE\n");
1150 SetLastError(0xdeadbeef);
1151 handle = GetStdHandle(STD_INPUT_HANDLE);
1152 error = GetLastError();
1153 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1155 /* set invalid std handle */
1156 SetLastError(0xdeadbeef);
1157 ret = SetStdHandle(42, handle);
1158 error = GetLastError();
1159 ok(!ret, "expected SetStdHandle to fail\n");
1160 ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1161 "wrong GetLastError() %d\n", error);
1163 /* set valid (restore old value) */
1164 SetLastError(0xdeadbeef);
1165 ret = SetStdHandle(STD_INPUT_HANDLE, handle);
1166 error = GetLastError();
1167 ok(ret, "expected SetStdHandle to succeed\n");
1168 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1173 HANDLE hConIn, hConOut;
1175 CONSOLE_SCREEN_BUFFER_INFO sbi;
1177 init_function_pointers();
1179 /* be sure we have a clean console (and that's our own)
1180 * FIXME: this will make the test fail (currently) if we don't run
1182 * Another solution would be to rerun the test under wineconsole with
1183 * the curses backend
1186 /* first, we detach and open a fresh console to play with */
1188 ok(AllocConsole(), "Couldn't alloc console\n");
1189 hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1190 hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1192 /* now verify everything's ok */
1193 ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
1194 ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
1196 ret = GetConsoleScreenBufferInfo(hConOut, &sbi);
1197 ok(ret, "Getting sb info\n");
1200 /* Non interactive tests */
1201 testCursor(hConOut, sbi.dwSize);
1202 /* test parameters (FIXME: test functionality) */
1203 testCursorInfo(hConOut);
1204 /* will test wrapped (on/off) & processed (on/off) strings output */
1205 testWrite(hConOut, sbi.dwSize);
1206 /* will test line scrolling at the bottom of the screen */
1207 /* testBottomScroll(); */
1208 /* will test all the scrolling operations */
1209 testScroll(hConOut, sbi.dwSize);
1210 /* will test sb creation / modification / codepage handling */
1211 testScreenBuffer(hConOut);
1213 /* still to be done: access rights & access on objects */
1215 if (!pGetConsoleInputExeNameA || !pSetConsoleInputExeNameA)
1216 win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
1218 test_GetSetConsoleInputExeName();
1220 test_GetConsoleProcessList();
1221 test_OpenConsoleW();
1222 test_VerifyConsoleIoHandle(hConOut);
1223 test_GetSetStdHandle();