Release 1.4-rc5.
[wine] / dlls / kernel32 / tests / console.c
1 /*
2  * Unit tests for console API
3  *
4  * Copyright (c) 2003,2004 Eric Pouech
5  * Copyright (c) 2007 Kirill K. Smirnov
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "wine/test.h"
23 #include <windows.h>
24 #include <stdio.h>
25
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);
31
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
35  */
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'
40  */
41 #define CONTENT(c)    ('A' + (((c).Y * 17 + (c).X) % 23))
42
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); \
49 } while (0)
50
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); \
57 } while (0)
58
59 static void init_function_pointers(void)
60 {
61     HMODULE hKernel32;
62
63 #define KERNEL32_GET_PROC(func)                                     \
64     p##func = (void *)GetProcAddress(hKernel32, #func);             \
65     if(!p##func) trace("GetProcAddress(hKernel32, '%s') failed\n", #func);
66
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);
73
74 #undef KERNEL32_GET_PROC
75 }
76
77 /* FIXME: this could be optimized on a speed point of view */
78 static void resetContent(HANDLE hCon, COORD sbSize, BOOL content)
79 {
80     COORD       c;
81     WORD        attr = DEFAULT_ATTRIB;
82     char        ch;
83     DWORD       len;
84
85     for (c.X = 0; c.X < sbSize.X; c.X++)
86     {
87         for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
88         {
89             ch = (content) ? CONTENT(c) : ' ';
90             WriteConsoleOutputAttribute(hCon, &attr, 1, c, &len);
91             WriteConsoleOutputCharacterA(hCon, &ch, 1, c, &len);
92         }
93     }
94 }
95
96 static void testCursor(HANDLE hCon, COORD sbSize)
97 {
98     COORD               c;
99
100     c.X = c.Y = 0;
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());
104
105     c.X = c.Y = 0;
106     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
107     okCURSOR(hCon, c);
108
109     c.X = sbSize.X - 1;
110     c.Y = sbSize.Y - 1;
111     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in lower-right\n");
112     okCURSOR(hCon, c);
113
114     c.X = sbSize.X;
115     c.Y = sbSize.Y - 1;
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());
119
120     c.X = sbSize.X - 1;
121     c.Y = sbSize.Y;
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());
125
126     c.X = -1;
127     c.Y = 0;
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());
131
132     c.X = 0;
133     c.Y = -1;
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());
137 }
138
139 static void testCursorInfo(HANDLE hCon)
140 {
141     BOOL ret;
142     CONSOLE_CURSOR_INFO info;
143
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());
149
150     SetLastError(0xdeadbeef);
151     info.dwSize = -1;
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());
157
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());
168
169     /* Don't test NULL CONSOLE_CURSOR_INFO, it crashes on win9x and win7 */
170 }
171
172 static void testEmptyWrite(HANDLE hCon)
173 {
174     static const char   emptybuf[16];
175     COORD               c;
176     DWORD               len;
177
178     c.X = c.Y = 0;
179     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
180
181     len = -1;
182     ok(WriteConsole(hCon, NULL, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
183     okCURSOR(hCon, c);
184
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. */
188     if (0)
189     {
190         len = -1;
191         ok(!WriteConsole(hCon, NULL, 16, &len, NULL) && len == -1, "WriteConsole\n");
192         okCURSOR(hCon, c);
193
194         /* Cursor advances for this call. */
195         len = -1;
196         ok(WriteConsole(hCon, NULL, 128, &len, NULL) != 0 && len == 128, "WriteConsole\n");
197     }
198
199     len = -1;
200     ok(WriteConsole(hCon, emptybuf, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
201     okCURSOR(hCon, c);
202
203     /* WriteConsole does not halt on a null terminator and is happy to write
204      * memory contents beyond the actual size of the buffer. */
205     len = -1;
206     ok(WriteConsole(hCon, emptybuf, 16, &len, NULL) != 0 && len == 16, "WriteConsole\n");
207     c.X += 16;
208     okCURSOR(hCon, c);
209 }
210
211 static void testWriteSimple(HANDLE hCon)
212 {
213     COORD               c;
214     DWORD               len;
215     const char*         mytest = "abcdefg";
216     const int   mylen = strlen(mytest);
217
218     /* single line write */
219     c.X = c.Y = 0;
220     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
221
222     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
223     c.Y = 0;
224     for (c.X = 0; c.X < mylen; c.X++)
225     {
226         okCHAR(hCon, c, mytest[c.X], TEST_ATTRIB);
227     }
228
229     okCURSOR(hCon, c);
230     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
231 }
232
233 static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize)
234 {
235     COORD               c;
236     DWORD               len, mode;
237     const char*         mytest = "123";
238     const int           mylen = strlen(mytest);
239     int                 ret;
240     int                 p;
241
242     ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode & ~(ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT)),
243        "clearing wrap at EOL & processed output\n");
244
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");
248
249     ret = WriteConsole(hCon, mytest, mylen, &len, NULL);
250     ok(ret != 0 && len == mylen, "Couldn't write, ret = %d, len = %d\n", ret, len);
251     c.Y = 0;
252     for (p = mylen - 3; p < mylen; p++)
253     {
254         c.X = sbSize.X - 3 + p % 3;
255         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
256     }
257
258     c.X = 0; c.Y = 1;
259     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
260
261     p = sbSize.X - 3 + mylen % 3;
262     c.X = p; c.Y = 0;
263
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");
267
268     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
269 }
270
271 static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
272 {
273     COORD               c;
274     DWORD               len, mode;
275     const char*         mytest = "abcd\nf\tg";
276     const int   mylen = strlen(mytest);
277     const int   mylen2 = strchr(mytest, '\n') - mytest;
278     int                 p;
279     WORD                attr;
280
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");
283
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");
287
288     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
289     c.Y = 0;
290     for (c.X = sbSize.X - 5; c.X < sbSize.X - 1; c.X++)
291     {
292         okCHAR(hCon, c, mytest[c.X - sbSize.X + 5], TEST_ATTRIB);
293     }
294
295     ReadConsoleOutputAttribute(hCon, &attr, 1, c, &len);
296     /* Win9x and WinMe change the attribs for '\n' up to 'f' */
297     if (attr == TEST_ATTRIB)
298     {
299         win_skip("Win9x/WinMe don't respect ~ENABLE_WRAP_AT_EOL_OUTPUT\n");
300         return;
301     }
302
303     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
304
305     c.X = 0; c.Y++;
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);
310     c.X++;
311     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
312
313     okCURSOR(hCon, c);
314
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");
318
319     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
320     c.Y = 0;
321     for (c.X = sbSize.X - 4; c.X < sbSize.X; c.X++)
322     {
323         okCHAR(hCon, c, mytest[c.X - sbSize.X + 4], TEST_ATTRIB);
324     }
325     c.X = 0; c.Y++;
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);
330     c.X++;
331     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
332
333     okCURSOR(hCon, c);
334
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");
338
339     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
340     c.Y = 0;
341     for (p = mylen2 - 3; p < mylen2; p++)
342     {
343         c.X = sbSize.X - 3 + p % 3;
344         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
345     }
346     c.X = 0; c.Y = 1;
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);
351     c.X++;
352     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
353
354     okCURSOR(hCon, c);
355 }
356
357 static void testWriteWrappedNotProcessed(HANDLE hCon, COORD sbSize)
358 {
359     COORD               c;
360     DWORD               len, mode;
361     const char*         mytest = "abcd\nf\tg";
362     const int   mylen = strlen(mytest);
363     int                 p;
364
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");
367
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");
371
372     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
373     c.Y = 0;
374     for (p = 0; p < mylen; p++)
375     {
376         c.X = sbSize.X - 9 + p;
377         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
378     }
379     c.X = sbSize.X - 9 + mylen;
380     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
381     c.X = 0; c.Y = 1;
382     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
383
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");
387
388     c.Y = 1;
389     c.X = mylen - 3;
390     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
391 }
392
393 static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize)
394 {
395     COORD               c;
396     DWORD               len, mode;
397     const char*         mytest = "abcd\nf\tg";
398     const int   mylen = strlen(mytest);
399     int                 p;
400     WORD                attr;
401
402     ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode | (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)),
403        "setting wrap at EOL & processed output\n");
404
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");
408
409     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
410     for (p = 0; p < 4; p++)
411     {
412         c.X = sbSize.X - 9 + p;
413         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
414     }
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");
419     else
420         okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
421     c.X = 0; c.Y++;
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);
426     c.X++;
427     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
428     okCURSOR(hCon, c);
429
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");
433
434     ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
435     for (p = 0; p < 3; p++)
436     {
437         c.X = sbSize.X - 3 + p;
438         okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
439     }
440     c.X = 0; c.Y++;
441     okCHAR(hCon, c, mytest[3], TEST_ATTRIB);
442     c.X++;
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");
446     else
447         okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
448
449     c.X = 0; c.Y++;
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);
454     c.X++;
455     okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
456     okCURSOR(hCon, c);
457 }
458
459 static void testWrite(HANDLE hCon, COORD sbSize)
460 {
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);
475 }
476
477 static void testScroll(HANDLE hCon, COORD sbSize)
478 {
479     SMALL_RECT  scroll, clip;
480     COORD       dst, c, tc;
481     CHAR_INFO   ci;
482     BOOL ret;
483
484 #define W 11
485 #define H 7
486
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)
489
490     /* no clipping, src & dst rect don't overlap */
491     resetContent(hCon, sbSize, TRUE);
492
493     scroll.Left = 0;
494     scroll.Right = W - 1;
495     scroll.Top = 0;
496     scroll.Bottom = H - 1;
497     dst.X = W + 3;
498     dst.Y = H + 3;
499     ci.Char.UnicodeChar = '#';
500     ci.Attributes = TEST_ATTRIB;
501
502     clip.Left = 0;
503     clip.Right = sbSize.X - 1;
504     clip.Top = 0;
505     clip.Bottom = sbSize.Y - 1;
506
507     ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
508
509     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
510     {
511         for (c.X = 0; c.X < sbSize.X; c.X++)
512         {
513             if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
514             {
515                 tc.X = c.X - dst.X;
516                 tc.Y = c.Y - dst.Y;
517                 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
518             }
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);
522         }
523     }
524
525     /* no clipping, src & dst rect do overlap */
526     resetContent(hCon, sbSize, TRUE);
527
528     scroll.Left = 0;
529     scroll.Right = W - 1;
530     scroll.Top = 0;
531     scroll.Bottom = H - 1;
532     dst.X = W /2;
533     dst.Y = H / 2;
534     ci.Char.UnicodeChar = '#';
535     ci.Attributes = TEST_ATTRIB;
536
537     clip.Left = 0;
538     clip.Right = sbSize.X - 1;
539     clip.Top = 0;
540     clip.Bottom = sbSize.Y - 1;
541
542     ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
543
544     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
545     {
546         for (c.X = 0; c.X < sbSize.X; c.X++)
547         {
548             if (dst.X <= c.X && c.X < dst.X + W && dst.Y <= c.Y && c.Y < dst.Y + H)
549             {
550                 tc.X = c.X - dst.X;
551                 tc.Y = c.Y - dst.Y;
552                 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
553             }
554             else if (c.X < W && c.Y < H) okCHAR(hCon, c, '#', TEST_ATTRIB);
555             else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
556         }
557     }
558
559     /* clipping, src & dst rect don't overlap */
560     resetContent(hCon, sbSize, TRUE);
561
562     scroll.Left = 0;
563     scroll.Right = W - 1;
564     scroll.Top = 0;
565     scroll.Bottom = H - 1;
566     dst.X = W + 3;
567     dst.Y = H + 3;
568     ci.Char.UnicodeChar = '#';
569     ci.Attributes = TEST_ATTRIB;
570
571     clip.Left = W / 2;
572     clip.Right = min(W + W / 2, sbSize.X - 1);
573     clip.Top = H / 2;
574     clip.Bottom = min(H + H / 2, sbSize.Y - 1);
575
576     SetLastError(0xdeadbeef);
577     ret = ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci);
578     if (ret)
579     {
580         for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
581         {
582             for (c.X = 0; c.X < sbSize.X; c.X++)
583             {
584                 if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
585                 {
586                     tc.X = c.X - dst.X;
587                     tc.Y = c.Y - dst.Y;
588                     okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
589                 }
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);
593             }
594         }
595     }
596     else
597     {
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());
601     }
602
603     /* clipping, src & dst rect do overlap */
604     resetContent(hCon, sbSize, TRUE);
605
606     scroll.Left = 0;
607     scroll.Right = W - 1;
608     scroll.Top = 0;
609     scroll.Bottom = H - 1;
610     dst.X = W / 2 - 3;
611     dst.Y = H / 2 - 3;
612     ci.Char.UnicodeChar = '#';
613     ci.Attributes = TEST_ATTRIB;
614
615     clip.Left = W / 2;
616     clip.Right = min(W + W / 2, sbSize.X - 1);
617     clip.Top = H / 2;
618     clip.Bottom = min(H + H / 2, sbSize.Y - 1);
619
620     ok(ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci), "Scrolling SB\n");
621
622     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
623     {
624         for (c.X = 0; c.X < sbSize.X; c.X++)
625         {
626             if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
627             {
628                 tc.X = c.X - dst.X;
629                 tc.Y = c.Y - dst.Y;
630                 okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
631             }
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);
635         }
636     }
637 }
638
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).
643  */
644 static HANDLE mch_event;
645 static BOOL WINAPI mch(DWORD event)
646 {
647     mch_count++;
648     SetEvent(mch_event);
649     return TRUE;
650 }
651
652 static void testCtrlHandler(void)
653 {
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()
659      */
660     mch_event = CreateEventA(NULL, TRUE, FALSE, NULL);
661     mch_count = 0;
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);
667
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);
671     mch_count = 0;
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());
680 }
681
682 /*
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.
687  * 4) Test cursor.
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.
691  *
692  * What is not tested but should be:
693  * 1) ScreenBufferInfo
694  */
695 static void testScreenBuffer(HANDLE hConOut)
696 {
697     HANDLE hConOutRW, hConOutRO, hConOutWT;
698     HANDLE hFileOutRW, hFileOutRO, hFileOutWT;
699     HANDLE hConOutNew;
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};
705     WCHAR str_wbuf[20];
706     char str_buf[20];
707     DWORD len;
708     COORD c;
709     BOOL ret;
710     DWORD oldcp;
711
712     if (!IsValidCodePage(866))
713     {
714         skip("Codepage 866 not available\n");
715         return;
716     }
717
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)
723     {
724         win_skip("SetConsoleOutputCP is not implemented\n");
725         return;
726     }
727     ok(ret, "Cannot set output codepage to 866\n");
728
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");
744
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");
755
756     /* Trying to set invalid handle */
757     SetLastError(0);
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());
763
764     /* Trying to set non-console handles */
765     SetLastError(0);
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());
770
771     SetLastError(0);
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());
776
777     SetLastError(0);
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());
782
783     CloseHandle(hFileOutRW);
784     CloseHandle(hFileOutRO);
785     CloseHandle(hFileOutWT);
786
787     /* Trying to set SB handles with various access modes */
788     SetLastError(0);
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());
793
794     ok(SetConsoleActiveScreenBuffer(hConOutWT), "Couldn't set new WriteOnly SB\n");
795
796     ok(SetConsoleActiveScreenBuffer(hConOutRW), "Couldn't set new ReadWrite SB\n");
797
798     CloseHandle(hConOutWT);
799     CloseHandle(hConOutRO);
800
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");
806
807
808     /* test cursor */
809     c.X = c.Y = 10;
810     SetConsoleCursorPosition(hConOut, c);
811     c.X = c.Y = 5;
812     SetConsoleCursorPosition(hConOutRW, c);
813     okCURSOR(hConOutNew, c);
814     c.X = c.Y = 10;
815     okCURSOR(hConOut, c);
816
817
818     c.X = c.Y = 0;
819
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);
829
830
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");
839
840     /*
841      * cp866 is OK, let's switch to cp1251.
842      * We expect that this codepage will be used in every SB - active and not.
843      */
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");
852
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");
861
862     /* Close all handles of current console SB */
863     CloseHandle(hConOutNew);
864     CloseHandle(hConOutRW);
865
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");
870
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);
881
882     /* This is not really needed under Windows */
883     SetConsoleActiveScreenBuffer(hConOut);
884
885     /* restore codepage */
886     SetConsoleOutputCP(oldcp);
887 }
888
889 static void test_GetSetConsoleInputExeName(void)
890 {
891     BOOL ret;
892     DWORD error;
893     char buffer[MAX_PATH], module[MAX_PATH], *p;
894     static char input_exe[MAX_PATH] = "winetest.exe";
895
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);
901
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);
907
908     GetModuleFileNameA(GetModuleHandle(NULL), module, sizeof(module));
909     p = strrchr(module, '\\') + 1;
910
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);
914
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);
920
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);
926
927     ret = pSetConsoleInputExeNameA(input_exe);
928     ok(ret, "SetConsoleInputExeNameA failed\n");
929
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);
933 }
934
935 static void test_GetConsoleProcessList(void)
936 {
937     DWORD ret, *list = NULL;
938
939     if (!pGetConsoleProcessList)
940     {
941         win_skip("GetConsoleProcessList is not available\n");
942         return;
943     }
944
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",
950        GetLastError());
951
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",
957        GetLastError());
958
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.
962      */
963     list = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));
964
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",
970        GetLastError());
971
972     SetLastError(0xdeadbeef);
973     ret = pGetConsoleProcessList(list, 1);
974     todo_wine
975     ok(ret == 1, "Expected 1, got %d\n", ret);
976
977     HeapFree(GetProcessHeap(), 0, list);
978
979     list = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(DWORD));
980
981     SetLastError(0xdeadbeef);
982     ret = pGetConsoleProcessList(list, ret);
983     todo_wine
984     ok(ret == 1, "Expected 1, got %d\n", ret);
985
986     if (ret == 1)
987     {
988         DWORD pid = GetCurrentProcessId();
989         ok(list[0] == pid, "Expected %d, got %d\n", pid, list[0]);
990     }
991
992     HeapFree(GetProcessHeap(), 0, list);
993 }
994
995 static void test_OpenCON(void)
996 {
997     static const WCHAR conW[] = {'C','O','N',0};
998     static const DWORD accesses[] = {CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING,
999                                      OPEN_ALWAYS, TRUNCATE_EXISTING};
1000     unsigned            i;
1001     HANDLE              h;
1002
1003     for (i = 0; i < sizeof(accesses) / sizeof(accesses[0]); i++)
1004     {
1005         h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1006         ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on write (%x)\n", accesses[i]);
1007         CloseHandle(h);
1008
1009         h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL);
1010         /* Windows versions differ here:
1011          * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1012          * NT, XP, Vista comply, but Win7 doesn't and allows to open CON with TRUNCATE_EXISTING
1013          * So don't test when disposition is TRUNCATE_EXISTING
1014          */
1015         if (accesses[i] != TRUNCATE_EXISTING)
1016         {
1017             ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on read (%x)\n", accesses[i]);
1018         }
1019         CloseHandle(h);
1020         h = CreateFileW(conW, GENERIC_READ|GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1021         ok(h == INVALID_HANDLE_VALUE, "Expected not to open the CON device on read-write (%x)\n", accesses[i]);
1022         ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Unexpected error %x\n", GetLastError());
1023     }
1024 }
1025
1026 static void test_OpenConsoleW(void)
1027 {
1028     static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1029     static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1030     static const WCHAR emptyW[] = {0};
1031     static const WCHAR invalidW[] = {'I','N','V','A','L','I','D',0};
1032
1033     static const struct
1034     {
1035         LPCWSTR name;
1036         DWORD access;
1037         BOOL inherit;
1038         DWORD creation;
1039         DWORD gle;
1040     } invalid_table[] = {
1041         {NULL,     0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
1042         {NULL,     0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1043         {NULL,     0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1044         {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
1045         {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1046         {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
1047         {emptyW,   0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
1048         {emptyW,   0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1049         {emptyW,   0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1050         {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
1051         {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1052         {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
1053         {invalidW, 0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
1054         {invalidW, 0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1055         {invalidW, 0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1056         {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
1057         {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1058         {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
1059         {coninW,   0,                            FALSE,      0,                 ERROR_SHARING_VIOLATION},
1060         {coninW,   0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1061         {coninW,   0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1062         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_SHARING_VIOLATION},
1063         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        ERROR_SHARING_VIOLATION},
1064         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     ERROR_SHARING_VIOLATION},
1065         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1066         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
1067         {conoutW,  0,                            FALSE,      0,                 ERROR_SHARING_VIOLATION},
1068         {conoutW,  0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1069         {conoutW,  0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1070         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_SHARING_VIOLATION},
1071         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        ERROR_SHARING_VIOLATION},
1072         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     ERROR_SHARING_VIOLATION},
1073         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1074         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
1075     };
1076
1077     int index;
1078     HANDLE ret;
1079
1080     if (!pOpenConsoleW)
1081     {
1082         win_skip("OpenConsoleW is not available\n");
1083         return;
1084     }
1085
1086     for (index = 0; index < sizeof(invalid_table)/sizeof(invalid_table[0]); index++)
1087     {
1088         SetLastError(0xdeadbeef);
1089         ret = pOpenConsoleW(invalid_table[index].name, invalid_table[index].access,
1090                             invalid_table[index].inherit, invalid_table[index].creation);
1091         ok(ret == INVALID_HANDLE_VALUE,
1092            "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1093            index, ret);
1094         ok(GetLastError() == invalid_table[index].gle,
1095            "Expected GetLastError() to return %u for index %d, got %u\n",
1096            invalid_table[index].gle, index, GetLastError());
1097     }
1098
1099     /* OpenConsoleW should not touch the last error on success. */
1100     SetLastError(0xdeadbeef);
1101     ret = pOpenConsoleW(coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1102     ok(ret != INVALID_HANDLE_VALUE,
1103        "Expected OpenConsoleW to return a valid handle\n");
1104     ok(GetLastError() == 0xdeadbeef,
1105        "Expected the last error to be untouched, got %u\n", GetLastError());
1106     if (ret != INVALID_HANDLE_VALUE)
1107         CloseHandle(ret);
1108
1109     SetLastError(0xdeadbeef);
1110     ret = pOpenConsoleW(conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1111     ok(ret != INVALID_HANDLE_VALUE,
1112        "Expected OpenConsoleW to return a valid handle\n");
1113     ok(GetLastError() == 0xdeadbeef,
1114        "Expected the last error to be untouched, got %u\n", GetLastError());
1115     if (ret != INVALID_HANDLE_VALUE)
1116         CloseHandle(ret);
1117 }
1118
1119 static void test_CreateFileW(void)
1120 {
1121     static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1122     static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1123
1124     static const struct
1125     {
1126         LPCWSTR name;
1127         DWORD access;
1128         BOOL inherit;
1129         DWORD creation;
1130         DWORD gle;
1131         BOOL is_broken;
1132     } cf_table[] = {
1133         {coninW,   0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
1134         {coninW,   0,                            FALSE,      OPEN_ALWAYS,       0,                              FALSE},
1135         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
1136         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        0,                              FALSE},
1137         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     0,                              FALSE},
1138         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       0,                              FALSE},
1139         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, 0,                              FALSE},
1140         {conoutW,  0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
1141         {conoutW,  0,                            FALSE,      OPEN_ALWAYS,       0,                              FALSE},
1142         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
1143         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        0,                              FALSE},
1144         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     0,                              FALSE},
1145         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       0,                              FALSE},
1146         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, 0,                              FALSE},
1147     };
1148
1149     int index;
1150     HANDLE ret;
1151     SECURITY_ATTRIBUTES sa;
1152
1153     for (index = 0; index < sizeof(cf_table)/sizeof(cf_table[0]); index++)
1154     {
1155         SetLastError(0xdeadbeef);
1156
1157         sa.nLength = sizeof(sa);
1158         sa.lpSecurityDescriptor = NULL;
1159         sa.bInheritHandle = cf_table[index].inherit;
1160
1161         ret = CreateFileW(cf_table[index].name, cf_table[index].access,
1162                           FILE_SHARE_READ|FILE_SHARE_WRITE, &sa,
1163                           cf_table[index].creation, FILE_ATTRIBUTE_NORMAL, NULL);
1164         if (ret == INVALID_HANDLE_VALUE)
1165         {
1166             ok(cf_table[index].gle,
1167                "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index);
1168             ok(GetLastError() == cf_table[index].gle,
1169                 "Expected GetLastError() to return %u for index %d, got %u\n",
1170                 cf_table[index].gle, index, GetLastError());
1171         }
1172         else
1173         {
1174             ok(!cf_table[index].gle || broken(cf_table[index].is_broken) /* Win7 */,
1175                "Expected CreateFileW to succeed for index %d\n", index);
1176             CloseHandle(ret);
1177         }
1178     }
1179 }
1180
1181 static void test_VerifyConsoleIoHandle( HANDLE handle )
1182 {
1183     BOOL ret;
1184     DWORD error;
1185
1186     if (!pVerifyConsoleIoHandle)
1187     {
1188         win_skip("VerifyConsoleIoHandle is not available\n");
1189         return;
1190     }
1191
1192     /* invalid handle */
1193     SetLastError(0xdeadbeef);
1194     ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee0);
1195     error = GetLastError();
1196     ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1197     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1198
1199     /* invalid handle + 1 */
1200     SetLastError(0xdeadbeef);
1201     ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee1);
1202     error = GetLastError();
1203     ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1204     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1205
1206     /* invalid handle + 2 */
1207     SetLastError(0xdeadbeef);
1208     ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee2);
1209     error = GetLastError();
1210     ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1211     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1212
1213     /* invalid handle + 3 */
1214     SetLastError(0xdeadbeef);
1215     ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee3);
1216     error = GetLastError();
1217     ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1218     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1219
1220     /* valid handle */
1221     SetLastError(0xdeadbeef);
1222     ret = pVerifyConsoleIoHandle(handle);
1223     error = GetLastError();
1224     ok(ret, "expected VerifyConsoleIoHandle to succeed\n");
1225     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1226 }
1227
1228 static void test_GetSetStdHandle(void)
1229 {
1230     HANDLE handle;
1231     DWORD error;
1232     BOOL ret;
1233
1234     /* get invalid std handle */
1235     SetLastError(0xdeadbeef);
1236     handle = GetStdHandle(42);
1237     error = GetLastError();
1238     ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1239        "wrong GetLastError() %d\n", error);
1240     ok(handle == INVALID_HANDLE_VALUE, "expected INVALID_HANDLE_VALUE\n");
1241
1242     /* get valid */
1243     SetLastError(0xdeadbeef);
1244     handle = GetStdHandle(STD_INPUT_HANDLE);
1245     error = GetLastError();
1246     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1247
1248     /* set invalid std handle */
1249     SetLastError(0xdeadbeef);
1250     ret = SetStdHandle(42, handle);
1251     error = GetLastError();
1252     ok(!ret, "expected SetStdHandle to fail\n");
1253     ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1254        "wrong GetLastError() %d\n", error);
1255
1256     /* set valid (restore old value) */
1257     SetLastError(0xdeadbeef);
1258     ret = SetStdHandle(STD_INPUT_HANDLE, handle);
1259     error = GetLastError();
1260     ok(ret, "expected SetStdHandle to succeed\n");
1261     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1262 }
1263
1264 static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle)
1265 {
1266     DWORD count;
1267     BOOL ret;
1268     int i;
1269
1270     const struct
1271     {
1272         HANDLE handle;
1273         LPDWORD nrofevents;
1274         DWORD last_error;
1275     } invalid_table[] =
1276     {
1277         {NULL,                 NULL,   ERROR_INVALID_HANDLE},
1278         {NULL,                 &count, ERROR_INVALID_HANDLE},
1279         {INVALID_HANDLE_VALUE, NULL,   ERROR_INVALID_HANDLE},
1280         {INVALID_HANDLE_VALUE, &count, ERROR_INVALID_HANDLE},
1281     };
1282
1283     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1284     {
1285         SetLastError(0xdeadbeef);
1286         if (invalid_table[i].nrofevents) count = 0xdeadbeef;
1287         ret = GetNumberOfConsoleInputEvents(invalid_table[i].handle,
1288                                             invalid_table[i].nrofevents);
1289         ok(!ret, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i, ret);
1290         if (invalid_table[i].nrofevents)
1291         {
1292             ok(count == 0xdeadbeef,
1293                "[%d] Expected output count to be unmodified, got %u\n", i, count);
1294         }
1295         ok(GetLastError() == invalid_table[i].last_error,
1296            "[%d] Expected last error to be %u, got %u\n",
1297            i, invalid_table[i].last_error, GetLastError());
1298     }
1299
1300     /* Test crashes on Windows 7. */
1301     if (0)
1302     {
1303         SetLastError(0xdeadbeef);
1304         ret = GetNumberOfConsoleInputEvents(input_handle, NULL);
1305         ok(!ret, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret);
1306         ok(GetLastError() == ERROR_INVALID_ACCESS,
1307            "Expected last error to be ERROR_INVALID_ACCESS, got %u\n",
1308            GetLastError());
1309     }
1310
1311     count = 0xdeadbeef;
1312     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1313     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1314     ok(count != 0xdeadbeef, "Expected output count to initialized\n");
1315 }
1316
1317 static void test_WriteConsoleInputA(HANDLE input_handle)
1318 {
1319     INPUT_RECORD event;
1320     INPUT_RECORD event_list[5];
1321     MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1322     KEY_EVENT_RECORD key_event;
1323     DWORD count, console_mode;
1324     BOOL ret;
1325     int i;
1326
1327     const struct
1328     {
1329         HANDLE handle;
1330         const INPUT_RECORD *buffer;
1331         DWORD count;
1332         LPDWORD written;
1333         DWORD expected_count;
1334         DWORD last_error;
1335         int win7_crash;
1336     } invalid_table[] =
1337     {
1338         {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1339         {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1340         {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1341         {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1342         {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1343         {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1344         {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1345         {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1346         {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1347         {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1348         {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1349         {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1350         {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1351         {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1352         {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1353         {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1354         {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1355         {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1356         {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1357         {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1358         {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1359     };
1360
1361     /* Suppress external sources of input events for the duration of the test. */
1362     ret = GetConsoleMode(input_handle, &console_mode);
1363     ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1364     if (!ret)
1365     {
1366         skip("GetConsoleMode failed with last error %u\n", GetLastError());
1367         return;
1368     }
1369
1370     ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1371     ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1372     if (!ret)
1373     {
1374         skip("SetConsoleMode failed with last error %u\n", GetLastError());
1375         return;
1376     }
1377
1378     /* Discard any events queued before the tests. */
1379     ret = FlushConsoleInputBuffer(input_handle);
1380     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1381
1382     event.EventType = MOUSE_EVENT;
1383     event.Event.MouseEvent = mouse_event;
1384
1385     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1386     {
1387         if (invalid_table[i].win7_crash)
1388             continue;
1389
1390         SetLastError(0xdeadbeef);
1391         if (invalid_table[i].written) count = 0xdeadbeef;
1392         ret = WriteConsoleInputA(invalid_table[i].handle,
1393                                  invalid_table[i].buffer,
1394                                  invalid_table[i].count,
1395                                  invalid_table[i].written);
1396         ok(!ret, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i, ret);
1397         if (invalid_table[i].written)
1398         {
1399             ok(count == invalid_table[i].expected_count,
1400                "[%d] Expected output count to be %u, got %u\n",
1401                i, invalid_table[i].expected_count, count);
1402         }
1403         ok(GetLastError() == invalid_table[i].last_error,
1404            "[%d] Expected last error to be %u, got %u\n",
1405            i, invalid_table[i].last_error, GetLastError());
1406     }
1407
1408     count = 0xdeadbeef;
1409     ret = WriteConsoleInputA(input_handle, NULL, 0, &count);
1410     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1411     ok(count == 0, "Expected count to be 0, got %u\n", count);
1412
1413     count = 0xdeadbeef;
1414     ret = WriteConsoleInputA(input_handle, &event, 0, &count);
1415     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1416     ok(count == 0, "Expected count to be 0, got %u\n", count);
1417
1418     count = 0xdeadbeef;
1419     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1420     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1421     ok(count == 1, "Expected count to be 1, got %u\n", count);
1422
1423     ret = FlushConsoleInputBuffer(input_handle);
1424     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1425
1426     /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1427     event.EventType = MOUSE_EVENT;
1428     event.Event.MouseEvent = mouse_event;
1429
1430     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1431     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1432     ok(count == 1, "Expected count to be 1, got %u\n", count);
1433
1434     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1435     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1436     ok(count == 1, "Expected count to be 1, got %u\n", count);
1437
1438     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1439     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1440     ok(count == 1, "Expected count to be 1, got %u\n", count);
1441
1442     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1443     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1444     todo_wine
1445     ok(count == 1, "Expected count to be 1, got %u\n", count);
1446
1447     ret = FlushConsoleInputBuffer(input_handle);
1448     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1449
1450     for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1451     {
1452         event_list[i].EventType = MOUSE_EVENT;
1453         event_list[i].Event.MouseEvent = mouse_event;
1454     }
1455
1456     /* Writing consecutive chunks of mouse events appears to work. */
1457     ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1458     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1459     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1460        "Expected count to be event list length, got %u\n", count);
1461
1462     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1463     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1464     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1465        "Expected count to be event list length, got %u\n", count);
1466
1467     ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1468     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1469     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1470        "Expected count to be event list length, got %u\n", count);
1471
1472     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1473     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1474     ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1475        "Expected count to be twice event list length, got %u\n", count);
1476
1477     /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1478     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1479     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1480     ok(count == 1, "Expected count to be 1, got %u\n", count);
1481
1482     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1483     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1484     todo_wine
1485     ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1486        "Expected count to be twice event list length, got %u\n", count);
1487
1488     ret = FlushConsoleInputBuffer(input_handle);
1489     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1490
1491     key_event.bKeyDown = FALSE;
1492     key_event.wRepeatCount = 0;
1493     key_event.wVirtualKeyCode = VK_SPACE;
1494     key_event.wVirtualScanCode = VK_SPACE;
1495     key_event.uChar.AsciiChar = ' ';
1496     key_event.dwControlKeyState = 0;
1497
1498     event.EventType = KEY_EVENT;
1499     event.Event.KeyEvent = key_event;
1500
1501     /* Key events don't exhibit the same behavior as mouse events. */
1502     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1503     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1504     ok(count == 1, "Expected count to be 1, got %u\n", count);
1505
1506     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1507     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1508     ok(count == 1, "Expected count to be 1, got %u\n", count);
1509
1510     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1511     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1512     ok(count == 1, "Expected count to be 1, got %u\n", count);
1513
1514     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1515     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1516     ok(count == 2, "Expected count to be 2, got %u\n", count);
1517
1518     ret = FlushConsoleInputBuffer(input_handle);
1519     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1520
1521     /* Try interleaving mouse and key events. */
1522     event.EventType = MOUSE_EVENT;
1523     event.Event.MouseEvent = mouse_event;
1524
1525     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1526     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1527     ok(count == 1, "Expected count to be 1, got %u\n", count);
1528
1529     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1530     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1531     ok(count == 1, "Expected count to be 1, got %u\n", count);
1532
1533     event.EventType = KEY_EVENT;
1534     event.Event.KeyEvent = key_event;
1535
1536     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1537     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1538     ok(count == 1, "Expected count to be 1, got %u\n", count);
1539
1540     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1541     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1542     ok(count == 2, "Expected count to be 2, got %u\n", count);
1543
1544     event.EventType = MOUSE_EVENT;
1545     event.Event.MouseEvent = mouse_event;
1546
1547     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1548     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1549     ok(count == 1, "Expected count to be 1, got %u\n", count);
1550
1551     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1552     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1553     ok(count == 3, "Expected count to be 3, got %u\n", count);
1554
1555     /* Restore the old console mode. */
1556     ret = SetConsoleMode(input_handle, console_mode);
1557     ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1558 }
1559
1560 static void test_WriteConsoleInputW(HANDLE input_handle)
1561 {
1562     INPUT_RECORD event;
1563     INPUT_RECORD event_list[5];
1564     MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1565     KEY_EVENT_RECORD key_event;
1566     DWORD count, console_mode;
1567     BOOL ret;
1568     int i;
1569
1570     const struct
1571     {
1572         HANDLE handle;
1573         const INPUT_RECORD *buffer;
1574         DWORD count;
1575         LPDWORD written;
1576         DWORD expected_count;
1577         DWORD last_error;
1578         int win7_crash;
1579     } invalid_table[] =
1580     {
1581         {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1582         {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1583         {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1584         {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1585         {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1586         {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1587         {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1588         {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1589         {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1590         {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1591         {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1592         {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1593         {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1594         {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1595         {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1596         {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1597         {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1598         {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1599         {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1600         {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1601         {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1602     };
1603
1604     /* Suppress external sources of input events for the duration of the test. */
1605     ret = GetConsoleMode(input_handle, &console_mode);
1606     ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1607     if (!ret)
1608     {
1609         skip("GetConsoleMode failed with last error %u\n", GetLastError());
1610         return;
1611     }
1612
1613     ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1614     ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1615     if (!ret)
1616     {
1617         skip("SetConsoleMode failed with last error %u\n", GetLastError());
1618         return;
1619     }
1620
1621     /* Discard any events queued before the tests. */
1622     ret = FlushConsoleInputBuffer(input_handle);
1623     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1624
1625     event.EventType = MOUSE_EVENT;
1626     event.Event.MouseEvent = mouse_event;
1627
1628     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1629     {
1630         if (invalid_table[i].win7_crash)
1631             continue;
1632
1633         SetLastError(0xdeadbeef);
1634         if (invalid_table[i].written) count = 0xdeadbeef;
1635         ret = WriteConsoleInputW(invalid_table[i].handle,
1636                                  invalid_table[i].buffer,
1637                                  invalid_table[i].count,
1638                                  invalid_table[i].written);
1639         ok(!ret, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i, ret);
1640         if (invalid_table[i].written)
1641         {
1642             ok(count == invalid_table[i].expected_count,
1643                "[%d] Expected output count to be %u, got %u\n",
1644                i, invalid_table[i].expected_count, count);
1645         }
1646         ok(GetLastError() == invalid_table[i].last_error,
1647            "[%d] Expected last error to be %u, got %u\n",
1648            i, invalid_table[i].last_error, GetLastError());
1649     }
1650
1651     count = 0xdeadbeef;
1652     ret = WriteConsoleInputW(input_handle, NULL, 0, &count);
1653     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1654     ok(count == 0, "Expected count to be 0, got %u\n", count);
1655
1656     count = 0xdeadbeef;
1657     ret = WriteConsoleInputW(input_handle, &event, 0, &count);
1658     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1659     ok(count == 0, "Expected count to be 0, got %u\n", count);
1660
1661     count = 0xdeadbeef;
1662     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1663     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1664     ok(count == 1, "Expected count to be 1, got %u\n", count);
1665
1666     ret = FlushConsoleInputBuffer(input_handle);
1667     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1668
1669     /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1670     event.EventType = MOUSE_EVENT;
1671     event.Event.MouseEvent = mouse_event;
1672
1673     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1674     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1675     ok(count == 1, "Expected count to be 1, got %u\n", count);
1676
1677     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1678     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1679     ok(count == 1, "Expected count to be 1, got %u\n", count);
1680
1681     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1682     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1683     ok(count == 1, "Expected count to be 1, got %u\n", count);
1684
1685     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1686     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1687     todo_wine
1688     ok(count == 1, "Expected count to be 1, got %u\n", count);
1689
1690     ret = FlushConsoleInputBuffer(input_handle);
1691     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1692
1693     for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1694     {
1695         event_list[i].EventType = MOUSE_EVENT;
1696         event_list[i].Event.MouseEvent = mouse_event;
1697     }
1698
1699     /* Writing consecutive chunks of mouse events appears to work. */
1700     ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1701     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1702     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1703        "Expected count to be event list length, got %u\n", count);
1704
1705     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1706     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1707     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1708        "Expected count to be event list length, got %u\n", count);
1709
1710     ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1711     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1712     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1713        "Expected count to be event list length, got %u\n", count);
1714
1715     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1716     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1717     ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1718        "Expected count to be twice event list length, got %u\n", count);
1719
1720     /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1721     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1722     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1723     ok(count == 1, "Expected count to be 1, got %u\n", count);
1724
1725     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1726     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1727     todo_wine
1728     ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1729        "Expected count to be twice event list length, got %u\n", count);
1730
1731     ret = FlushConsoleInputBuffer(input_handle);
1732     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1733
1734     key_event.bKeyDown = FALSE;
1735     key_event.wRepeatCount = 0;
1736     key_event.wVirtualKeyCode = VK_SPACE;
1737     key_event.wVirtualScanCode = VK_SPACE;
1738     key_event.uChar.UnicodeChar = ' ';
1739     key_event.dwControlKeyState = 0;
1740
1741     event.EventType = KEY_EVENT;
1742     event.Event.KeyEvent = key_event;
1743
1744     /* Key events don't exhibit the same behavior as mouse events. */
1745     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1746     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1747     ok(count == 1, "Expected count to be 1, got %u\n", count);
1748
1749     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1750     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1751     ok(count == 1, "Expected count to be 1, got %u\n", count);
1752
1753     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1754     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1755     ok(count == 1, "Expected count to be 1, got %u\n", count);
1756
1757     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1758     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1759     ok(count == 2, "Expected count to be 2, got %u\n", count);
1760
1761     ret = FlushConsoleInputBuffer(input_handle);
1762     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1763
1764     /* Try interleaving mouse and key events. */
1765     event.EventType = MOUSE_EVENT;
1766     event.Event.MouseEvent = mouse_event;
1767
1768     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1769     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1770     ok(count == 1, "Expected count to be 1, got %u\n", count);
1771
1772     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1773     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1774     ok(count == 1, "Expected count to be 1, got %u\n", count);
1775
1776     event.EventType = KEY_EVENT;
1777     event.Event.KeyEvent = key_event;
1778
1779     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1780     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1781     ok(count == 1, "Expected count to be 1, got %u\n", count);
1782
1783     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1784     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1785     ok(count == 2, "Expected count to be 2, got %u\n", count);
1786
1787     event.EventType = MOUSE_EVENT;
1788     event.Event.MouseEvent = mouse_event;
1789
1790     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1791     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1792     ok(count == 1, "Expected count to be 1, got %u\n", count);
1793
1794     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1795     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1796     ok(count == 3, "Expected count to be 3, got %u\n", count);
1797
1798     /* Restore the old console mode. */
1799     ret = SetConsoleMode(input_handle, console_mode);
1800     ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1801 }
1802
1803 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle)
1804 {
1805     static const char output[] = {'a', 0};
1806
1807     COORD origin = {0, 0};
1808     DWORD count;
1809     BOOL ret;
1810     int i;
1811
1812     const struct
1813     {
1814         HANDLE hConsoleOutput;
1815         LPCSTR str;
1816         DWORD length;
1817         COORD coord;
1818         LPDWORD lpNumCharsWritten;
1819         DWORD expected_count;
1820         DWORD last_error;
1821         int win7_crash;
1822     } invalid_table[] =
1823     {
1824         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1825         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1826         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1827         {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1828         {NULL, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1829         {NULL, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1830         {NULL, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1831         {NULL, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1832         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1833         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1834         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1835         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1836         {INVALID_HANDLE_VALUE, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1837         {INVALID_HANDLE_VALUE, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1838         {INVALID_HANDLE_VALUE, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1839         {INVALID_HANDLE_VALUE, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1840         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1841         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1842         {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1843         {output_handle, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1844         {output_handle, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1845     };
1846
1847     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1848     {
1849         if (invalid_table[i].win7_crash)
1850             continue;
1851
1852         SetLastError(0xdeadbeef);
1853         if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1854         ret = WriteConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
1855                                            invalid_table[i].str,
1856                                            invalid_table[i].length,
1857                                            invalid_table[i].coord,
1858                                            invalid_table[i].lpNumCharsWritten);
1859         ok(!ret, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
1860         if (invalid_table[i].lpNumCharsWritten)
1861         {
1862             ok(count == invalid_table[i].expected_count,
1863                "[%d] Expected count to be %u, got %u\n",
1864                i, invalid_table[i].expected_count, count);
1865         }
1866         ok(GetLastError() == invalid_table[i].last_error,
1867            "[%d] Expected last error to be %u, got %u\n",
1868            i, invalid_table[i].last_error, GetLastError());
1869     }
1870
1871     count = 0xdeadbeef;
1872     ret = WriteConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
1873     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1874     ok(count == 0, "Expected count to be 0, got %u\n", count);
1875
1876     count = 0xdeadbeef;
1877     ret = WriteConsoleOutputCharacterA(output_handle, output, 0, origin, &count);
1878     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1879     ok(count == 0, "Expected count to be 0, got %u\n", count);
1880
1881     count = 0xdeadbeef;
1882     ret = WriteConsoleOutputCharacterA(output_handle, output, 1, origin, &count);
1883     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1884     ok(count == 1, "Expected count to be 1, got %u\n", count);
1885 }
1886
1887 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle)
1888 {
1889     static const WCHAR outputW[] = {'a',0};
1890
1891     COORD origin = {0, 0};
1892     DWORD count;
1893     BOOL ret;
1894     int i;
1895
1896     const struct
1897     {
1898         HANDLE hConsoleOutput;
1899         LPCWSTR str;
1900         DWORD length;
1901         COORD coord;
1902         LPDWORD lpNumCharsWritten;
1903         DWORD expected_count;
1904         DWORD last_error;
1905         int win7_crash;
1906     } invalid_table[] =
1907     {
1908         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1909         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1910         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1911         {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1912         {NULL, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1913         {NULL, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1914         {NULL, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1915         {NULL, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1916         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1917         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1918         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1919         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1920         {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1921         {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1922         {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1923         {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1924         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1925         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1926         {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1927         {output_handle, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1928         {output_handle, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1929     };
1930
1931     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1932     {
1933         if (invalid_table[i].win7_crash)
1934             continue;
1935
1936         SetLastError(0xdeadbeef);
1937         if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1938         ret = WriteConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
1939                                            invalid_table[i].str,
1940                                            invalid_table[i].length,
1941                                            invalid_table[i].coord,
1942                                            invalid_table[i].lpNumCharsWritten);
1943         ok(!ret, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
1944         if (invalid_table[i].lpNumCharsWritten)
1945         {
1946             ok(count == invalid_table[i].expected_count,
1947                "[%d] Expected count to be %u, got %u\n",
1948                i, invalid_table[i].expected_count, count);
1949         }
1950         ok(GetLastError() == invalid_table[i].last_error,
1951            "[%d] Expected last error to be %u, got %u\n",
1952            i, invalid_table[i].last_error, GetLastError());
1953     }
1954
1955     count = 0xdeadbeef;
1956     ret = WriteConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
1957     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1958     ok(count == 0, "Expected count to be 0, got %u\n", count);
1959
1960     count = 0xdeadbeef;
1961     ret = WriteConsoleOutputCharacterW(output_handle, outputW, 0, origin, &count);
1962     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1963     ok(count == 0, "Expected count to be 0, got %u\n", count);
1964
1965     count = 0xdeadbeef;
1966     ret = WriteConsoleOutputCharacterW(output_handle, outputW, 1, origin, &count);
1967     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1968     ok(count == 1, "Expected count to be 1, got %u\n", count);
1969 }
1970
1971 static void test_WriteConsoleOutputAttribute(HANDLE output_handle)
1972 {
1973     WORD attr = FOREGROUND_BLUE;
1974     COORD origin = {0, 0};
1975     DWORD count;
1976     BOOL ret;
1977     int i;
1978
1979     const struct
1980     {
1981         HANDLE hConsoleOutput;
1982         CONST WORD *attr;
1983         DWORD length;
1984         COORD coord;
1985         LPDWORD lpNumAttrsWritten;
1986         DWORD expected_count;
1987         DWORD last_error;
1988         int win7_crash;
1989     } invalid_table[] =
1990     {
1991         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1992         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1993         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1994         {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1995         {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1996         {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1997         {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1998         {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1999         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2000         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2001         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2002         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2003         {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2004         {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2005         {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2006         {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2007         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2008         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2009         {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2010         {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2011         {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2012     };
2013
2014     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2015     {
2016         if (invalid_table[i].win7_crash)
2017             continue;
2018
2019         SetLastError(0xdeadbeef);
2020         if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2021         ret = WriteConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2022                                           invalid_table[i].attr,
2023                                           invalid_table[i].length,
2024                                           invalid_table[i].coord,
2025                                           invalid_table[i].lpNumAttrsWritten);
2026         ok(!ret, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2027         if (invalid_table[i].lpNumAttrsWritten)
2028         {
2029             ok(count == invalid_table[i].expected_count,
2030                "[%d] Expected count to be %u, got %u\n",
2031                i, invalid_table[i].expected_count, count);
2032         }
2033         ok(GetLastError() == invalid_table[i].last_error,
2034            "[%d] Expected last error to be %u, got %u\n",
2035            i, invalid_table[i].last_error, GetLastError());
2036     }
2037
2038     count = 0xdeadbeef;
2039     ret = WriteConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2040     ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2041     ok(count == 0, "Expected count to be 0, got %u\n", count);
2042
2043     count = 0xdeadbeef;
2044     ret = WriteConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2045     ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2046     ok(count == 0, "Expected count to be 0, got %u\n", count);
2047
2048     count = 0xdeadbeef;
2049     ret = WriteConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2050     ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2051     ok(count == 1, "Expected count to be 1, got %u\n", count);
2052 }
2053
2054 static void test_FillConsoleOutputCharacterA(HANDLE output_handle)
2055 {
2056     COORD origin = {0, 0};
2057     DWORD count;
2058     BOOL ret;
2059     int i;
2060
2061     const struct
2062     {
2063         HANDLE hConsoleOutput;
2064         CHAR ch;
2065         DWORD length;
2066         COORD coord;
2067         LPDWORD lpNumCharsWritten;
2068         DWORD expected_count;
2069         DWORD last_error;
2070         int win7_crash;
2071     } invalid_table[] =
2072     {
2073         {NULL, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2074         {NULL, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2075         {NULL, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2076         {NULL, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2077         {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2078         {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2079         {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2080         {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2081         {output_handle, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2082         {output_handle, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2083     };
2084
2085     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2086     {
2087         if (invalid_table[i].win7_crash)
2088             continue;
2089
2090         SetLastError(0xdeadbeef);
2091         if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2092         ret = FillConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2093                                           invalid_table[i].ch,
2094                                           invalid_table[i].length,
2095                                           invalid_table[i].coord,
2096                                           invalid_table[i].lpNumCharsWritten);
2097         ok(!ret, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2098         if (invalid_table[i].lpNumCharsWritten)
2099         {
2100             ok(count == invalid_table[i].expected_count,
2101                "[%d] Expected count to be %u, got %u\n",
2102                i, invalid_table[i].expected_count, count);
2103         }
2104         ok(GetLastError() == invalid_table[i].last_error,
2105            "[%d] Expected last error to be %u, got %u\n",
2106            i, invalid_table[i].last_error, GetLastError());
2107     }
2108
2109     count = 0xdeadbeef;
2110     ret = FillConsoleOutputCharacterA(output_handle, 'a', 0, origin, &count);
2111     ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2112     ok(count == 0, "Expected count to be 0, got %u\n", count);
2113
2114     count = 0xdeadbeef;
2115     ret = FillConsoleOutputCharacterA(output_handle, 'a', 1, origin, &count);
2116     ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2117     ok(count == 1, "Expected count to be 1, got %u\n", count);
2118 }
2119
2120 static void test_FillConsoleOutputCharacterW(HANDLE output_handle)
2121 {
2122     COORD origin = {0, 0};
2123     DWORD count;
2124     BOOL ret;
2125     int i;
2126
2127     const struct
2128     {
2129         HANDLE hConsoleOutput;
2130         WCHAR ch;
2131         DWORD length;
2132         COORD coord;
2133         LPDWORD lpNumCharsWritten;
2134         DWORD expected_count;
2135         DWORD last_error;
2136         int win7_crash;
2137     } invalid_table[] =
2138     {
2139         {NULL, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2140         {NULL, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2141         {NULL, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2142         {NULL, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2143         {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2144         {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2145         {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2146         {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2147         {output_handle, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2148         {output_handle, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2149     };
2150
2151     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2152     {
2153         if (invalid_table[i].win7_crash)
2154             continue;
2155
2156         SetLastError(0xdeadbeef);
2157         if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2158         ret = FillConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2159                                           invalid_table[i].ch,
2160                                           invalid_table[i].length,
2161                                           invalid_table[i].coord,
2162                                           invalid_table[i].lpNumCharsWritten);
2163         ok(!ret, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2164         if (invalid_table[i].lpNumCharsWritten)
2165         {
2166             ok(count == invalid_table[i].expected_count,
2167                "[%d] Expected count to be %u, got %u\n",
2168                i, invalid_table[i].expected_count, count);
2169         }
2170         ok(GetLastError() == invalid_table[i].last_error,
2171            "[%d] Expected last error to be %u, got %u\n",
2172            i, invalid_table[i].last_error, GetLastError());
2173     }
2174
2175     count = 0xdeadbeef;
2176     ret = FillConsoleOutputCharacterW(output_handle, 'a', 0, origin, &count);
2177     ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2178     ok(count == 0, "Expected count to be 0, got %u\n", count);
2179
2180     count = 0xdeadbeef;
2181     ret = FillConsoleOutputCharacterW(output_handle, 'a', 1, origin, &count);
2182     ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2183     ok(count == 1, "Expected count to be 1, got %u\n", count);
2184 }
2185
2186 static void test_FillConsoleOutputAttribute(HANDLE output_handle)
2187 {
2188     COORD origin = {0, 0};
2189     DWORD count;
2190     BOOL ret;
2191     int i;
2192
2193     const struct
2194     {
2195         HANDLE hConsoleOutput;
2196         WORD attr;
2197         DWORD length;
2198         COORD coord;
2199         LPDWORD lpNumAttrsWritten;
2200         DWORD expected_count;
2201         DWORD last_error;
2202         int win7_crash;
2203     } invalid_table[] =
2204     {
2205         {NULL, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2206         {NULL, FOREGROUND_BLUE, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2207         {NULL, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2208         {NULL, FOREGROUND_BLUE, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2209         {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2210         {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2211         {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2212         {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2213         {output_handle, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2214         {output_handle, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2215     };
2216
2217     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2218     {
2219         if (invalid_table[i].win7_crash)
2220             continue;
2221
2222         SetLastError(0xdeadbeef);
2223         if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2224         ret = FillConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2225                                          invalid_table[i].attr,
2226                                          invalid_table[i].length,
2227                                          invalid_table[i].coord,
2228                                          invalid_table[i].lpNumAttrsWritten);
2229         ok(!ret, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2230         if (invalid_table[i].lpNumAttrsWritten)
2231         {
2232             ok(count == invalid_table[i].expected_count,
2233                "[%d] Expected count to be %u, got %u\n",
2234                i, invalid_table[i].expected_count, count);
2235         }
2236         ok(GetLastError() == invalid_table[i].last_error,
2237            "[%d] Expected last error to be %u, got %u\n",
2238            i, invalid_table[i].last_error, GetLastError());
2239     }
2240
2241     count = 0xdeadbeef;
2242     ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 0, origin, &count);
2243     ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2244     ok(count == 0, "Expected count to be 0, got %u\n", count);
2245
2246     count = 0xdeadbeef;
2247     ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 1, origin, &count);
2248     ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2249     ok(count == 1, "Expected count to be 1, got %u\n", count);
2250
2251     count = 0xdeadbeef;
2252     ret = FillConsoleOutputAttribute(output_handle, ~0, 1, origin, &count);
2253     ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2254     ok(count == 1, "Expected count to be 1, got %u\n", count);
2255 }
2256
2257 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle)
2258 {
2259     CHAR read;
2260     COORD origin = {0, 0};
2261     DWORD count;
2262     BOOL ret;
2263     int i;
2264
2265     const struct
2266     {
2267         HANDLE hConsoleOutput;
2268         LPSTR lpstr;
2269         DWORD length;
2270         COORD coord;
2271         LPDWORD read_count;
2272         DWORD expected_count;
2273         DWORD last_error;
2274         int win7_crash;
2275     } invalid_table[] =
2276     {
2277         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2278         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2279         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2280         {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2281         {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2282         {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2283         {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2284         {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2285         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2286         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2287         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2288         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2289         {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2290         {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2291         {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2292         {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2293         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2294         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2295         {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2296         {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1},
2297         {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2298         {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2299     };
2300
2301     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2302     {
2303         if (invalid_table[i].win7_crash)
2304             continue;
2305
2306         SetLastError(0xdeadbeef);
2307         if (invalid_table[i].read_count) count = 0xdeadbeef;
2308         ret = ReadConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2309                                           invalid_table[i].lpstr,
2310                                           invalid_table[i].length,
2311                                           invalid_table[i].coord,
2312                                           invalid_table[i].read_count);
2313         ok(!ret, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2314         if (invalid_table[i].read_count)
2315         {
2316             ok(count == invalid_table[i].expected_count,
2317                "[%d] Expected count to be %u, got %u\n",
2318                i, invalid_table[i].expected_count, count);
2319         }
2320         ok(GetLastError() == invalid_table[i].last_error,
2321            "[%d] Expected last error to be %u, got %u\n",
2322            i, invalid_table[i].last_error, GetLastError());
2323     }
2324
2325     count = 0xdeadbeef;
2326     ret = ReadConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
2327     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2328     ok(count == 0, "Expected count to be 0, got %u\n", count);
2329
2330     count = 0xdeadbeef;
2331     ret = ReadConsoleOutputCharacterA(output_handle, &read, 0, origin, &count);
2332     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2333     ok(count == 0, "Expected count to be 0, got %u\n", count);
2334
2335     count = 0xdeadbeef;
2336     ret = ReadConsoleOutputCharacterA(output_handle, &read, 1, origin, &count);
2337     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2338     ok(count == 1, "Expected count to be 1, got %u\n", count);
2339 }
2340
2341 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle)
2342 {
2343     WCHAR read;
2344     COORD origin = {0, 0};
2345     DWORD count;
2346     BOOL ret;
2347     int i;
2348
2349     const struct
2350     {
2351         HANDLE hConsoleOutput;
2352         LPWSTR buffer;
2353         DWORD length;
2354         COORD coord;
2355         LPDWORD read_count;
2356         DWORD expected_count;
2357         DWORD last_error;
2358         int win7_crash;
2359     } invalid_table[] =
2360     {
2361         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2362         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2363         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2364         {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2365         {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2366         {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2367         {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2368         {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2369         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2370         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2371         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2372         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2373         {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2374         {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2375         {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2376         {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2377         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2378         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2379         {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2380         {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1},
2381         {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2382         {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2383     };
2384
2385     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2386     {
2387         if (invalid_table[i].win7_crash)
2388             continue;
2389
2390         SetLastError(0xdeadbeef);
2391         if (invalid_table[i].read_count) count = 0xdeadbeef;
2392         ret = ReadConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2393                                           invalid_table[i].buffer,
2394                                           invalid_table[i].length,
2395                                           invalid_table[i].coord,
2396                                           invalid_table[i].read_count);
2397         ok(!ret, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2398         if (invalid_table[i].read_count)
2399         {
2400             ok(count == invalid_table[i].expected_count,
2401                "[%d] Expected count to be %u, got %u\n",
2402                i, invalid_table[i].expected_count, count);
2403         }
2404         ok(GetLastError() == invalid_table[i].last_error,
2405            "[%d] Expected last error to be %u, got %u\n",
2406            i, invalid_table[i].last_error, GetLastError());
2407     }
2408
2409     count = 0xdeadbeef;
2410     ret = ReadConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
2411     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2412     ok(count == 0, "Expected count to be 0, got %u\n", count);
2413
2414     count = 0xdeadbeef;
2415     ret = ReadConsoleOutputCharacterW(output_handle, &read, 0, origin, &count);
2416     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2417     ok(count == 0, "Expected count to be 0, got %u\n", count);
2418
2419     count = 0xdeadbeef;
2420     ret = ReadConsoleOutputCharacterW(output_handle, &read, 1, origin, &count);
2421     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2422     ok(count == 1, "Expected count to be 1, got %u\n", count);
2423 }
2424
2425 static void test_ReadConsoleOutputAttribute(HANDLE output_handle)
2426 {
2427     WORD attr;
2428     COORD origin = {0, 0};
2429     DWORD count;
2430     BOOL ret;
2431     int i;
2432
2433     const struct
2434     {
2435         HANDLE hConsoleOutput;
2436         LPWORD lpAttribute;
2437         DWORD length;
2438         COORD coord;
2439         LPDWORD read_count;
2440         DWORD expected_count;
2441         DWORD last_error;
2442         int win7_crash;
2443     } invalid_table[] =
2444     {
2445         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2446         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2447         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2448         {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2449         {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2450         {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2451         {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2452         {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2453         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2454         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2455         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2456         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2457         {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2458         {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2459         {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2460         {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2461         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2462         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2463         {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2464         {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2465         {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2466     };
2467
2468     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2469     {
2470         if (invalid_table[i].win7_crash)
2471             continue;
2472
2473         SetLastError(0xdeadbeef);
2474         if (invalid_table[i].read_count) count = 0xdeadbeef;
2475         ret = ReadConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2476                                          invalid_table[i].lpAttribute,
2477                                          invalid_table[i].length,
2478                                          invalid_table[i].coord,
2479                                          invalid_table[i].read_count);
2480         ok(!ret, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2481         if (invalid_table[i].read_count)
2482         {
2483             ok(count == invalid_table[i].expected_count,
2484                "[%d] Expected count to be %u, got %u\n",
2485                i, invalid_table[i].expected_count, count);
2486         }
2487         ok(GetLastError() == invalid_table[i].last_error,
2488            "[%d] Expected last error to be %u, got %u\n",
2489            i, invalid_table[i].last_error, GetLastError());
2490     }
2491
2492     count = 0xdeadbeef;
2493     ret = ReadConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2494     ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2495     ok(count == 0, "Expected count to be 0, got %u\n", count);
2496
2497     count = 0xdeadbeef;
2498     ret = ReadConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2499     ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2500     ok(count == 0, "Expected count to be 0, got %u\n", count);
2501
2502     count = 0xdeadbeef;
2503     ret = ReadConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2504     ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2505     ok(count == 1, "Expected count to be 1, got %u\n", count);
2506 }
2507
2508 START_TEST(console)
2509 {
2510     static const char font_name[] = "Lucida Console";
2511     HANDLE hConIn, hConOut;
2512     BOOL ret;
2513     CONSOLE_SCREEN_BUFFER_INFO  sbi;
2514     LONG err;
2515     HKEY console_key;
2516     char old_font[LF_FACESIZE];
2517     BOOL delete = FALSE;
2518     DWORD size;
2519
2520     init_function_pointers();
2521
2522     /* be sure we have a clean console (and that's our own)
2523      * FIXME: this will make the test fail (currently) if we don't run
2524      * under X11
2525      * Another solution would be to rerun the test under wineconsole with
2526      * the curses backend
2527      */
2528
2529     /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
2530      * correctly for characters that don't have a glyph in the console font. So,
2531      * we first set the console font to Lucida Console (which has a wider
2532      * selection of glyphs available than the default raster fonts). We want
2533      * to be able to restore the original font afterwards, so don't change
2534      * if we can't read the original font.
2535      */
2536     err = RegOpenKeyExA(HKEY_CURRENT_USER, "Console", 0,
2537                         KEY_QUERY_VALUE | KEY_SET_VALUE, &console_key);
2538     if (err == ERROR_SUCCESS)
2539     {
2540         size = sizeof(old_font);
2541         err = RegQueryValueExA(console_key, "FaceName", NULL, NULL,
2542                                (LPBYTE) old_font, &size);
2543         if (err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND)
2544         {
2545             delete = (err == ERROR_FILE_NOT_FOUND);
2546             err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
2547                                  (const BYTE *) font_name, sizeof(font_name));
2548             if (err != ERROR_SUCCESS)
2549                 trace("Unable to change default console font, error %d\n", err);
2550         }
2551         else
2552         {
2553             trace("Unable to query default console font, error %d\n", err);
2554             RegCloseKey(console_key);
2555             console_key = NULL;
2556         }
2557     }
2558     else
2559     {
2560         trace("Unable to open HKCU\\Console, error %d\n", err);
2561         console_key = NULL;
2562     }
2563
2564     /* Now detach and open a fresh console to play with */
2565     FreeConsole();
2566     ok(AllocConsole(), "Couldn't alloc console\n");
2567
2568     /* Restore default console font if needed */
2569     if (console_key != NULL)
2570     {
2571         if (delete)
2572             err = RegDeleteValueA(console_key, "FaceName");
2573         else
2574             err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
2575                                  (const BYTE *) old_font, strlen(old_font) + 1);
2576         ok(err == ERROR_SUCCESS, "Unable to restore default console font, error %d\n", err);
2577     }
2578     hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2579     hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2580
2581     /* now verify everything's ok */
2582     ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
2583     ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
2584
2585     ret = GetConsoleScreenBufferInfo(hConOut, &sbi);
2586     ok(ret, "Getting sb info\n");
2587     if (!ret) return;
2588
2589     /* Non interactive tests */
2590     testCursor(hConOut, sbi.dwSize);
2591     /* test parameters (FIXME: test functionality) */
2592     testCursorInfo(hConOut);
2593     /* will test wrapped (on/off) & processed (on/off) strings output */
2594     testWrite(hConOut, sbi.dwSize);
2595     /* will test line scrolling at the bottom of the screen */
2596     /* testBottomScroll(); */
2597     /* will test all the scrolling operations */
2598     testScroll(hConOut, sbi.dwSize);
2599     /* will test sb creation / modification / codepage handling */
2600     testScreenBuffer(hConOut);
2601     testCtrlHandler();
2602     /* still to be done: access rights & access on objects */
2603
2604     if (!pGetConsoleInputExeNameA || !pSetConsoleInputExeNameA)
2605         win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
2606     else
2607         test_GetSetConsoleInputExeName();
2608
2609     test_GetConsoleProcessList();
2610     test_OpenConsoleW();
2611     test_CreateFileW();
2612     test_OpenCON();
2613     test_VerifyConsoleIoHandle(hConOut);
2614     test_GetSetStdHandle();
2615     test_GetNumberOfConsoleInputEvents(hConIn);
2616     test_WriteConsoleInputA(hConIn);
2617     test_WriteConsoleInputW(hConIn);
2618     test_WriteConsoleOutputCharacterA(hConOut);
2619     test_WriteConsoleOutputCharacterW(hConOut);
2620     test_WriteConsoleOutputAttribute(hConOut);
2621     test_FillConsoleOutputCharacterA(hConOut);
2622     test_FillConsoleOutputCharacterW(hConOut);
2623     test_FillConsoleOutputAttribute(hConOut);
2624     test_ReadConsoleOutputCharacterA(hConOut);
2625     test_ReadConsoleOutputCharacterW(hConOut);
2626     test_ReadConsoleOutputAttribute(hConOut);
2627 }