Assorted spelling fixes.
[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     /* trying to write non-console handle */
784     SetLastError(0xdeadbeef);
785     ok(!WriteConsoleA(hFileOutRW, test_str1, lstrlenA(test_str1), &len, NULL),
786         "Shouldn't succeed\n");
787     ok(GetLastError() == ERROR_INVALID_HANDLE,
788        "GetLastError: expecting %u got %u\n",
789        ERROR_INVALID_HANDLE, GetLastError());
790
791     SetLastError(0xdeadbeef);
792     ok(!WriteConsoleA(hFileOutRO, test_str1, lstrlenA(test_str1), &len, NULL),
793         "Shouldn't succeed\n");
794     ok(GetLastError() == ERROR_INVALID_HANDLE,
795        "GetLastError: expecting %u got %u\n",
796        ERROR_INVALID_HANDLE, GetLastError());
797
798     SetLastError(0xdeadbeef);
799     ok(!WriteConsoleA(hFileOutWT, test_str1, lstrlenA(test_str1), &len, NULL),
800         "Shouldn't succeed\n");
801     todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
802        "GetLastError: expecting %u got %u\n",
803        ERROR_INVALID_HANDLE, GetLastError());
804
805     CloseHandle(hFileOutRW);
806     CloseHandle(hFileOutRO);
807     CloseHandle(hFileOutWT);
808
809     /* Trying to set SB handles with various access modes */
810     SetLastError(0);
811     ok(!SetConsoleActiveScreenBuffer(hConOutRO), "Shouldn't succeed\n");
812     ok(GetLastError() == ERROR_INVALID_HANDLE,
813        "GetLastError: expecting %u got %u\n",
814        ERROR_INVALID_HANDLE, GetLastError());
815
816     ok(SetConsoleActiveScreenBuffer(hConOutWT), "Couldn't set new WriteOnly SB\n");
817
818     ok(SetConsoleActiveScreenBuffer(hConOutRW), "Couldn't set new ReadWrite SB\n");
819
820     CloseHandle(hConOutWT);
821     CloseHandle(hConOutRO);
822
823     /* Now we have two ReadWrite SB, active must be hConOutRW */
824     /* Open current SB via CONOUT$ */
825     hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0,
826                              NULL, OPEN_EXISTING, 0, 0);
827     ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n");
828
829
830     /* test cursor */
831     c.X = c.Y = 10;
832     SetConsoleCursorPosition(hConOut, c);
833     c.X = c.Y = 5;
834     SetConsoleCursorPosition(hConOutRW, c);
835     okCURSOR(hConOutNew, c);
836     c.X = c.Y = 10;
837     okCURSOR(hConOut, c);
838
839
840     c.X = c.Y = 0;
841
842     /* Write using hConOutNew... */
843     SetConsoleCursorPosition(hConOutNew, c);
844     ret = WriteConsoleA(hConOutNew, test_str2, lstrlenA(test_str2), &len, NULL);
845     ok (ret && len == lstrlenA(test_str2), "WriteConsoleA failed\n");
846     /* ... and read it back via hConOutRW */
847     ret = ReadConsoleOutputCharacterA(hConOutRW, str_buf, lstrlenA(test_str2), c, &len);
848     ok(ret && len == lstrlenA(test_str2), "ReadConsoleOutputCharacterA failed\n");
849     str_buf[lstrlenA(test_str2)] = 0;
850     ok(!lstrcmpA(str_buf, test_str2), "got '%s' expected '%s'\n", str_buf, test_str2);
851
852
853     /* Now test output codepage handling. Current is 866 as we set earlier. */
854     SetConsoleCursorPosition(hConOutRW, c);
855     ret = WriteConsoleA(hConOutRW, test_cp866, lstrlenA(test_cp866), &len, NULL);
856     ok(ret && len == lstrlenA(test_cp866), "WriteConsoleA failed\n");
857     ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp866), c, &len);
858     ok(ret && len == lstrlenA(test_cp866), "ReadConsoleOutputCharacterW failed\n");
859     str_wbuf[lstrlenA(test_cp866)] = 0;
860     ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
861
862     /*
863      * cp866 is OK, let's switch to cp1251.
864      * We expect that this codepage will be used in every SB - active and not.
865      */
866     ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n");
867     SetConsoleCursorPosition(hConOutRW, c);
868     ret = WriteConsoleA(hConOutRW, test_cp1251, lstrlenA(test_cp1251), &len, NULL);
869     ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n");
870     ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp1251), c, &len);
871     ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n");
872     str_wbuf[lstrlenA(test_cp1251)] = 0;
873     ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
874
875     /* Check what has happened to hConOut. */
876     SetConsoleCursorPosition(hConOut, c);
877     ret = WriteConsoleA(hConOut, test_cp1251, lstrlenA(test_cp1251), &len, NULL);
878     ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n");
879     ret = ReadConsoleOutputCharacterW(hConOut, str_wbuf, lstrlenA(test_cp1251), c, &len);
880     ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n");
881     str_wbuf[lstrlenA(test_cp1251)] = 0;
882     ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
883
884     /* Close all handles of current console SB */
885     CloseHandle(hConOutNew);
886     CloseHandle(hConOutRW);
887
888     /* Now active SB should be hConOut */
889     hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0,
890                              NULL, OPEN_EXISTING, 0, 0);
891     ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n");
892
893     /* Write using hConOutNew... */
894     SetConsoleCursorPosition(hConOutNew, c);
895     ret = WriteConsoleA(hConOutNew, test_str1, lstrlenA(test_str1), &len, NULL);
896     ok (ret && len == lstrlenA(test_str1), "WriteConsoleA failed\n");
897     /* ... and read it back via hConOut */
898     ret = ReadConsoleOutputCharacterA(hConOut, str_buf, lstrlenA(test_str1), c, &len);
899     ok(ret && len == lstrlenA(test_str1), "ReadConsoleOutputCharacterA failed\n");
900     str_buf[lstrlenA(test_str1)] = 0;
901     todo_wine ok(!lstrcmpA(str_buf, test_str1), "got '%s' expected '%s'\n", str_buf, test_str1);
902     CloseHandle(hConOutNew);
903
904     /* This is not really needed under Windows */
905     SetConsoleActiveScreenBuffer(hConOut);
906
907     /* restore codepage */
908     SetConsoleOutputCP(oldcp);
909 }
910
911 static void test_GetSetConsoleInputExeName(void)
912 {
913     BOOL ret;
914     DWORD error;
915     char buffer[MAX_PATH], module[MAX_PATH], *p;
916     static char input_exe[MAX_PATH] = "winetest.exe";
917
918     SetLastError(0xdeadbeef);
919     ret = pGetConsoleInputExeNameA(0, NULL);
920     error = GetLastError();
921     ok(ret, "GetConsoleInputExeNameA failed\n");
922     ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
923
924     SetLastError(0xdeadbeef);
925     ret = pGetConsoleInputExeNameA(0, buffer);
926     error = GetLastError();
927     ok(ret, "GetConsoleInputExeNameA failed\n");
928     ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
929
930     GetModuleFileNameA(GetModuleHandle(NULL), module, sizeof(module));
931     p = strrchr(module, '\\') + 1;
932
933     ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
934     ok(ret, "GetConsoleInputExeNameA failed\n");
935     todo_wine ok(!lstrcmpA(buffer, p), "got %s expected %s\n", buffer, p);
936
937     SetLastError(0xdeadbeef);
938     ret = pSetConsoleInputExeNameA(NULL);
939     error = GetLastError();
940     ok(!ret, "SetConsoleInputExeNameA failed\n");
941     ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
942
943     SetLastError(0xdeadbeef);
944     ret = pSetConsoleInputExeNameA("");
945     error = GetLastError();
946     ok(!ret, "SetConsoleInputExeNameA failed\n");
947     ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
948
949     ret = pSetConsoleInputExeNameA(input_exe);
950     ok(ret, "SetConsoleInputExeNameA failed\n");
951
952     ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
953     ok(ret, "GetConsoleInputExeNameA failed\n");
954     ok(!lstrcmpA(buffer, input_exe), "got %s expected %s\n", buffer, input_exe);
955 }
956
957 static void test_GetConsoleProcessList(void)
958 {
959     DWORD ret, *list = NULL;
960
961     if (!pGetConsoleProcessList)
962     {
963         win_skip("GetConsoleProcessList is not available\n");
964         return;
965     }
966
967     SetLastError(0xdeadbeef);
968     ret = pGetConsoleProcessList(NULL, 0);
969     ok(ret == 0, "Expected failure\n");
970     ok(GetLastError() == ERROR_INVALID_PARAMETER,
971        "Expected ERROR_INVALID_PARAMETER, got %d\n",
972        GetLastError());
973
974     SetLastError(0xdeadbeef);
975     ret = pGetConsoleProcessList(NULL, 1);
976     ok(ret == 0, "Expected failure\n");
977     ok(GetLastError() == ERROR_INVALID_PARAMETER,
978        "Expected ERROR_INVALID_PARAMETER, got %d\n",
979        GetLastError());
980
981     /* We should only have 1 process but only for these specific unit tests as
982      * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would
983      * give us two processes for example.
984      */
985     list = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));
986
987     SetLastError(0xdeadbeef);
988     ret = pGetConsoleProcessList(list, 0);
989     ok(ret == 0, "Expected failure\n");
990     ok(GetLastError() == ERROR_INVALID_PARAMETER,
991        "Expected ERROR_INVALID_PARAMETER, got %d\n",
992        GetLastError());
993
994     SetLastError(0xdeadbeef);
995     ret = pGetConsoleProcessList(list, 1);
996     todo_wine
997     ok(ret == 1, "Expected 1, got %d\n", ret);
998
999     HeapFree(GetProcessHeap(), 0, list);
1000
1001     list = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(DWORD));
1002
1003     SetLastError(0xdeadbeef);
1004     ret = pGetConsoleProcessList(list, ret);
1005     todo_wine
1006     ok(ret == 1, "Expected 1, got %d\n", ret);
1007
1008     if (ret == 1)
1009     {
1010         DWORD pid = GetCurrentProcessId();
1011         ok(list[0] == pid, "Expected %d, got %d\n", pid, list[0]);
1012     }
1013
1014     HeapFree(GetProcessHeap(), 0, list);
1015 }
1016
1017 static void test_OpenCON(void)
1018 {
1019     static const WCHAR conW[] = {'C','O','N',0};
1020     static const DWORD accesses[] = {CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING,
1021                                      OPEN_ALWAYS, TRUNCATE_EXISTING};
1022     unsigned            i;
1023     HANDLE              h;
1024
1025     for (i = 0; i < sizeof(accesses) / sizeof(accesses[0]); i++)
1026     {
1027         h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1028         ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on write (%x)\n", accesses[i]);
1029         CloseHandle(h);
1030
1031         h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL);
1032         /* Windows versions differ here:
1033          * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1034          * NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING
1035          * So don't test when disposition is TRUNCATE_EXISTING
1036          */
1037         if (accesses[i] != TRUNCATE_EXISTING)
1038         {
1039             ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on read (%x)\n", accesses[i]);
1040         }
1041         CloseHandle(h);
1042         h = CreateFileW(conW, GENERIC_READ|GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1043         ok(h == INVALID_HANDLE_VALUE, "Expected not to open the CON device on read-write (%x)\n", accesses[i]);
1044         ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Unexpected error %x\n", GetLastError());
1045     }
1046 }
1047
1048 static void test_OpenConsoleW(void)
1049 {
1050     static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1051     static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1052     static const WCHAR emptyW[] = {0};
1053     static const WCHAR invalidW[] = {'I','N','V','A','L','I','D',0};
1054
1055     static const struct
1056     {
1057         LPCWSTR name;
1058         DWORD access;
1059         BOOL inherit;
1060         DWORD creation;
1061         DWORD gle;
1062     } invalid_table[] = {
1063         {NULL,     0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
1064         {NULL,     0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1065         {NULL,     0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1066         {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
1067         {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1068         {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
1069         {emptyW,   0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
1070         {emptyW,   0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1071         {emptyW,   0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1072         {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
1073         {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1074         {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
1075         {invalidW, 0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
1076         {invalidW, 0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1077         {invalidW, 0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1078         {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
1079         {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1080         {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
1081         {coninW,   0,                            FALSE,      0,                 ERROR_SHARING_VIOLATION},
1082         {coninW,   0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1083         {coninW,   0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1084         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_SHARING_VIOLATION},
1085         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        ERROR_SHARING_VIOLATION},
1086         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     ERROR_SHARING_VIOLATION},
1087         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1088         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
1089         {conoutW,  0,                            FALSE,      0,                 ERROR_SHARING_VIOLATION},
1090         {conoutW,  0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
1091         {conoutW,  0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1092         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_SHARING_VIOLATION},
1093         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        ERROR_SHARING_VIOLATION},
1094         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     ERROR_SHARING_VIOLATION},
1095         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
1096         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
1097     };
1098
1099     int index;
1100     HANDLE ret;
1101
1102     if (!pOpenConsoleW)
1103     {
1104         win_skip("OpenConsoleW is not available\n");
1105         return;
1106     }
1107
1108     for (index = 0; index < sizeof(invalid_table)/sizeof(invalid_table[0]); index++)
1109     {
1110         SetLastError(0xdeadbeef);
1111         ret = pOpenConsoleW(invalid_table[index].name, invalid_table[index].access,
1112                             invalid_table[index].inherit, invalid_table[index].creation);
1113         ok(ret == INVALID_HANDLE_VALUE,
1114            "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1115            index, ret);
1116         ok(GetLastError() == invalid_table[index].gle,
1117            "Expected GetLastError() to return %u for index %d, got %u\n",
1118            invalid_table[index].gle, index, GetLastError());
1119     }
1120
1121     /* OpenConsoleW should not touch the last error on success. */
1122     SetLastError(0xdeadbeef);
1123     ret = pOpenConsoleW(coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1124     ok(ret != INVALID_HANDLE_VALUE,
1125        "Expected OpenConsoleW to return a valid handle\n");
1126     ok(GetLastError() == 0xdeadbeef,
1127        "Expected the last error to be untouched, got %u\n", GetLastError());
1128     if (ret != INVALID_HANDLE_VALUE)
1129         CloseHandle(ret);
1130
1131     SetLastError(0xdeadbeef);
1132     ret = pOpenConsoleW(conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1133     ok(ret != INVALID_HANDLE_VALUE,
1134        "Expected OpenConsoleW to return a valid handle\n");
1135     ok(GetLastError() == 0xdeadbeef,
1136        "Expected the last error to be untouched, got %u\n", GetLastError());
1137     if (ret != INVALID_HANDLE_VALUE)
1138         CloseHandle(ret);
1139 }
1140
1141 static void test_CreateFileW(void)
1142 {
1143     static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1144     static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1145
1146     static const struct
1147     {
1148         LPCWSTR name;
1149         DWORD access;
1150         BOOL inherit;
1151         DWORD creation;
1152         DWORD gle;
1153         BOOL is_broken;
1154     } cf_table[] = {
1155         {coninW,   0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
1156         {coninW,   0,                            FALSE,      OPEN_ALWAYS,       0,                              FALSE},
1157         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
1158         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        0,                              FALSE},
1159         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     0,                              FALSE},
1160         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       0,                              FALSE},
1161         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, 0,                              FALSE},
1162         {conoutW,  0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
1163         {conoutW,  0,                            FALSE,      OPEN_ALWAYS,       0,                              FALSE},
1164         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
1165         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        0,                              FALSE},
1166         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     0,                              FALSE},
1167         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       0,                              FALSE},
1168         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, 0,                              FALSE},
1169     };
1170
1171     int index;
1172     HANDLE ret;
1173     SECURITY_ATTRIBUTES sa;
1174
1175     for (index = 0; index < sizeof(cf_table)/sizeof(cf_table[0]); index++)
1176     {
1177         SetLastError(0xdeadbeef);
1178
1179         sa.nLength = sizeof(sa);
1180         sa.lpSecurityDescriptor = NULL;
1181         sa.bInheritHandle = cf_table[index].inherit;
1182
1183         ret = CreateFileW(cf_table[index].name, cf_table[index].access,
1184                           FILE_SHARE_READ|FILE_SHARE_WRITE, &sa,
1185                           cf_table[index].creation, FILE_ATTRIBUTE_NORMAL, NULL);
1186         if (ret == INVALID_HANDLE_VALUE)
1187         {
1188             ok(cf_table[index].gle,
1189                "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index);
1190             ok(GetLastError() == cf_table[index].gle,
1191                 "Expected GetLastError() to return %u for index %d, got %u\n",
1192                 cf_table[index].gle, index, GetLastError());
1193         }
1194         else
1195         {
1196             ok(!cf_table[index].gle || broken(cf_table[index].is_broken) /* Win7 */,
1197                "Expected CreateFileW to succeed for index %d\n", index);
1198             CloseHandle(ret);
1199         }
1200     }
1201 }
1202
1203 static void test_VerifyConsoleIoHandle( HANDLE handle )
1204 {
1205     BOOL ret;
1206     DWORD error;
1207
1208     if (!pVerifyConsoleIoHandle)
1209     {
1210         win_skip("VerifyConsoleIoHandle is not available\n");
1211         return;
1212     }
1213
1214     /* invalid handle */
1215     SetLastError(0xdeadbeef);
1216     ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee0);
1217     error = GetLastError();
1218     ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1219     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1220
1221     /* invalid handle + 1 */
1222     SetLastError(0xdeadbeef);
1223     ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee1);
1224     error = GetLastError();
1225     ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1226     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1227
1228     /* invalid handle + 2 */
1229     SetLastError(0xdeadbeef);
1230     ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee2);
1231     error = GetLastError();
1232     ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1233     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1234
1235     /* invalid handle + 3 */
1236     SetLastError(0xdeadbeef);
1237     ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee3);
1238     error = GetLastError();
1239     ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1240     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1241
1242     /* valid handle */
1243     SetLastError(0xdeadbeef);
1244     ret = pVerifyConsoleIoHandle(handle);
1245     error = GetLastError();
1246     ok(ret, "expected VerifyConsoleIoHandle to succeed\n");
1247     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1248 }
1249
1250 static void test_GetSetStdHandle(void)
1251 {
1252     HANDLE handle;
1253     DWORD error;
1254     BOOL ret;
1255
1256     /* get invalid std handle */
1257     SetLastError(0xdeadbeef);
1258     handle = GetStdHandle(42);
1259     error = GetLastError();
1260     ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1261        "wrong GetLastError() %d\n", error);
1262     ok(handle == INVALID_HANDLE_VALUE, "expected INVALID_HANDLE_VALUE\n");
1263
1264     /* get valid */
1265     SetLastError(0xdeadbeef);
1266     handle = GetStdHandle(STD_INPUT_HANDLE);
1267     error = GetLastError();
1268     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1269
1270     /* set invalid std handle */
1271     SetLastError(0xdeadbeef);
1272     ret = SetStdHandle(42, handle);
1273     error = GetLastError();
1274     ok(!ret, "expected SetStdHandle to fail\n");
1275     ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1276        "wrong GetLastError() %d\n", error);
1277
1278     /* set valid (restore old value) */
1279     SetLastError(0xdeadbeef);
1280     ret = SetStdHandle(STD_INPUT_HANDLE, handle);
1281     error = GetLastError();
1282     ok(ret, "expected SetStdHandle to succeed\n");
1283     ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1284 }
1285
1286 static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle)
1287 {
1288     DWORD count;
1289     BOOL ret;
1290     int i;
1291
1292     const struct
1293     {
1294         HANDLE handle;
1295         LPDWORD nrofevents;
1296         DWORD last_error;
1297     } invalid_table[] =
1298     {
1299         {NULL,                 NULL,   ERROR_INVALID_HANDLE},
1300         {NULL,                 &count, ERROR_INVALID_HANDLE},
1301         {INVALID_HANDLE_VALUE, NULL,   ERROR_INVALID_HANDLE},
1302         {INVALID_HANDLE_VALUE, &count, ERROR_INVALID_HANDLE},
1303     };
1304
1305     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1306     {
1307         SetLastError(0xdeadbeef);
1308         if (invalid_table[i].nrofevents) count = 0xdeadbeef;
1309         ret = GetNumberOfConsoleInputEvents(invalid_table[i].handle,
1310                                             invalid_table[i].nrofevents);
1311         ok(!ret, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i, ret);
1312         if (invalid_table[i].nrofevents)
1313         {
1314             ok(count == 0xdeadbeef,
1315                "[%d] Expected output count to be unmodified, got %u\n", i, count);
1316         }
1317         ok(GetLastError() == invalid_table[i].last_error,
1318            "[%d] Expected last error to be %u, got %u\n",
1319            i, invalid_table[i].last_error, GetLastError());
1320     }
1321
1322     /* Test crashes on Windows 7. */
1323     if (0)
1324     {
1325         SetLastError(0xdeadbeef);
1326         ret = GetNumberOfConsoleInputEvents(input_handle, NULL);
1327         ok(!ret, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret);
1328         ok(GetLastError() == ERROR_INVALID_ACCESS,
1329            "Expected last error to be ERROR_INVALID_ACCESS, got %u\n",
1330            GetLastError());
1331     }
1332
1333     count = 0xdeadbeef;
1334     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1335     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1336     ok(count != 0xdeadbeef, "Expected output count to initialized\n");
1337 }
1338
1339 static void test_WriteConsoleInputA(HANDLE input_handle)
1340 {
1341     INPUT_RECORD event;
1342     INPUT_RECORD event_list[5];
1343     MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1344     KEY_EVENT_RECORD key_event;
1345     DWORD count, console_mode;
1346     BOOL ret;
1347     int i;
1348
1349     const struct
1350     {
1351         HANDLE handle;
1352         const INPUT_RECORD *buffer;
1353         DWORD count;
1354         LPDWORD written;
1355         DWORD expected_count;
1356         DWORD last_error;
1357         int win7_crash;
1358     } invalid_table[] =
1359     {
1360         {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1361         {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1362         {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1363         {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1364         {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1365         {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1366         {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1367         {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1368         {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1369         {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1370         {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1371         {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1372         {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1373         {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1374         {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1375         {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1376         {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1377         {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1378         {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1379         {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1380         {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1381     };
1382
1383     /* Suppress external sources of input events for the duration of the test. */
1384     ret = GetConsoleMode(input_handle, &console_mode);
1385     ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1386     if (!ret)
1387     {
1388         skip("GetConsoleMode failed with last error %u\n", GetLastError());
1389         return;
1390     }
1391
1392     ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1393     ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1394     if (!ret)
1395     {
1396         skip("SetConsoleMode failed with last error %u\n", GetLastError());
1397         return;
1398     }
1399
1400     /* Discard any events queued before the tests. */
1401     ret = FlushConsoleInputBuffer(input_handle);
1402     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1403
1404     event.EventType = MOUSE_EVENT;
1405     event.Event.MouseEvent = mouse_event;
1406
1407     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1408     {
1409         if (invalid_table[i].win7_crash)
1410             continue;
1411
1412         SetLastError(0xdeadbeef);
1413         if (invalid_table[i].written) count = 0xdeadbeef;
1414         ret = WriteConsoleInputA(invalid_table[i].handle,
1415                                  invalid_table[i].buffer,
1416                                  invalid_table[i].count,
1417                                  invalid_table[i].written);
1418         ok(!ret, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i, ret);
1419         if (invalid_table[i].written)
1420         {
1421             ok(count == invalid_table[i].expected_count,
1422                "[%d] Expected output count to be %u, got %u\n",
1423                i, invalid_table[i].expected_count, count);
1424         }
1425         ok(GetLastError() == invalid_table[i].last_error,
1426            "[%d] Expected last error to be %u, got %u\n",
1427            i, invalid_table[i].last_error, GetLastError());
1428     }
1429
1430     count = 0xdeadbeef;
1431     ret = WriteConsoleInputA(input_handle, NULL, 0, &count);
1432     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1433     ok(count == 0, "Expected count to be 0, got %u\n", count);
1434
1435     count = 0xdeadbeef;
1436     ret = WriteConsoleInputA(input_handle, &event, 0, &count);
1437     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1438     ok(count == 0, "Expected count to be 0, got %u\n", count);
1439
1440     count = 0xdeadbeef;
1441     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1442     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1443     ok(count == 1, "Expected count to be 1, got %u\n", count);
1444
1445     ret = FlushConsoleInputBuffer(input_handle);
1446     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1447
1448     /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1449     event.EventType = MOUSE_EVENT;
1450     event.Event.MouseEvent = mouse_event;
1451
1452     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1453     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1454     ok(count == 1, "Expected count to be 1, got %u\n", count);
1455
1456     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1457     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1458     ok(count == 1, "Expected count to be 1, got %u\n", count);
1459
1460     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1461     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1462     ok(count == 1, "Expected count to be 1, got %u\n", count);
1463
1464     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1465     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1466     todo_wine
1467     ok(count == 1, "Expected count to be 1, got %u\n", count);
1468
1469     ret = FlushConsoleInputBuffer(input_handle);
1470     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1471
1472     for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1473     {
1474         event_list[i].EventType = MOUSE_EVENT;
1475         event_list[i].Event.MouseEvent = mouse_event;
1476     }
1477
1478     /* Writing consecutive chunks of mouse events appears to work. */
1479     ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1480     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1481     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1482        "Expected count to be event list length, got %u\n", count);
1483
1484     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1485     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1486     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1487        "Expected count to be event list length, got %u\n", count);
1488
1489     ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1490     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1491     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1492        "Expected count to be event list length, got %u\n", count);
1493
1494     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1495     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1496     ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1497        "Expected count to be twice event list length, got %u\n", count);
1498
1499     /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1500     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1501     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1502     ok(count == 1, "Expected count to be 1, got %u\n", count);
1503
1504     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1505     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1506     todo_wine
1507     ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1508        "Expected count to be twice event list length, got %u\n", count);
1509
1510     ret = FlushConsoleInputBuffer(input_handle);
1511     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1512
1513     key_event.bKeyDown = FALSE;
1514     key_event.wRepeatCount = 0;
1515     key_event.wVirtualKeyCode = VK_SPACE;
1516     key_event.wVirtualScanCode = VK_SPACE;
1517     key_event.uChar.AsciiChar = ' ';
1518     key_event.dwControlKeyState = 0;
1519
1520     event.EventType = KEY_EVENT;
1521     event.Event.KeyEvent = key_event;
1522
1523     /* Key events don't exhibit the same behavior as mouse events. */
1524     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1525     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1526     ok(count == 1, "Expected count to be 1, got %u\n", count);
1527
1528     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1529     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1530     ok(count == 1, "Expected count to be 1, got %u\n", count);
1531
1532     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1533     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1534     ok(count == 1, "Expected count to be 1, got %u\n", count);
1535
1536     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1537     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1538     ok(count == 2, "Expected count to be 2, got %u\n", count);
1539
1540     ret = FlushConsoleInputBuffer(input_handle);
1541     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1542
1543     /* Try interleaving mouse and key events. */
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 == 1, "Expected count to be 1, got %u\n", count);
1554
1555     event.EventType = KEY_EVENT;
1556     event.Event.KeyEvent = key_event;
1557
1558     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1559     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1560     ok(count == 1, "Expected count to be 1, got %u\n", count);
1561
1562     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1563     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1564     ok(count == 2, "Expected count to be 2, got %u\n", count);
1565
1566     event.EventType = MOUSE_EVENT;
1567     event.Event.MouseEvent = mouse_event;
1568
1569     ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1570     ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1571     ok(count == 1, "Expected count to be 1, got %u\n", count);
1572
1573     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1574     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1575     ok(count == 3, "Expected count to be 3, got %u\n", count);
1576
1577     /* Restore the old console mode. */
1578     ret = SetConsoleMode(input_handle, console_mode);
1579     ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1580 }
1581
1582 static void test_WriteConsoleInputW(HANDLE input_handle)
1583 {
1584     INPUT_RECORD event;
1585     INPUT_RECORD event_list[5];
1586     MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1587     KEY_EVENT_RECORD key_event;
1588     DWORD count, console_mode;
1589     BOOL ret;
1590     int i;
1591
1592     const struct
1593     {
1594         HANDLE handle;
1595         const INPUT_RECORD *buffer;
1596         DWORD count;
1597         LPDWORD written;
1598         DWORD expected_count;
1599         DWORD last_error;
1600         int win7_crash;
1601     } invalid_table[] =
1602     {
1603         {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1604         {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1605         {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1606         {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1607         {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1608         {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1609         {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1610         {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1611         {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1612         {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1613         {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1614         {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1615         {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1616         {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1617         {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1618         {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1619         {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1620         {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS},
1621         {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
1622         {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1623         {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1624     };
1625
1626     /* Suppress external sources of input events for the duration of the test. */
1627     ret = GetConsoleMode(input_handle, &console_mode);
1628     ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1629     if (!ret)
1630     {
1631         skip("GetConsoleMode failed with last error %u\n", GetLastError());
1632         return;
1633     }
1634
1635     ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1636     ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1637     if (!ret)
1638     {
1639         skip("SetConsoleMode failed with last error %u\n", GetLastError());
1640         return;
1641     }
1642
1643     /* Discard any events queued before the tests. */
1644     ret = FlushConsoleInputBuffer(input_handle);
1645     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1646
1647     event.EventType = MOUSE_EVENT;
1648     event.Event.MouseEvent = mouse_event;
1649
1650     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1651     {
1652         if (invalid_table[i].win7_crash)
1653             continue;
1654
1655         SetLastError(0xdeadbeef);
1656         if (invalid_table[i].written) count = 0xdeadbeef;
1657         ret = WriteConsoleInputW(invalid_table[i].handle,
1658                                  invalid_table[i].buffer,
1659                                  invalid_table[i].count,
1660                                  invalid_table[i].written);
1661         ok(!ret, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i, ret);
1662         if (invalid_table[i].written)
1663         {
1664             ok(count == invalid_table[i].expected_count,
1665                "[%d] Expected output count to be %u, got %u\n",
1666                i, invalid_table[i].expected_count, count);
1667         }
1668         ok(GetLastError() == invalid_table[i].last_error,
1669            "[%d] Expected last error to be %u, got %u\n",
1670            i, invalid_table[i].last_error, GetLastError());
1671     }
1672
1673     count = 0xdeadbeef;
1674     ret = WriteConsoleInputW(input_handle, NULL, 0, &count);
1675     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1676     ok(count == 0, "Expected count to be 0, got %u\n", count);
1677
1678     count = 0xdeadbeef;
1679     ret = WriteConsoleInputW(input_handle, &event, 0, &count);
1680     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1681     ok(count == 0, "Expected count to be 0, got %u\n", count);
1682
1683     count = 0xdeadbeef;
1684     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1685     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1686     ok(count == 1, "Expected count to be 1, got %u\n", count);
1687
1688     ret = FlushConsoleInputBuffer(input_handle);
1689     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1690
1691     /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1692     event.EventType = MOUSE_EVENT;
1693     event.Event.MouseEvent = mouse_event;
1694
1695     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1696     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1697     ok(count == 1, "Expected count to be 1, got %u\n", count);
1698
1699     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1700     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1701     ok(count == 1, "Expected count to be 1, got %u\n", count);
1702
1703     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1704     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1705     ok(count == 1, "Expected count to be 1, got %u\n", count);
1706
1707     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1708     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1709     todo_wine
1710     ok(count == 1, "Expected count to be 1, got %u\n", count);
1711
1712     ret = FlushConsoleInputBuffer(input_handle);
1713     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1714
1715     for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1716     {
1717         event_list[i].EventType = MOUSE_EVENT;
1718         event_list[i].Event.MouseEvent = mouse_event;
1719     }
1720
1721     /* Writing consecutive chunks of mouse events appears to work. */
1722     ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1723     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1724     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1725        "Expected count to be event list length, got %u\n", count);
1726
1727     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1728     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1729     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1730        "Expected count to be event list length, got %u\n", count);
1731
1732     ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1733     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1734     ok(count == sizeof(event_list)/sizeof(event_list[0]),
1735        "Expected count to be event list length, got %u\n", count);
1736
1737     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1738     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1739     ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1740        "Expected count to be twice event list length, got %u\n", count);
1741
1742     /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1743     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1744     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1745     ok(count == 1, "Expected count to be 1, got %u\n", count);
1746
1747     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1748     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1749     todo_wine
1750     ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1751        "Expected count to be twice event list length, got %u\n", count);
1752
1753     ret = FlushConsoleInputBuffer(input_handle);
1754     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1755
1756     key_event.bKeyDown = FALSE;
1757     key_event.wRepeatCount = 0;
1758     key_event.wVirtualKeyCode = VK_SPACE;
1759     key_event.wVirtualScanCode = VK_SPACE;
1760     key_event.uChar.UnicodeChar = ' ';
1761     key_event.dwControlKeyState = 0;
1762
1763     event.EventType = KEY_EVENT;
1764     event.Event.KeyEvent = key_event;
1765
1766     /* Key events don't exhibit the same behavior as mouse events. */
1767     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1768     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1769     ok(count == 1, "Expected count to be 1, got %u\n", count);
1770
1771     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1772     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1773     ok(count == 1, "Expected count to be 1, got %u\n", count);
1774
1775     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1776     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1777     ok(count == 1, "Expected count to be 1, got %u\n", count);
1778
1779     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1780     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1781     ok(count == 2, "Expected count to be 2, got %u\n", count);
1782
1783     ret = FlushConsoleInputBuffer(input_handle);
1784     ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1785
1786     /* Try interleaving mouse and key events. */
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 == 1, "Expected count to be 1, got %u\n", count);
1797
1798     event.EventType = KEY_EVENT;
1799     event.Event.KeyEvent = key_event;
1800
1801     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1802     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1803     ok(count == 1, "Expected count to be 1, got %u\n", count);
1804
1805     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1806     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1807     ok(count == 2, "Expected count to be 2, got %u\n", count);
1808
1809     event.EventType = MOUSE_EVENT;
1810     event.Event.MouseEvent = mouse_event;
1811
1812     ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1813     ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1814     ok(count == 1, "Expected count to be 1, got %u\n", count);
1815
1816     ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1817     ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1818     ok(count == 3, "Expected count to be 3, got %u\n", count);
1819
1820     /* Restore the old console mode. */
1821     ret = SetConsoleMode(input_handle, console_mode);
1822     ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1823 }
1824
1825 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle)
1826 {
1827     static const char output[] = {'a', 0};
1828
1829     COORD origin = {0, 0};
1830     DWORD count;
1831     BOOL ret;
1832     int i;
1833
1834     const struct
1835     {
1836         HANDLE hConsoleOutput;
1837         LPCSTR str;
1838         DWORD length;
1839         COORD coord;
1840         LPDWORD lpNumCharsWritten;
1841         DWORD expected_count;
1842         DWORD last_error;
1843         int win7_crash;
1844     } invalid_table[] =
1845     {
1846         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1847         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1848         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1849         {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1850         {NULL, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1851         {NULL, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1852         {NULL, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1853         {NULL, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1854         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1855         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1856         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1857         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1858         {INVALID_HANDLE_VALUE, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1859         {INVALID_HANDLE_VALUE, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1860         {INVALID_HANDLE_VALUE, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1861         {INVALID_HANDLE_VALUE, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1862         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1863         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1864         {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1865         {output_handle, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1866         {output_handle, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1867     };
1868
1869     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1870     {
1871         if (invalid_table[i].win7_crash)
1872             continue;
1873
1874         SetLastError(0xdeadbeef);
1875         if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1876         ret = WriteConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
1877                                            invalid_table[i].str,
1878                                            invalid_table[i].length,
1879                                            invalid_table[i].coord,
1880                                            invalid_table[i].lpNumCharsWritten);
1881         ok(!ret, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
1882         if (invalid_table[i].lpNumCharsWritten)
1883         {
1884             ok(count == invalid_table[i].expected_count,
1885                "[%d] Expected count to be %u, got %u\n",
1886                i, invalid_table[i].expected_count, count);
1887         }
1888         ok(GetLastError() == invalid_table[i].last_error,
1889            "[%d] Expected last error to be %u, got %u\n",
1890            i, invalid_table[i].last_error, GetLastError());
1891     }
1892
1893     count = 0xdeadbeef;
1894     ret = WriteConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
1895     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1896     ok(count == 0, "Expected count to be 0, got %u\n", count);
1897
1898     count = 0xdeadbeef;
1899     ret = WriteConsoleOutputCharacterA(output_handle, output, 0, origin, &count);
1900     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1901     ok(count == 0, "Expected count to be 0, got %u\n", count);
1902
1903     count = 0xdeadbeef;
1904     ret = WriteConsoleOutputCharacterA(output_handle, output, 1, origin, &count);
1905     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1906     ok(count == 1, "Expected count to be 1, got %u\n", count);
1907 }
1908
1909 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle)
1910 {
1911     static const WCHAR outputW[] = {'a',0};
1912
1913     COORD origin = {0, 0};
1914     DWORD count;
1915     BOOL ret;
1916     int i;
1917
1918     const struct
1919     {
1920         HANDLE hConsoleOutput;
1921         LPCWSTR str;
1922         DWORD length;
1923         COORD coord;
1924         LPDWORD lpNumCharsWritten;
1925         DWORD expected_count;
1926         DWORD last_error;
1927         int win7_crash;
1928     } invalid_table[] =
1929     {
1930         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1931         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1932         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1933         {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1934         {NULL, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1935         {NULL, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1936         {NULL, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1937         {NULL, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1938         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1939         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1940         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1941         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1942         {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1943         {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1944         {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1945         {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1946         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1947         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1948         {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1949         {output_handle, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1950         {output_handle, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1951     };
1952
1953     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1954     {
1955         if (invalid_table[i].win7_crash)
1956             continue;
1957
1958         SetLastError(0xdeadbeef);
1959         if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1960         ret = WriteConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
1961                                            invalid_table[i].str,
1962                                            invalid_table[i].length,
1963                                            invalid_table[i].coord,
1964                                            invalid_table[i].lpNumCharsWritten);
1965         ok(!ret, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
1966         if (invalid_table[i].lpNumCharsWritten)
1967         {
1968             ok(count == invalid_table[i].expected_count,
1969                "[%d] Expected count to be %u, got %u\n",
1970                i, invalid_table[i].expected_count, count);
1971         }
1972         ok(GetLastError() == invalid_table[i].last_error,
1973            "[%d] Expected last error to be %u, got %u\n",
1974            i, invalid_table[i].last_error, GetLastError());
1975     }
1976
1977     count = 0xdeadbeef;
1978     ret = WriteConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
1979     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1980     ok(count == 0, "Expected count to be 0, got %u\n", count);
1981
1982     count = 0xdeadbeef;
1983     ret = WriteConsoleOutputCharacterW(output_handle, outputW, 0, origin, &count);
1984     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1985     ok(count == 0, "Expected count to be 0, got %u\n", count);
1986
1987     count = 0xdeadbeef;
1988     ret = WriteConsoleOutputCharacterW(output_handle, outputW, 1, origin, &count);
1989     ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
1990     ok(count == 1, "Expected count to be 1, got %u\n", count);
1991 }
1992
1993 static void test_WriteConsoleOutputAttribute(HANDLE output_handle)
1994 {
1995     WORD attr = FOREGROUND_BLUE;
1996     COORD origin = {0, 0};
1997     DWORD count;
1998     BOOL ret;
1999     int i;
2000
2001     const struct
2002     {
2003         HANDLE hConsoleOutput;
2004         CONST WORD *attr;
2005         DWORD length;
2006         COORD coord;
2007         LPDWORD lpNumAttrsWritten;
2008         DWORD expected_count;
2009         DWORD last_error;
2010         int win7_crash;
2011     } invalid_table[] =
2012     {
2013         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2014         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2015         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2016         {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2017         {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2018         {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2019         {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2020         {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2021         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2022         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2023         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2024         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2025         {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2026         {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2027         {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2028         {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2029         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2030         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2031         {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2032         {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2033         {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2034     };
2035
2036     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2037     {
2038         if (invalid_table[i].win7_crash)
2039             continue;
2040
2041         SetLastError(0xdeadbeef);
2042         if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2043         ret = WriteConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2044                                           invalid_table[i].attr,
2045                                           invalid_table[i].length,
2046                                           invalid_table[i].coord,
2047                                           invalid_table[i].lpNumAttrsWritten);
2048         ok(!ret, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2049         if (invalid_table[i].lpNumAttrsWritten)
2050         {
2051             ok(count == invalid_table[i].expected_count,
2052                "[%d] Expected count to be %u, got %u\n",
2053                i, invalid_table[i].expected_count, count);
2054         }
2055         ok(GetLastError() == invalid_table[i].last_error,
2056            "[%d] Expected last error to be %u, got %u\n",
2057            i, invalid_table[i].last_error, GetLastError());
2058     }
2059
2060     count = 0xdeadbeef;
2061     ret = WriteConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2062     ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2063     ok(count == 0, "Expected count to be 0, got %u\n", count);
2064
2065     count = 0xdeadbeef;
2066     ret = WriteConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2067     ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2068     ok(count == 0, "Expected count to be 0, got %u\n", count);
2069
2070     count = 0xdeadbeef;
2071     ret = WriteConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2072     ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2073     ok(count == 1, "Expected count to be 1, got %u\n", count);
2074 }
2075
2076 static void test_FillConsoleOutputCharacterA(HANDLE output_handle)
2077 {
2078     COORD origin = {0, 0};
2079     DWORD count;
2080     BOOL ret;
2081     int i;
2082
2083     const struct
2084     {
2085         HANDLE hConsoleOutput;
2086         CHAR ch;
2087         DWORD length;
2088         COORD coord;
2089         LPDWORD lpNumCharsWritten;
2090         DWORD expected_count;
2091         DWORD last_error;
2092         int win7_crash;
2093     } invalid_table[] =
2094     {
2095         {NULL, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2096         {NULL, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2097         {NULL, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2098         {NULL, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2099         {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2100         {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2101         {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2102         {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2103         {output_handle, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2104         {output_handle, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2105     };
2106
2107     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2108     {
2109         if (invalid_table[i].win7_crash)
2110             continue;
2111
2112         SetLastError(0xdeadbeef);
2113         if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2114         ret = FillConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2115                                           invalid_table[i].ch,
2116                                           invalid_table[i].length,
2117                                           invalid_table[i].coord,
2118                                           invalid_table[i].lpNumCharsWritten);
2119         ok(!ret, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2120         if (invalid_table[i].lpNumCharsWritten)
2121         {
2122             ok(count == invalid_table[i].expected_count,
2123                "[%d] Expected count to be %u, got %u\n",
2124                i, invalid_table[i].expected_count, count);
2125         }
2126         ok(GetLastError() == invalid_table[i].last_error,
2127            "[%d] Expected last error to be %u, got %u\n",
2128            i, invalid_table[i].last_error, GetLastError());
2129     }
2130
2131     count = 0xdeadbeef;
2132     ret = FillConsoleOutputCharacterA(output_handle, 'a', 0, origin, &count);
2133     ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2134     ok(count == 0, "Expected count to be 0, got %u\n", count);
2135
2136     count = 0xdeadbeef;
2137     ret = FillConsoleOutputCharacterA(output_handle, 'a', 1, origin, &count);
2138     ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2139     ok(count == 1, "Expected count to be 1, got %u\n", count);
2140 }
2141
2142 static void test_FillConsoleOutputCharacterW(HANDLE output_handle)
2143 {
2144     COORD origin = {0, 0};
2145     DWORD count;
2146     BOOL ret;
2147     int i;
2148
2149     const struct
2150     {
2151         HANDLE hConsoleOutput;
2152         WCHAR ch;
2153         DWORD length;
2154         COORD coord;
2155         LPDWORD lpNumCharsWritten;
2156         DWORD expected_count;
2157         DWORD last_error;
2158         int win7_crash;
2159     } invalid_table[] =
2160     {
2161         {NULL, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2162         {NULL, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2163         {NULL, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2164         {NULL, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2165         {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2166         {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2167         {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2168         {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2169         {output_handle, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2170         {output_handle, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2171     };
2172
2173     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2174     {
2175         if (invalid_table[i].win7_crash)
2176             continue;
2177
2178         SetLastError(0xdeadbeef);
2179         if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2180         ret = FillConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2181                                           invalid_table[i].ch,
2182                                           invalid_table[i].length,
2183                                           invalid_table[i].coord,
2184                                           invalid_table[i].lpNumCharsWritten);
2185         ok(!ret, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2186         if (invalid_table[i].lpNumCharsWritten)
2187         {
2188             ok(count == invalid_table[i].expected_count,
2189                "[%d] Expected count to be %u, got %u\n",
2190                i, invalid_table[i].expected_count, count);
2191         }
2192         ok(GetLastError() == invalid_table[i].last_error,
2193            "[%d] Expected last error to be %u, got %u\n",
2194            i, invalid_table[i].last_error, GetLastError());
2195     }
2196
2197     count = 0xdeadbeef;
2198     ret = FillConsoleOutputCharacterW(output_handle, 'a', 0, origin, &count);
2199     ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2200     ok(count == 0, "Expected count to be 0, got %u\n", count);
2201
2202     count = 0xdeadbeef;
2203     ret = FillConsoleOutputCharacterW(output_handle, 'a', 1, origin, &count);
2204     ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2205     ok(count == 1, "Expected count to be 1, got %u\n", count);
2206 }
2207
2208 static void test_FillConsoleOutputAttribute(HANDLE output_handle)
2209 {
2210     COORD origin = {0, 0};
2211     DWORD count;
2212     BOOL ret;
2213     int i;
2214
2215     const struct
2216     {
2217         HANDLE hConsoleOutput;
2218         WORD attr;
2219         DWORD length;
2220         COORD coord;
2221         LPDWORD lpNumAttrsWritten;
2222         DWORD expected_count;
2223         DWORD last_error;
2224         int win7_crash;
2225     } invalid_table[] =
2226     {
2227         {NULL, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2228         {NULL, FOREGROUND_BLUE, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2229         {NULL, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2230         {NULL, FOREGROUND_BLUE, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2231         {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2232         {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2233         {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2234         {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2235         {output_handle, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2236         {output_handle, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2237     };
2238
2239     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2240     {
2241         if (invalid_table[i].win7_crash)
2242             continue;
2243
2244         SetLastError(0xdeadbeef);
2245         if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2246         ret = FillConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2247                                          invalid_table[i].attr,
2248                                          invalid_table[i].length,
2249                                          invalid_table[i].coord,
2250                                          invalid_table[i].lpNumAttrsWritten);
2251         ok(!ret, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2252         if (invalid_table[i].lpNumAttrsWritten)
2253         {
2254             ok(count == invalid_table[i].expected_count,
2255                "[%d] Expected count to be %u, got %u\n",
2256                i, invalid_table[i].expected_count, count);
2257         }
2258         ok(GetLastError() == invalid_table[i].last_error,
2259            "[%d] Expected last error to be %u, got %u\n",
2260            i, invalid_table[i].last_error, GetLastError());
2261     }
2262
2263     count = 0xdeadbeef;
2264     ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 0, origin, &count);
2265     ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2266     ok(count == 0, "Expected count to be 0, got %u\n", count);
2267
2268     count = 0xdeadbeef;
2269     ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 1, origin, &count);
2270     ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2271     ok(count == 1, "Expected count to be 1, got %u\n", count);
2272
2273     count = 0xdeadbeef;
2274     ret = FillConsoleOutputAttribute(output_handle, ~0, 1, origin, &count);
2275     ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2276     ok(count == 1, "Expected count to be 1, got %u\n", count);
2277 }
2278
2279 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle)
2280 {
2281     CHAR read;
2282     COORD origin = {0, 0};
2283     DWORD count;
2284     BOOL ret;
2285     int i;
2286
2287     const struct
2288     {
2289         HANDLE hConsoleOutput;
2290         LPSTR lpstr;
2291         DWORD length;
2292         COORD coord;
2293         LPDWORD read_count;
2294         DWORD expected_count;
2295         DWORD last_error;
2296         int win7_crash;
2297     } invalid_table[] =
2298     {
2299         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2300         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2301         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2302         {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2303         {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2304         {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2305         {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2306         {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2307         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2308         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2309         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2310         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2311         {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2312         {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2313         {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2314         {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2315         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2316         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2317         {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2318         {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1},
2319         {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2320         {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2321     };
2322
2323     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2324     {
2325         if (invalid_table[i].win7_crash)
2326             continue;
2327
2328         SetLastError(0xdeadbeef);
2329         if (invalid_table[i].read_count) count = 0xdeadbeef;
2330         ret = ReadConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2331                                           invalid_table[i].lpstr,
2332                                           invalid_table[i].length,
2333                                           invalid_table[i].coord,
2334                                           invalid_table[i].read_count);
2335         ok(!ret, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2336         if (invalid_table[i].read_count)
2337         {
2338             ok(count == invalid_table[i].expected_count,
2339                "[%d] Expected count to be %u, got %u\n",
2340                i, invalid_table[i].expected_count, count);
2341         }
2342         ok(GetLastError() == invalid_table[i].last_error,
2343            "[%d] Expected last error to be %u, got %u\n",
2344            i, invalid_table[i].last_error, GetLastError());
2345     }
2346
2347     count = 0xdeadbeef;
2348     ret = ReadConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
2349     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2350     ok(count == 0, "Expected count to be 0, got %u\n", count);
2351
2352     count = 0xdeadbeef;
2353     ret = ReadConsoleOutputCharacterA(output_handle, &read, 0, origin, &count);
2354     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2355     ok(count == 0, "Expected count to be 0, got %u\n", count);
2356
2357     count = 0xdeadbeef;
2358     ret = ReadConsoleOutputCharacterA(output_handle, &read, 1, origin, &count);
2359     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2360     ok(count == 1, "Expected count to be 1, got %u\n", count);
2361 }
2362
2363 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle)
2364 {
2365     WCHAR read;
2366     COORD origin = {0, 0};
2367     DWORD count;
2368     BOOL ret;
2369     int i;
2370
2371     const struct
2372     {
2373         HANDLE hConsoleOutput;
2374         LPWSTR buffer;
2375         DWORD length;
2376         COORD coord;
2377         LPDWORD read_count;
2378         DWORD expected_count;
2379         DWORD last_error;
2380         int win7_crash;
2381     } invalid_table[] =
2382     {
2383         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2384         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2385         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2386         {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2387         {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2388         {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2389         {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2390         {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2391         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2392         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2393         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2394         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2395         {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2396         {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2397         {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2398         {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2399         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2400         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2401         {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2402         {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1},
2403         {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2404         {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2405     };
2406
2407     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2408     {
2409         if (invalid_table[i].win7_crash)
2410             continue;
2411
2412         SetLastError(0xdeadbeef);
2413         if (invalid_table[i].read_count) count = 0xdeadbeef;
2414         ret = ReadConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2415                                           invalid_table[i].buffer,
2416                                           invalid_table[i].length,
2417                                           invalid_table[i].coord,
2418                                           invalid_table[i].read_count);
2419         ok(!ret, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2420         if (invalid_table[i].read_count)
2421         {
2422             ok(count == invalid_table[i].expected_count,
2423                "[%d] Expected count to be %u, got %u\n",
2424                i, invalid_table[i].expected_count, count);
2425         }
2426         ok(GetLastError() == invalid_table[i].last_error,
2427            "[%d] Expected last error to be %u, got %u\n",
2428            i, invalid_table[i].last_error, GetLastError());
2429     }
2430
2431     count = 0xdeadbeef;
2432     ret = ReadConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
2433     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2434     ok(count == 0, "Expected count to be 0, got %u\n", count);
2435
2436     count = 0xdeadbeef;
2437     ret = ReadConsoleOutputCharacterW(output_handle, &read, 0, origin, &count);
2438     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2439     ok(count == 0, "Expected count to be 0, got %u\n", count);
2440
2441     count = 0xdeadbeef;
2442     ret = ReadConsoleOutputCharacterW(output_handle, &read, 1, origin, &count);
2443     ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2444     ok(count == 1, "Expected count to be 1, got %u\n", count);
2445 }
2446
2447 static void test_ReadConsoleOutputAttribute(HANDLE output_handle)
2448 {
2449     WORD attr;
2450     COORD origin = {0, 0};
2451     DWORD count;
2452     BOOL ret;
2453     int i;
2454
2455     const struct
2456     {
2457         HANDLE hConsoleOutput;
2458         LPWORD lpAttribute;
2459         DWORD length;
2460         COORD coord;
2461         LPDWORD read_count;
2462         DWORD expected_count;
2463         DWORD last_error;
2464         int win7_crash;
2465     } invalid_table[] =
2466     {
2467         {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2468         {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2469         {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2470         {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2471         {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2472         {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2473         {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2474         {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2475         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2476         {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2477         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2478         {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2479         {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2480         {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2481         {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2482         {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2483         {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2484         {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2485         {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2486         {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2487         {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2488     };
2489
2490     for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2491     {
2492         if (invalid_table[i].win7_crash)
2493             continue;
2494
2495         SetLastError(0xdeadbeef);
2496         if (invalid_table[i].read_count) count = 0xdeadbeef;
2497         ret = ReadConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2498                                          invalid_table[i].lpAttribute,
2499                                          invalid_table[i].length,
2500                                          invalid_table[i].coord,
2501                                          invalid_table[i].read_count);
2502         ok(!ret, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2503         if (invalid_table[i].read_count)
2504         {
2505             ok(count == invalid_table[i].expected_count,
2506                "[%d] Expected count to be %u, got %u\n",
2507                i, invalid_table[i].expected_count, count);
2508         }
2509         ok(GetLastError() == invalid_table[i].last_error,
2510            "[%d] Expected last error to be %u, got %u\n",
2511            i, invalid_table[i].last_error, GetLastError());
2512     }
2513
2514     count = 0xdeadbeef;
2515     ret = ReadConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2516     ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2517     ok(count == 0, "Expected count to be 0, got %u\n", count);
2518
2519     count = 0xdeadbeef;
2520     ret = ReadConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2521     ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2522     ok(count == 0, "Expected count to be 0, got %u\n", count);
2523
2524     count = 0xdeadbeef;
2525     ret = ReadConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2526     ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2527     ok(count == 1, "Expected count to be 1, got %u\n", count);
2528 }
2529
2530 START_TEST(console)
2531 {
2532     static const char font_name[] = "Lucida Console";
2533     HANDLE hConIn, hConOut;
2534     BOOL ret;
2535     CONSOLE_SCREEN_BUFFER_INFO  sbi;
2536     LONG err;
2537     HKEY console_key;
2538     char old_font[LF_FACESIZE];
2539     BOOL delete = FALSE;
2540     DWORD size;
2541
2542     init_function_pointers();
2543
2544     /* be sure we have a clean console (and that's our own)
2545      * FIXME: this will make the test fail (currently) if we don't run
2546      * under X11
2547      * Another solution would be to rerun the test under wineconsole with
2548      * the curses backend
2549      */
2550
2551     /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
2552      * correctly for characters that don't have a glyph in the console font. So,
2553      * we first set the console font to Lucida Console (which has a wider
2554      * selection of glyphs available than the default raster fonts). We want
2555      * to be able to restore the original font afterwards, so don't change
2556      * if we can't read the original font.
2557      */
2558     err = RegOpenKeyExA(HKEY_CURRENT_USER, "Console", 0,
2559                         KEY_QUERY_VALUE | KEY_SET_VALUE, &console_key);
2560     if (err == ERROR_SUCCESS)
2561     {
2562         size = sizeof(old_font);
2563         err = RegQueryValueExA(console_key, "FaceName", NULL, NULL,
2564                                (LPBYTE) old_font, &size);
2565         if (err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND)
2566         {
2567             delete = (err == ERROR_FILE_NOT_FOUND);
2568             err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
2569                                  (const BYTE *) font_name, sizeof(font_name));
2570             if (err != ERROR_SUCCESS)
2571                 trace("Unable to change default console font, error %d\n", err);
2572         }
2573         else
2574         {
2575             trace("Unable to query default console font, error %d\n", err);
2576             RegCloseKey(console_key);
2577             console_key = NULL;
2578         }
2579     }
2580     else
2581     {
2582         trace("Unable to open HKCU\\Console, error %d\n", err);
2583         console_key = NULL;
2584     }
2585
2586     /* Now detach and open a fresh console to play with */
2587     FreeConsole();
2588     ok(AllocConsole(), "Couldn't alloc console\n");
2589
2590     /* Restore default console font if needed */
2591     if (console_key != NULL)
2592     {
2593         if (delete)
2594             err = RegDeleteValueA(console_key, "FaceName");
2595         else
2596             err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
2597                                  (const BYTE *) old_font, strlen(old_font) + 1);
2598         ok(err == ERROR_SUCCESS, "Unable to restore default console font, error %d\n", err);
2599     }
2600     hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2601     hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2602
2603     /* now verify everything's ok */
2604     ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
2605     ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
2606
2607     ret = GetConsoleScreenBufferInfo(hConOut, &sbi);
2608     ok(ret, "Getting sb info\n");
2609     if (!ret) return;
2610
2611     /* Non interactive tests */
2612     testCursor(hConOut, sbi.dwSize);
2613     /* test parameters (FIXME: test functionality) */
2614     testCursorInfo(hConOut);
2615     /* will test wrapped (on/off) & processed (on/off) strings output */
2616     testWrite(hConOut, sbi.dwSize);
2617     /* will test line scrolling at the bottom of the screen */
2618     /* testBottomScroll(); */
2619     /* will test all the scrolling operations */
2620     testScroll(hConOut, sbi.dwSize);
2621     /* will test sb creation / modification / codepage handling */
2622     testScreenBuffer(hConOut);
2623     testCtrlHandler();
2624     /* still to be done: access rights & access on objects */
2625
2626     if (!pGetConsoleInputExeNameA || !pSetConsoleInputExeNameA)
2627         win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
2628     else
2629         test_GetSetConsoleInputExeName();
2630
2631     test_GetConsoleProcessList();
2632     test_OpenConsoleW();
2633     test_CreateFileW();
2634     test_OpenCON();
2635     test_VerifyConsoleIoHandle(hConOut);
2636     test_GetSetStdHandle();
2637     test_GetNumberOfConsoleInputEvents(hConIn);
2638     test_WriteConsoleInputA(hConIn);
2639     test_WriteConsoleInputW(hConIn);
2640     test_WriteConsoleOutputCharacterA(hConOut);
2641     test_WriteConsoleOutputCharacterW(hConOut);
2642     test_WriteConsoleOutputAttribute(hConOut);
2643     test_FillConsoleOutputCharacterA(hConOut);
2644     test_FillConsoleOutputCharacterW(hConOut);
2645     test_FillConsoleOutputAttribute(hConOut);
2646     test_ReadConsoleOutputCharacterA(hConOut);
2647     test_ReadConsoleOutputCharacterW(hConOut);
2648     test_ReadConsoleOutputAttribute(hConOut);
2649 }