ReactOS  0.4.13-dev-443-g10f00f8
console.c
Go to the documentation of this file.
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 = ReadConsoleOutputCharacterA((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");
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;
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",
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",
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",
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",
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",
137 }
138 
139 static void testCursorInfo(HANDLE hCon)
140 {
141  BOOL ret;
143 
144  SetLastError(0xdeadbeef);
146  ok(!ret, "Expected failure\n");
147  ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
149 
150  SetLastError(0xdeadbeef);
151  info.dwSize = -1;
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",
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(WriteConsoleA(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(!WriteConsoleA(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(WriteConsoleA(hCon, NULL, 128, &len, NULL) != 0 && len == 128, "WriteConsole\n");
197  }
198 
199  len = -1;
200  ok(WriteConsoleA(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(WriteConsoleA(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(WriteConsoleA(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 
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 
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 = WriteConsoleA(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(WriteConsoleA(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 
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(WriteConsoleA(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(WriteConsoleA(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(WriteConsoleA(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 
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(WriteConsoleA(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 
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(WriteConsoleA(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(WriteConsoleA(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 ensure that the sb is at least 10 characters 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(ScrollConsoleScreenBufferA(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(ScrollConsoleScreenBufferA(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 = ScrollConsoleScreenBufferA(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 */
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(ScrollConsoleScreenBufferA(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  */
646 {
647  mch_count++;
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 ensure, so far, that
658  * events are processed synchronously in GenerateConsoleCtrlEvent()
659  */
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");
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");
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");
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, error;
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);
723  {
724  win_skip("SetConsoleOutputCP is not implemented\n");
725  return;
726  }
727  ok(ret, "Cannot set output codepage to 866\n");
728 
732  ok(hConOutRW != INVALID_HANDLE_VALUE,
733  "Cannot create a new screen buffer for ReadWrite\n");
737  ok(hConOutRO != INVALID_HANDLE_VALUE,
738  "Cannot create a new screen buffer for ReadOnly\n");
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,
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);
759  "Shouldn't succeed\n");
761  "GetLastError: expecting %u got %u\n",
763 
764  /* Trying to set non-console handles */
765  SetLastError(0);
766  ok(!SetConsoleActiveScreenBuffer(hFileOutRW), "Shouldn't succeed\n");
768  "GetLastError: expecting %u got %u\n",
770 
771  SetLastError(0);
772  ok(!SetConsoleActiveScreenBuffer(hFileOutRO), "Shouldn't succeed\n");
774  "GetLastError: expecting %u got %u\n",
776 
777  SetLastError(0);
778  ok(!SetConsoleActiveScreenBuffer(hFileOutWT), "Shouldn't succeed\n");
780  "GetLastError: expecting %u got %u\n",
782 
783  /* trying to write non-console handle */
784  SetLastError(0xdeadbeef);
785  ret = WriteConsoleA(hFileOutRW, test_str1, lstrlenA(test_str1), &len, NULL);
786  error = GetLastError();
787  ok(!ret, "Shouldn't succeed\n");
789  "GetLastError: got %u\n", error);
790 
791  SetLastError(0xdeadbeef);
792  ret = WriteConsoleA(hFileOutRO, test_str1, lstrlenA(test_str1), &len, NULL);
793  error = GetLastError();
794  ok(!ret, "Shouldn't succeed\n");
796  "GetLastError: got %u\n", error);
797 
798  SetLastError(0xdeadbeef);
799  ret = WriteConsoleA(hFileOutWT, test_str1, lstrlenA(test_str1), &len, NULL);
800  error = GetLastError();
801  ok(!ret, "Shouldn't succeed\n");
803  "GetLastError: got %u\n", error);
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");
813  "GetLastError: expecting %u got %u\n",
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 */
906 
907  /* restore codepage */
908  SetConsoleOutputCP(oldcp);
909 }
910 
912 {
913  HANDLE event = p;
914  SetEvent(event);
915  ok(!timeout, "wait shouldn't have timed out\n");
916 }
917 
918 static void testWaitForConsoleInput(HANDLE input_handle)
919 {
920  HANDLE wait_handle;
923  DWORD events_written;
924  DWORD wait_ret;
925  BOOL ret;
926 
928 
929  /* Test success case */
931  ok(ret == TRUE, "Expected RegisterWaitForSingleObject to return TRUE, got %d\n", ret);
932  /* give worker thread a chance to start up */
933  Sleep(100);
934  record.EventType = KEY_EVENT;
935  record.Event.KeyEvent.bKeyDown = 1;
936  record.Event.KeyEvent.wRepeatCount = 1;
937  record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
938  record.Event.KeyEvent.wVirtualScanCode = VK_RETURN;
939  record.Event.KeyEvent.uChar.UnicodeChar = '\r';
940  record.Event.KeyEvent.dwControlKeyState = 0;
941  ret = WriteConsoleInputW(input_handle, &record, 1, &events_written);
942  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
944  ok(wait_ret == WAIT_OBJECT_0, "Expected the handle to be signaled\n");
945  ret = UnregisterWait(wait_handle);
946  /* If the callback is still running, this fails with ERROR_IO_PENDING, but
947  that's ok and expected. */
948  ok(ret != 0 || GetLastError() == ERROR_IO_PENDING,
949  "UnregisterWait failed with error %d\n", GetLastError());
950 
951  /* Test timeout case */
952  FlushConsoleInputBuffer(input_handle);
954  wait_ret = WaitForSingleObject(complete_event, 100);
955  ok(wait_ret == WAIT_TIMEOUT, "Expected the wait to time out\n");
956  ret = UnregisterWait(wait_handle);
957  ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
958 
959  /* Clean up */
961 }
962 
964 {
965  BOOL ret;
966  DWORD error;
967  char buffer[MAX_PATH], module[MAX_PATH], *p;
968  static char input_exe[MAX_PATH] = "winetest.exe";
969 
970  SetLastError(0xdeadbeef);
971  ret = pGetConsoleInputExeNameA(0, NULL);
972  error = GetLastError();
973  ok(ret, "GetConsoleInputExeNameA failed\n");
974  ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
975 
976  SetLastError(0xdeadbeef);
977  ret = pGetConsoleInputExeNameA(0, buffer);
978  error = GetLastError();
979  ok(ret, "GetConsoleInputExeNameA failed\n");
980  ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
981 
983  p = strrchr(module, '\\') + 1;
984 
985  ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
986  ok(ret, "GetConsoleInputExeNameA failed\n");
987  todo_wine ok(!lstrcmpA(buffer, p), "got %s expected %s\n", buffer, p);
988 
989  SetLastError(0xdeadbeef);
990  ret = pSetConsoleInputExeNameA(NULL);
991  error = GetLastError();
992  ok(!ret, "SetConsoleInputExeNameA failed\n");
993  ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
994 
995  SetLastError(0xdeadbeef);
996  ret = pSetConsoleInputExeNameA("");
997  error = GetLastError();
998  ok(!ret, "SetConsoleInputExeNameA failed\n");
999  ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
1000 
1001  ret = pSetConsoleInputExeNameA(input_exe);
1002  ok(ret, "SetConsoleInputExeNameA failed\n");
1003 
1004  ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
1005  ok(ret, "GetConsoleInputExeNameA failed\n");
1006  ok(!lstrcmpA(buffer, input_exe), "got %s expected %s\n", buffer, input_exe);
1007 }
1008 
1010 {
1011  DWORD ret, *list = NULL;
1012 
1013  if (!pGetConsoleProcessList)
1014  {
1015  win_skip("GetConsoleProcessList is not available\n");
1016  return;
1017  }
1018 
1019  SetLastError(0xdeadbeef);
1020  ret = pGetConsoleProcessList(NULL, 0);
1021  ok(ret == 0, "Expected failure\n");
1023  "Expected ERROR_INVALID_PARAMETER, got %d\n",
1024  GetLastError());
1025 
1026  SetLastError(0xdeadbeef);
1027  ret = pGetConsoleProcessList(NULL, 1);
1028  ok(ret == 0, "Expected failure\n");
1030  "Expected ERROR_INVALID_PARAMETER, got %d\n",
1031  GetLastError());
1032 
1033  /* We should only have 1 process but only for these specific unit tests as
1034  * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would
1035  * give us two processes for example.
1036  */
1037  list = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));
1038 
1039  SetLastError(0xdeadbeef);
1040  ret = pGetConsoleProcessList(list, 0);
1041  ok(ret == 0, "Expected failure\n");
1043  "Expected ERROR_INVALID_PARAMETER, got %d\n",
1044  GetLastError());
1045 
1046  SetLastError(0xdeadbeef);
1047  ret = pGetConsoleProcessList(list, 1);
1048  todo_wine
1049  ok(ret == 1, "Expected 1, got %d\n", ret);
1050 
1051  HeapFree(GetProcessHeap(), 0, list);
1052 
1053  list = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(DWORD));
1054 
1055  SetLastError(0xdeadbeef);
1056  ret = pGetConsoleProcessList(list, ret);
1057  todo_wine
1058  ok(ret == 1, "Expected 1, got %d\n", ret);
1059 
1060  if (ret == 1)
1061  {
1063  ok(list[0] == pid, "Expected %d, got %d\n", pid, list[0]);
1064  }
1065 
1066  HeapFree(GetProcessHeap(), 0, list);
1067 }
1068 
1069 static void test_OpenCON(void)
1070 {
1071  static const WCHAR conW[] = {'C','O','N',0};
1072  static const DWORD accesses[] = {CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING,
1074  unsigned i;
1075  HANDLE h;
1076 
1077  for (i = 0; i < sizeof(accesses) / sizeof(accesses[0]); i++)
1078  {
1079  h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1080  ok(h != INVALID_HANDLE_VALUE || broken(accesses[i] == TRUNCATE_EXISTING /* Win8 */),
1081  "Expected to open the CON device on write (%x)\n", accesses[i]);
1082  CloseHandle(h);
1083 
1084  h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL);
1085  /* Windows versions differ here:
1086  * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1087  * NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING
1088  * So don't test when disposition is TRUNCATE_EXISTING
1089  */
1090  ok(h != INVALID_HANDLE_VALUE || broken(accesses[i] == TRUNCATE_EXISTING /* Win7+ */),
1091  "Expected to open the CON device on read (%x)\n", accesses[i]);
1092  CloseHandle(h);
1093  h = CreateFileW(conW, GENERIC_READ|GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1094  ok(h == INVALID_HANDLE_VALUE, "Expected not to open the CON device on read-write (%x)\n", accesses[i]);
1096  "Unexpected error %x\n", GetLastError());
1097  }
1098 }
1099 
1100 static void test_OpenConsoleW(void)
1101 {
1102  static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1103  static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1104  static const WCHAR emptyW[] = {0};
1105  static const WCHAR invalidW[] = {'I','N','V','A','L','I','D',0};
1106  DWORD gle;
1107 
1108  static const struct
1109  {
1110  LPCWSTR name;
1111  DWORD access;
1112  BOOL inherit;
1113  DWORD creation;
1114  DWORD gle, gle2;
1115  } invalid_table[] = {
1119  {NULL, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1127  {emptyW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1133  {invalidW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1135  {invalidW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1140  {coninW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1141  {coninW, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED},
1142  {coninW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1143  {conoutW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1144  {conoutW, 0xceadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED},
1145  {conoutW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1146  };
1147  static const struct
1148  {
1149  LPCWSTR name;
1150  DWORD access;
1151  BOOL inherit;
1152  DWORD creation;
1153  } valid_table[] = {
1154  {coninW, 0, FALSE, 0 },
1155  {coninW, 0, TRUE, 0 },
1156  {coninW, GENERIC_EXECUTE, TRUE, 0 },
1157  {coninW, GENERIC_ALL, TRUE, 0 },
1158  {coninW, 0, FALSE, OPEN_ALWAYS },
1159  {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, 0 },
1160  {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW },
1164  {conoutW, 0, FALSE, 0 },
1165  {conoutW, 0, FALSE, OPEN_ALWAYS },
1166  {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, 0 },
1167  {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, },
1169  {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS },
1171  };
1172 
1173  int index;
1174  HANDLE ret;
1175 
1176  if (!pOpenConsoleW)
1177  {
1178  win_skip("OpenConsoleW is not available\n");
1179  return;
1180  }
1181 
1182  for (index = 0; index < sizeof(invalid_table)/sizeof(invalid_table[0]); index++)
1183  {
1184  SetLastError(0xdeadbeef);
1185  ret = pOpenConsoleW(invalid_table[index].name, invalid_table[index].access,
1186  invalid_table[index].inherit, invalid_table[index].creation);
1187  gle = GetLastError();
1189  "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1190  index, ret);
1191  ok(gle == invalid_table[index].gle || (gle != 0 && gle == invalid_table[index].gle2),
1192  "Expected GetLastError() to return %u/%u for index %d, got %u\n",
1193  invalid_table[index].gle, invalid_table[index].gle2, index, gle);
1194  }
1195 
1196  for (index = 0; index < sizeof(valid_table)/sizeof(valid_table[0]); index++)
1197  {
1198  ret = pOpenConsoleW(valid_table[index].name, valid_table[index].access,
1199  valid_table[index].inherit, valid_table[index].creation);
1200  todo_wine
1201  ok(ret != INVALID_HANDLE_VALUE || broken(ret == INVALID_HANDLE_VALUE /* until Win7 */),
1202  "Expected OpenConsoleW to succeed for index %d, got %p\n", index, ret);
1203  if (ret != INVALID_HANDLE_VALUE)
1204  CloseHandle(ret);
1205  }
1206 
1207  ret = pOpenConsoleW(coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1208  ok(ret != INVALID_HANDLE_VALUE, "Expected OpenConsoleW to return a valid handle\n");
1209  if (ret != INVALID_HANDLE_VALUE)
1210  CloseHandle(ret);
1211 
1212  ret = pOpenConsoleW(conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1213  ok(ret != INVALID_HANDLE_VALUE, "Expected OpenConsoleW to return a valid handle\n");
1214  if (ret != INVALID_HANDLE_VALUE)
1215  CloseHandle(ret);
1216 }
1217 
1218 static void test_CreateFileW(void)
1219 {
1220  static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1221  static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1222 
1223  static const struct
1224  {
1225  LPCWSTR name;
1226  DWORD access;
1227  BOOL inherit;
1228  DWORD creation;
1229  DWORD gle;
1230  BOOL is_broken;
1231  } cf_table[] = {
1232  {coninW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE},
1233  {coninW, 0, FALSE, OPEN_ALWAYS, 0, FALSE},
1235  {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, 0, FALSE},
1237  {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, 0, FALSE},
1238  {conoutW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE},
1239  {conoutW, 0, FALSE, OPEN_ALWAYS, 0, FALSE},
1241  {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, 0, FALSE},
1242  {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, 0, FALSE},
1243  {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, 0, FALSE},
1244  /* TRUNCATE_EXISTING is forbidden starting with Windows 8 */
1245  };
1246 
1247  int index;
1248  HANDLE ret;
1250 
1251  for (index = 0; index < sizeof(cf_table)/sizeof(cf_table[0]); index++)
1252  {
1253  SetLastError(0xdeadbeef);
1254 
1255  sa.nLength = sizeof(sa);
1256  sa.lpSecurityDescriptor = NULL;
1257  sa.bInheritHandle = cf_table[index].inherit;
1258 
1259  ret = CreateFileW(cf_table[index].name, cf_table[index].access,
1261  cf_table[index].creation, FILE_ATTRIBUTE_NORMAL, NULL);
1262  if (ret == INVALID_HANDLE_VALUE)
1263  {
1264  ok(cf_table[index].gle,
1265  "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index);
1266  ok(GetLastError() == cf_table[index].gle,
1267  "Expected GetLastError() to return %u for index %d, got %u\n",
1268  cf_table[index].gle, index, GetLastError());
1269  }
1270  else
1271  {
1272  ok(!cf_table[index].gle || broken(cf_table[index].is_broken) /* Win7 */,
1273  "Expected CreateFileW to succeed for index %d\n", index);
1274  CloseHandle(ret);
1275  }
1276  }
1277 }
1278 
1280 {
1281  BOOL ret;
1282  DWORD error;
1283 
1284  if (!pVerifyConsoleIoHandle)
1285  {
1286  win_skip("VerifyConsoleIoHandle is not available\n");
1287  return;
1288  }
1289 
1290  /* invalid handle */
1291  SetLastError(0xdeadbeef);
1292  ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee0);
1293  error = GetLastError();
1294  ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1295  ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1296 
1297  /* invalid handle + 1 */
1298  SetLastError(0xdeadbeef);
1299  ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee1);
1300  error = GetLastError();
1301  ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1302  ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1303 
1304  /* invalid handle + 2 */
1305  SetLastError(0xdeadbeef);
1306  ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee2);
1307  error = GetLastError();
1308  ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1309  ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1310 
1311  /* invalid handle + 3 */
1312  SetLastError(0xdeadbeef);
1313  ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee3);
1314  error = GetLastError();
1315  ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1316  ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1317 
1318  /* valid handle */
1319  SetLastError(0xdeadbeef);
1320  ret = pVerifyConsoleIoHandle(handle);
1321  error = GetLastError();
1322  ok(ret ||
1323  broken(!ret), /* Windows 8 and 10 */
1324  "expected VerifyConsoleIoHandle to succeed\n");
1325  ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1326 }
1327 
1328 static void test_GetSetStdHandle(void)
1329 {
1330  HANDLE handle;
1331  DWORD error;
1332  BOOL ret;
1333 
1334  /* get invalid std handle */
1335  SetLastError(0xdeadbeef);
1336  handle = GetStdHandle(42);
1337  error = GetLastError();
1339  "wrong GetLastError() %d\n", error);
1340  ok(handle == INVALID_HANDLE_VALUE, "expected INVALID_HANDLE_VALUE\n");
1341 
1342  /* get valid */
1343  SetLastError(0xdeadbeef);
1345  error = GetLastError();
1346  ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1347 
1348  /* set invalid std handle */
1349  SetLastError(0xdeadbeef);
1350  ret = SetStdHandle(42, handle);
1351  error = GetLastError();
1352  ok(!ret, "expected SetStdHandle to fail\n");
1354  "wrong GetLastError() %d\n", error);
1355 
1356  /* set valid (restore old value) */
1357  SetLastError(0xdeadbeef);
1359  error = GetLastError();
1360  ok(ret, "expected SetStdHandle to succeed\n");
1361  ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1362 }
1363 
1365 {
1366  DWORD count;
1367  BOOL ret;
1368  int i;
1369 
1370  const struct
1371  {
1372  HANDLE handle;
1373  LPDWORD nrofevents;
1374  DWORD last_error;
1375  } invalid_table[] =
1376  {
1381  };
1382 
1383  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1384  {
1385  SetLastError(0xdeadbeef);
1386  if (invalid_table[i].nrofevents) count = 0xdeadbeef;
1387  ret = GetNumberOfConsoleInputEvents(invalid_table[i].handle,
1388  invalid_table[i].nrofevents);
1389  ok(!ret, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i, ret);
1390  if (invalid_table[i].nrofevents)
1391  {
1392  ok(count == 0xdeadbeef,
1393  "[%d] Expected output count to be unmodified, got %u\n", i, count);
1394  }
1395  ok(GetLastError() == invalid_table[i].last_error,
1396  "[%d] Expected last error to be %u, got %u\n",
1397  i, invalid_table[i].last_error, GetLastError());
1398  }
1399 
1400  /* Test crashes on Windows 7. */
1401  if (0)
1402  {
1403  SetLastError(0xdeadbeef);
1404  ret = GetNumberOfConsoleInputEvents(input_handle, NULL);
1405  ok(!ret, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret);
1407  "Expected last error to be ERROR_INVALID_ACCESS, got %u\n",
1408  GetLastError());
1409  }
1410 
1411  count = 0xdeadbeef;
1412  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1413  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1414  ok(count != 0xdeadbeef, "Expected output count to initialized\n");
1415 }
1416 
1417 static void test_WriteConsoleInputA(HANDLE input_handle)
1418 {
1420  INPUT_RECORD event_list[5];
1421  MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1423  DWORD count, console_mode, gle;
1424  BOOL ret;
1425  int i;
1426 
1427  const struct
1428  {
1429  HANDLE handle;
1430  const INPUT_RECORD *buffer;
1431  DWORD count;
1432  LPDWORD written;
1433  DWORD gle, gle2;
1434  int win_crash;
1435  } invalid_table[] =
1436  {
1437  {NULL, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
1439  {NULL, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
1441  {NULL, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
1443  {NULL, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
1453  {input_handle, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
1454  {input_handle, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
1455  {input_handle, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
1456  {input_handle, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
1457  {input_handle, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
1458  };
1459 
1460  /* Suppress external sources of input events for the duration of the test. */
1461  ret = GetConsoleMode(input_handle, &console_mode);
1462  ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1463  if (!ret)
1464  {
1465  skip("GetConsoleMode failed with last error %u\n", GetLastError());
1466  return;
1467  }
1468 
1469  ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1470  ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1471  if (!ret)
1472  {
1473  skip("SetConsoleMode failed with last error %u\n", GetLastError());
1474  return;
1475  }
1476 
1477  /* Discard any events queued before the tests. */
1478  ret = FlushConsoleInputBuffer(input_handle);
1479  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1480 
1481  event.EventType = MOUSE_EVENT;
1482  event.Event.MouseEvent = mouse_event;
1483 
1484  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1485  {
1486  if (invalid_table[i].win_crash)
1487  continue;
1488 
1489  SetLastError(0xdeadbeef);
1490  if (invalid_table[i].written) count = 0xdeadbeef;
1491  ret = WriteConsoleInputA(invalid_table[i].handle,
1492  invalid_table[i].buffer,
1493  invalid_table[i].count,
1494  invalid_table[i].written);
1495  ok(!ret, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i, ret);
1496  gle = GetLastError();
1497  ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2),
1498  "[%d] Expected last error to be %u or %u, got %u\n",
1499  i, invalid_table[i].gle, invalid_table[i].gle2, gle);
1500  }
1501 
1502  count = 0xdeadbeef;
1503  ret = WriteConsoleInputA(input_handle, NULL, 0, &count);
1504  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1505  ok(count == 0, "Expected count to be 0, got %u\n", count);
1506 
1507  count = 0xdeadbeef;
1508  ret = WriteConsoleInputA(input_handle, &event, 0, &count);
1509  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1510  ok(count == 0, "Expected count to be 0, got %u\n", count);
1511 
1512  count = 0xdeadbeef;
1513  ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1514  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1515  ok(count == 1, "Expected count to be 1, got %u\n", count);
1516 
1517  ret = FlushConsoleInputBuffer(input_handle);
1518  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1519 
1520  /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1521  event.EventType = MOUSE_EVENT;
1522  event.Event.MouseEvent = mouse_event;
1523 
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  todo_wine
1539  ok(count == 1, "Expected count to be 1, got %u\n", count);
1540 
1541  ret = FlushConsoleInputBuffer(input_handle);
1542  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1543 
1544  for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1545  {
1546  event_list[i].EventType = MOUSE_EVENT;
1547  event_list[i].Event.MouseEvent = mouse_event;
1548  }
1549 
1550  /* Writing consecutive chunks of mouse events appears to work. */
1551  ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1552  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1553  ok(count == sizeof(event_list)/sizeof(event_list[0]),
1554  "Expected count to be event list length, got %u\n", count);
1555 
1556  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1557  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1558  ok(count == sizeof(event_list)/sizeof(event_list[0]),
1559  "Expected count to be event list length, got %u\n", count);
1560 
1561  ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1562  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1563  ok(count == sizeof(event_list)/sizeof(event_list[0]),
1564  "Expected count to be event list length, got %u\n", count);
1565 
1566  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1567  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1568  ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1569  "Expected count to be twice event list length, got %u\n", count);
1570 
1571  /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1572  ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1573  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1574  ok(count == 1, "Expected count to be 1, got %u\n", count);
1575 
1576  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1577  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1578  todo_wine
1579  ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1580  "Expected count to be twice event list length, got %u\n", count);
1581 
1582  ret = FlushConsoleInputBuffer(input_handle);
1583  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1584 
1585  key_event.bKeyDown = FALSE;
1586  key_event.wRepeatCount = 0;
1587  key_event.wVirtualKeyCode = VK_SPACE;
1588  key_event.wVirtualScanCode = VK_SPACE;
1589  key_event.uChar.AsciiChar = ' ';
1590  key_event.dwControlKeyState = 0;
1591 
1592  event.EventType = KEY_EVENT;
1593  event.Event.KeyEvent = key_event;
1594 
1595  /* Key events don't exhibit the same behavior as mouse events. */
1596  ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1597  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1598  ok(count == 1, "Expected count to be 1, got %u\n", count);
1599 
1600  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1601  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1602  ok(count == 1, "Expected count to be 1, got %u\n", count);
1603 
1604  ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1605  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1606  ok(count == 1, "Expected count to be 1, got %u\n", count);
1607 
1608  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1609  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1610  ok(count == 2, "Expected count to be 2, got %u\n", count);
1611 
1612  ret = FlushConsoleInputBuffer(input_handle);
1613  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1614 
1615  /* Try interleaving mouse and key events. */
1616  event.EventType = MOUSE_EVENT;
1617  event.Event.MouseEvent = mouse_event;
1618 
1619  ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1620  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1621  ok(count == 1, "Expected count to be 1, got %u\n", count);
1622 
1623  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1624  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1625  ok(count == 1, "Expected count to be 1, got %u\n", count);
1626 
1627  event.EventType = KEY_EVENT;
1628  event.Event.KeyEvent = key_event;
1629 
1630  ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1631  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1632  ok(count == 1, "Expected count to be 1, got %u\n", count);
1633 
1634  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1635  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1636  ok(count == 2, "Expected count to be 2, got %u\n", count);
1637 
1638  event.EventType = MOUSE_EVENT;
1639  event.Event.MouseEvent = mouse_event;
1640 
1641  ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1642  ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1643  ok(count == 1, "Expected count to be 1, got %u\n", count);
1644 
1645  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1646  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1647  ok(count == 3, "Expected count to be 3, got %u\n", count);
1648 
1649  /* Restore the old console mode. */
1650  ret = SetConsoleMode(input_handle, console_mode);
1651  ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1652 }
1653 
1654 static void test_WriteConsoleInputW(HANDLE input_handle)
1655 {
1657  INPUT_RECORD event_list[5];
1658  MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1660  DWORD count, console_mode, gle;
1661  BOOL ret;
1662  int i;
1663 
1664  const struct
1665  {
1666  HANDLE handle;
1667  const INPUT_RECORD *buffer;
1668  DWORD count;
1669  LPDWORD written;
1670  DWORD gle, gle2;
1671  int win_crash;
1672  } invalid_table[] =
1673  {
1674  {NULL, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
1676  {NULL, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
1678  {NULL, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
1680  {NULL, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
1690  {input_handle, NULL, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
1691  {input_handle, NULL, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
1692  {input_handle, NULL, 1, &count, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
1693  {input_handle, &event, 0, NULL, ERROR_INVALID_ACCESS, 0, 1},
1694  {input_handle, &event, 1, NULL, ERROR_INVALID_ACCESS, 0, 1},
1695  };
1696 
1697  /* Suppress external sources of input events for the duration of the test. */
1698  ret = GetConsoleMode(input_handle, &console_mode);
1699  ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1700  if (!ret)
1701  {
1702  skip("GetConsoleMode failed with last error %u\n", GetLastError());
1703  return;
1704  }
1705 
1706  ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1707  ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1708  if (!ret)
1709  {
1710  skip("SetConsoleMode failed with last error %u\n", GetLastError());
1711  return;
1712  }
1713 
1714  /* Discard any events queued before the tests. */
1715  ret = FlushConsoleInputBuffer(input_handle);
1716  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1717 
1718  event.EventType = MOUSE_EVENT;
1719  event.Event.MouseEvent = mouse_event;
1720 
1721  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1722  {
1723  if (invalid_table[i].win_crash)
1724  continue;
1725 
1726  SetLastError(0xdeadbeef);
1727  if (invalid_table[i].written) count = 0xdeadbeef;
1728  ret = WriteConsoleInputW(invalid_table[i].handle,
1729  invalid_table[i].buffer,
1730  invalid_table[i].count,
1731  invalid_table[i].written);
1732  ok(!ret, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i, ret);
1733  gle = GetLastError();
1734  ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2),
1735  "[%d] Expected last error to be %u or %u, got %u\n",
1736  i, invalid_table[i].gle, invalid_table[i].gle2, gle);
1737  }
1738 
1739  count = 0xdeadbeef;
1740  ret = WriteConsoleInputW(input_handle, NULL, 0, &count);
1741  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1742  ok(count == 0, "Expected count to be 0, got %u\n", count);
1743 
1744  count = 0xdeadbeef;
1745  ret = WriteConsoleInputW(input_handle, &event, 0, &count);
1746  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1747  ok(count == 0, "Expected count to be 0, got %u\n", count);
1748 
1749  count = 0xdeadbeef;
1750  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1751  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1752  ok(count == 1, "Expected count to be 1, got %u\n", count);
1753 
1754  ret = FlushConsoleInputBuffer(input_handle);
1755  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1756 
1757  /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1758  event.EventType = MOUSE_EVENT;
1759  event.Event.MouseEvent = mouse_event;
1760 
1761  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1762  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1763  ok(count == 1, "Expected count to be 1, got %u\n", count);
1764 
1765  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1766  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1767  ok(count == 1, "Expected count to be 1, got %u\n", count);
1768 
1769  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1770  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1771  ok(count == 1, "Expected count to be 1, got %u\n", count);
1772 
1773  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1774  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1775  todo_wine
1776  ok(count == 1, "Expected count to be 1, got %u\n", count);
1777 
1778  ret = FlushConsoleInputBuffer(input_handle);
1779  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1780 
1781  for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1782  {
1783  event_list[i].EventType = MOUSE_EVENT;
1784  event_list[i].Event.MouseEvent = mouse_event;
1785  }
1786 
1787  /* Writing consecutive chunks of mouse events appears to work. */
1788  ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1789  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1790  ok(count == sizeof(event_list)/sizeof(event_list[0]),
1791  "Expected count to be event list length, got %u\n", count);
1792 
1793  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1794  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1795  ok(count == sizeof(event_list)/sizeof(event_list[0]),
1796  "Expected count to be event list length, got %u\n", count);
1797 
1798  ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1799  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1800  ok(count == sizeof(event_list)/sizeof(event_list[0]),
1801  "Expected count to be event list length, got %u\n", count);
1802 
1803  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1804  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1805  ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1806  "Expected count to be twice event list length, got %u\n", count);
1807 
1808  /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1809  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1810  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1811  ok(count == 1, "Expected count to be 1, got %u\n", count);
1812 
1813  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1814  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1815  todo_wine
1816  ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1817  "Expected count to be twice event list length, got %u\n", count);
1818 
1819  ret = FlushConsoleInputBuffer(input_handle);
1820  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1821 
1822  key_event.bKeyDown = FALSE;
1823  key_event.wRepeatCount = 0;
1824  key_event.wVirtualKeyCode = VK_SPACE;
1825  key_event.wVirtualScanCode = VK_SPACE;
1826  key_event.uChar.UnicodeChar = ' ';
1827  key_event.dwControlKeyState = 0;
1828 
1829  event.EventType = KEY_EVENT;
1830  event.Event.KeyEvent = key_event;
1831 
1832  /* Key events don't exhibit the same behavior as mouse events. */
1833  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1834  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1835  ok(count == 1, "Expected count to be 1, got %u\n", count);
1836 
1837  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1838  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1839  ok(count == 1, "Expected count to be 1, got %u\n", count);
1840 
1841  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1842  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1843  ok(count == 1, "Expected count to be 1, got %u\n", count);
1844 
1845  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1846  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1847  ok(count == 2, "Expected count to be 2, got %u\n", count);
1848 
1849  ret = FlushConsoleInputBuffer(input_handle);
1850  ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1851 
1852  /* Try interleaving mouse and key events. */
1853  event.EventType = MOUSE_EVENT;
1854  event.Event.MouseEvent = mouse_event;
1855 
1856  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1857  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1858  ok(count == 1, "Expected count to be 1, got %u\n", count);
1859 
1860  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1861  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1862  ok(count == 1, "Expected count to be 1, got %u\n", count);
1863 
1864  event.EventType = KEY_EVENT;
1865  event.Event.KeyEvent = key_event;
1866 
1867  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1868  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1869  ok(count == 1, "Expected count to be 1, got %u\n", count);
1870 
1871  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1872  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1873  ok(count == 2, "Expected count to be 2, got %u\n", count);
1874 
1875  event.EventType = MOUSE_EVENT;
1876  event.Event.MouseEvent = mouse_event;
1877 
1878  ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1879  ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1880  ok(count == 1, "Expected count to be 1, got %u\n", count);
1881 
1882  ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1883  ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1884  ok(count == 3, "Expected count to be 3, got %u\n", count);
1885 
1886  /* Restore the old console mode. */
1887  ret = SetConsoleMode(input_handle, console_mode);
1888  ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1889 }
1890 
1891 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle)
1892 {
1893  static const char output[] = {'a', 0};
1894 
1895  COORD origin = {0, 0};
1896  DWORD count;
1897  BOOL ret;
1898  int i;
1899 
1900  const struct
1901  {
1902  HANDLE hConsoleOutput;
1903  LPCSTR str;
1904  DWORD length;
1905  COORD coord;
1906  LPDWORD lpNumCharsWritten;
1908  DWORD last_error;
1909  int win7_crash;
1910  } invalid_table[] =
1911  {
1912  {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1913  {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1914  {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1915  {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1916  {NULL, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1917  {NULL, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1918  {NULL, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1919  {NULL, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1920  {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1922  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1923  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1924  {INVALID_HANDLE_VALUE, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1926  {INVALID_HANDLE_VALUE, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1928  {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1929  {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1930  {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1931  {output_handle, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1932  {output_handle, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1933  };
1934 
1935  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1936  {
1937  if (invalid_table[i].win7_crash)
1938  continue;
1939 
1940  SetLastError(0xdeadbeef);
1941  if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1942  ret = WriteConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
1943  invalid_table[i].str,
1944  invalid_table[i].length,
1945  invalid_table[i].coord,
1946  invalid_table[i].lpNumCharsWritten);
1947  ok(!ret, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
1948  if (invalid_table[i].lpNumCharsWritten)
1949  {
1950  ok(count == invalid_table[i].expected_count,
1951  "[%d] Expected count to be %u, got %u\n",
1952  i, invalid_table[i].expected_count, count);
1953  }
1954  ok(GetLastError() == invalid_table[i].last_error,
1955  "[%d] Expected last error to be %u, got %u\n",
1956  i, invalid_table[i].last_error, GetLastError());
1957  }
1958 
1959  count = 0xdeadbeef;
1960  ret = WriteConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
1961  ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1962  ok(count == 0, "Expected count to be 0, got %u\n", count);
1963 
1964  count = 0xdeadbeef;
1965  ret = WriteConsoleOutputCharacterA(output_handle, output, 0, origin, &count);
1966  ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1967  ok(count == 0, "Expected count to be 0, got %u\n", count);
1968 
1969  count = 0xdeadbeef;
1970  ret = WriteConsoleOutputCharacterA(output_handle, output, 1, origin, &count);
1971  ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1972  ok(count == 1, "Expected count to be 1, got %u\n", count);
1973 }
1974 
1975 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle)
1976 {
1977  static const WCHAR outputW[] = {'a',0};
1978 
1979  COORD origin = {0, 0};
1980  DWORD count;
1981  BOOL ret;
1982  int i;
1983 
1984  const struct
1985  {
1986  HANDLE hConsoleOutput;
1987  LPCWSTR str;
1988  DWORD length;
1989  COORD coord;
1990  LPDWORD lpNumCharsWritten;
1992  DWORD last_error;
1993  int win7_crash;
1994  } invalid_table[] =
1995  {
1996  {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1997  {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1998  {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1999  {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2000  {NULL, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2001  {NULL, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2002  {NULL, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2003  {NULL, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2004  {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2006  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2007  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2008  {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2009  {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2010  {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2011  {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2012  {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2013  {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2014  {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2015  {output_handle, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2016  {output_handle, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2017  };
2018 
2019  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2020  {
2021  if (invalid_table[i].win7_crash)
2022  continue;
2023 
2024  SetLastError(0xdeadbeef);
2025  if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2026  ret = WriteConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2027  invalid_table[i].str,
2028  invalid_table[i].length,
2029  invalid_table[i].coord,
2030  invalid_table[i].lpNumCharsWritten);
2031  ok(!ret, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2032  if (invalid_table[i].lpNumCharsWritten)
2033  {
2034  ok(count == invalid_table[i].expected_count,
2035  "[%d] Expected count to be %u, got %u\n",
2036  i, invalid_table[i].expected_count, count);
2037  }
2038  ok(GetLastError() == invalid_table[i].last_error,
2039  "[%d] Expected last error to be %u, got %u\n",
2040  i, invalid_table[i].last_error, GetLastError());
2041  }
2042 
2043  count = 0xdeadbeef;
2044  ret = WriteConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
2045  ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2046  ok(count == 0, "Expected count to be 0, got %u\n", count);
2047 
2048  count = 0xdeadbeef;
2049  ret = WriteConsoleOutputCharacterW(output_handle, outputW, 0, origin, &count);
2050  ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2051  ok(count == 0, "Expected count to be 0, got %u\n", count);
2052 
2053  count = 0xdeadbeef;
2054  ret = WriteConsoleOutputCharacterW(output_handle, outputW, 1, origin, &count);
2055  ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2056  ok(count == 1, "Expected count to be 1, got %u\n", count);
2057 }
2058 
2059 static void test_WriteConsoleOutputAttribute(HANDLE output_handle)
2060 {
2062  COORD origin = {0, 0};
2063  DWORD count;
2064  BOOL ret;
2065  int i;
2066 
2067  const struct
2068  {
2069  HANDLE hConsoleOutput;
2070  const WORD *attr;
2071  DWORD length;
2072  COORD coord;
2073  LPDWORD lpNumAttrsWritten;
2075  DWORD last_error;
2076  int win7_crash;
2077  } invalid_table[] =
2078  {
2079  {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2080  {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2081  {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2082  {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2083  {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2084  {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2085  {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2086  {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2087  {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2089  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2090  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2091  {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2092  {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2093  {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2094  {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2095  {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2096  {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2097  {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2098  {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2099  {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2100  };
2101 
2102  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2103  {
2104  if (invalid_table[i].win7_crash)
2105  continue;
2106 
2107  SetLastError(0xdeadbeef);
2108  if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2109  ret = WriteConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2110  invalid_table[i].attr,
2111  invalid_table[i].length,
2112  invalid_table[i].coord,
2113  invalid_table[i].lpNumAttrsWritten);
2114  ok(!ret, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2115  if (invalid_table[i].lpNumAttrsWritten)
2116  {
2117  ok(count == invalid_table[i].expected_count,
2118  "[%d] Expected count to be %u, got %u\n",
2119  i, invalid_table[i].expected_count, count);
2120  }
2121  ok(GetLastError() == invalid_table[i].last_error,
2122  "[%d] Expected last error to be %u, got %u\n",
2123  i, invalid_table[i].last_error, GetLastError());
2124  }
2125 
2126  count = 0xdeadbeef;
2127  ret = WriteConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2128  ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2129  ok(count == 0, "Expected count to be 0, got %u\n", count);
2130 
2131  count = 0xdeadbeef;
2132  ret = WriteConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2133  ok(ret == TRUE, "Expected WriteConsoleOutputAttribute 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 = WriteConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2138  ok(ret == TRUE, "Expected WriteConsoleOutputAttribute 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_FillConsoleOutputCharacterA(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  CHAR ch;
2153  DWORD length;
2154  COORD coord;
2155  LPDWORD lpNumCharsWritten;
2156  DWORD last_error;
2157  int win7_crash;
2158  } invalid_table[] =
2159  {
2160  {NULL, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2161  {NULL, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
2162  {NULL, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2163  {NULL, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
2164  {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2165  {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
2166  {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2167  {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
2168  {output_handle, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2169  {output_handle, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2170  };
2171 
2172  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2173  {
2174  if (invalid_table[i].win7_crash)
2175  continue;
2176 
2177  SetLastError(0xdeadbeef);
2178  if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2179  ret = FillConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2180  invalid_table[i].ch,
2181  invalid_table[i].length,
2182  invalid_table[i].coord,
2183  invalid_table[i].lpNumCharsWritten);
2184  ok(!ret, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2185  ok(GetLastError() == invalid_table[i].last_error,
2186  "[%d] Expected last error to be %u, got %u\n",
2187  i, invalid_table[i].last_error, GetLastError());
2188  }
2189 
2190  count = 0xdeadbeef;
2191  ret = FillConsoleOutputCharacterA(output_handle, 'a', 0, origin, &count);
2192  ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2193  ok(count == 0, "Expected count to be 0, got %u\n", count);
2194 
2195  count = 0xdeadbeef;
2196  ret = FillConsoleOutputCharacterA(output_handle, 'a', 1, origin, &count);
2197  ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2198  ok(count == 1, "Expected count to be 1, got %u\n", count);
2199 }
2200 
2201 static void test_FillConsoleOutputCharacterW(HANDLE output_handle)
2202 {
2203  COORD origin = {0, 0};
2204  DWORD count;
2205  BOOL ret;
2206  int i;
2207 
2208  const struct
2209  {
2210  HANDLE hConsoleOutput;
2211  WCHAR ch;
2212  DWORD length;
2213  COORD coord;
2214  LPDWORD lpNumCharsWritten;
2215  DWORD last_error;
2216  int win7_crash;
2217  } invalid_table[] =
2218  {
2219  {NULL, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2220  {NULL, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
2221  {NULL, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2222  {NULL, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
2223  {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2224  {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, ERROR_INVALID_HANDLE},
2225  {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2226  {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, ERROR_INVALID_HANDLE},
2227  {output_handle, 'a', 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2228  {output_handle, 'a', 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2229  };
2230 
2231  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2232  {
2233  if (invalid_table[i].win7_crash)
2234  continue;
2235 
2236  SetLastError(0xdeadbeef);
2237  if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2238  ret = FillConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2239  invalid_table[i].ch,
2240  invalid_table[i].length,
2241  invalid_table[i].coord,
2242  invalid_table[i].lpNumCharsWritten);
2243  ok(!ret, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2244  ok(GetLastError() == invalid_table[i].last_error,
2245  "[%d] Expected last error to be %u, got %u\n",
2246  i, invalid_table[i].last_error, GetLastError());
2247  }
2248 
2249  count = 0xdeadbeef;
2250  ret = FillConsoleOutputCharacterW(output_handle, 'a', 0, origin, &count);
2251  ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2252  ok(count == 0, "Expected count to be 0, got %u\n", count);
2253 
2254  count = 0xdeadbeef;
2255  ret = FillConsoleOutputCharacterW(output_handle, 'a', 1, origin, &count);
2256  ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2257  ok(count == 1, "Expected count to be 1, got %u\n", count);
2258 }
2259 
2260 static void test_FillConsoleOutputAttribute(HANDLE output_handle)
2261 {
2262  COORD origin = {0, 0};
2263  DWORD count;
2264  BOOL ret;
2265  int i;
2266 
2267  const struct
2268  {
2269  HANDLE hConsoleOutput;
2270  WORD attr;
2271  DWORD length;
2272  COORD coord;
2273  LPDWORD lpNumAttrsWritten;
2274  DWORD last_error;
2275  int win7_crash;
2276  } invalid_table[] =
2277  {
2278  {NULL, FOREGROUND_BLUE, 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2280  {NULL, FOREGROUND_BLUE, 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2286  {output_handle, FOREGROUND_BLUE, 0, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2287  {output_handle, FOREGROUND_BLUE, 1, {0, 0}, NULL, ERROR_INVALID_ACCESS, 1},
2288  };
2289 
2290  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2291  {
2292  if (invalid_table[i].win7_crash)
2293  continue;
2294 
2295  SetLastError(0xdeadbeef);
2296  if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2297  ret = FillConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2298  invalid_table[i].attr,
2299  invalid_table[i].length,
2300  invalid_table[i].coord,
2301  invalid_table[i].lpNumAttrsWritten);
2302  ok(!ret, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2303  ok(GetLastError() == invalid_table[i].last_error,
2304  "[%d] Expected last error to be %u, got %u\n",
2305  i, invalid_table[i].last_error, GetLastError());
2306  }
2307 
2308  count = 0xdeadbeef;
2309  ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 0, origin, &count);
2310  ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2311  ok(count == 0, "Expected count to be 0, got %u\n", count);
2312 
2313  count = 0xdeadbeef;
2314  ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 1, origin, &count);
2315  ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2316  ok(count == 1, "Expected count to be 1, got %u\n", count);
2317 
2318  count = 0xdeadbeef;
2319  ret = FillConsoleOutputAttribute(output_handle, ~0, 1, origin, &count);
2320  ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2321  ok(count == 1, "Expected count to be 1, got %u\n", count);
2322 }
2323 
2324 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle)
2325 {
2326  CHAR read;
2327  COORD origin = {0, 0};
2328  DWORD count;
2329  BOOL ret;
2330  int i;
2331 
2332  const struct
2333  {
2334  HANDLE hConsoleOutput;
2335  LPSTR lpstr;
2336  DWORD length;
2337  COORD coord;
2338  LPDWORD read_count;
2340  DWORD last_error;
2341  int win7_crash;
2342  } invalid_table[] =
2343  {
2344  {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2345  {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2346  {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2347  {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2348  {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2349  {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2350  {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2351  {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2352  {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2354  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2355  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2356  {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2357  {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2358  {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2359  {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2360  {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2361  {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2362  {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2363  {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1},
2364  {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2365  {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2366  };
2367 
2368  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2369  {
2370  if (invalid_table[i].win7_crash)
2371  continue;
2372 
2373  SetLastError(0xdeadbeef);
2374  if (invalid_table[i].read_count) count = 0xdeadbeef;
2375  ret = ReadConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2376  invalid_table[i].lpstr,
2377  invalid_table[i].length,
2378  invalid_table[i].coord,
2379  invalid_table[i].read_count);
2380  ok(!ret, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2381  if (invalid_table[i].read_count)
2382  {
2383  ok(count == invalid_table[i].expected_count,
2384  "[%d] Expected count to be %u, got %u\n",
2385  i, invalid_table[i].expected_count, count);
2386  }
2387  ok(GetLastError() == invalid_table[i].last_error,
2388  "[%d] Expected last error to be %u, got %u\n",
2389  i, invalid_table[i].last_error, GetLastError());
2390  }
2391 
2392  count = 0xdeadbeef;
2393  ret = ReadConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
2394  ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2395  ok(count == 0, "Expected count to be 0, got %u\n", count);
2396 
2397  count = 0xdeadbeef;
2398  ret = ReadConsoleOutputCharacterA(output_handle, &read, 0, origin, &count);
2399  ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2400  ok(count == 0, "Expected count to be 0, got %u\n", count);
2401 
2402  count = 0xdeadbeef;
2403  ret = ReadConsoleOutputCharacterA(output_handle, &read, 1, origin, &count);
2404  ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2405  ok(count == 1, "Expected count to be 1, got %u\n", count);
2406 }
2407 
2408 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle)
2409 {
2410  WCHAR read;
2411  COORD origin = {0, 0};
2412  DWORD count;
2413  BOOL ret;
2414  int i;
2415 
2416  const struct
2417  {
2418  HANDLE hConsoleOutput;
2419  LPWSTR buffer;
2420  DWORD length;
2421  COORD coord;
2422  LPDWORD read_count;
2424  DWORD last_error;
2425  int win7_crash;
2426  } invalid_table[] =
2427  {
2428  {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2429  {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2430  {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2431  {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2432  {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2433  {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2434  {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2435  {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2436  {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2438  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2439  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2440  {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2441  {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2442  {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2443  {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2444  {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2445  {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2446  {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2447  {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1},
2448  {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2449  {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2450  };
2451 
2452  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2453  {
2454  if (invalid_table[i].win7_crash)
2455  continue;
2456 
2457  SetLastError(0xdeadbeef);
2458  if (invalid_table[i].read_count) count = 0xdeadbeef;
2459  ret = ReadConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2460  invalid_table[i].buffer,
2461  invalid_table[i].length,
2462  invalid_table[i].coord,
2463  invalid_table[i].read_count);
2464  ok(!ret, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2465  if (invalid_table[i].read_count)
2466  {
2467  ok(count == invalid_table[i].expected_count,
2468  "[%d] Expected count to be %u, got %u\n",
2469  i, invalid_table[i].expected_count, count);
2470  }
2471  ok(GetLastError() == invalid_table[i].last_error,
2472  "[%d] Expected last error to be %u, got %u\n",
2473  i, invalid_table[i].last_error, GetLastError());
2474  }
2475 
2476  count = 0xdeadbeef;
2477  ret = ReadConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
2478  ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2479  ok(count == 0, "Expected count to be 0, got %u\n", count);
2480 
2481  count = 0xdeadbeef;
2482  ret = ReadConsoleOutputCharacterW(output_handle, &read, 0, origin, &count);
2483  ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2484  ok(count == 0, "Expected count to be 0, got %u\n", count);
2485 
2486  count = 0xdeadbeef;
2487  ret = ReadConsoleOutputCharacterW(output_handle, &read, 1, origin, &count);
2488  ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2489  ok(count == 1, "Expected count to be 1, got %u\n", count);
2490 }
2491 
2492 static void test_ReadConsoleOutputAttribute(HANDLE output_handle)
2493 {
2494  WORD attr;
2495  COORD origin = {0, 0};
2496  DWORD count;
2497  BOOL ret;
2498  int i;
2499 
2500  const struct
2501  {
2502  HANDLE hConsoleOutput;
2503  LPWORD lpAttribute;
2504  DWORD length;
2505  COORD coord;
2506  LPDWORD read_count;
2508  DWORD last_error;
2509  int win7_crash;
2510  } invalid_table[] =
2511  {
2512  {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2513  {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2514  {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2515  {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2516  {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2517  {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2518  {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2519  {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2520  {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2522  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2523  {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2524  {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2525  {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2526  {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2527  {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2528  {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2529  {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2530  {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2531  {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2532  {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2533  };
2534 
2535  for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2536  {
2537  if (invalid_table[i].win7_crash)
2538  continue;
2539 
2540  SetLastError(0xdeadbeef);
2541  if (invalid_table[i].read_count) count = 0xdeadbeef;
2542  ret = ReadConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2543  invalid_table[i].lpAttribute,
2544  invalid_table[i].length,
2545  invalid_table[i].coord,
2546  invalid_table[i].read_count);
2547  ok(!ret, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2548  if (invalid_table[i].read_count)
2549  {
2550  ok(count == invalid_table[i].expected_count,
2551  "[%d] Expected count to be %u, got %u\n",
2552  i, invalid_table[i].expected_count, count);
2553  }
2554  ok(GetLastError() == invalid_table[i].last_error,
2555  "[%d] Expected last error to be %u, got %u\n",
2556  i, invalid_table[i].last_error, GetLastError());
2557  }
2558 
2559  count = 0xdeadbeef;
2560  ret = ReadConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2561  ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2562  ok(count == 0, "Expected count to be 0, got %u\n", count);
2563 
2564  count = 0xdeadbeef;
2565  ret = ReadConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2566  ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2567  ok(count == 0, "Expected count to be 0, got %u\n", count);
2568 
2569  count = 0xdeadbeef;
2570  ret = ReadConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2571  ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2572  ok(count == 1, "Expected count to be 1, got %u\n", count);
2573 }
2574 
2575 static void test_ReadConsole(void)
2576 {
2577  HANDLE std_input;
2578  DWORD ret, bytes;
2579  char buf[1024];
2580 
2581  std_input = GetStdHandle(STD_INPUT_HANDLE);
2582 
2583  SetLastError(0xdeadbeef);
2584  ret = GetFileSize(std_input, NULL);
2585  if (GetLastError() == 0xdeadbeef)
2586  {
2587  skip("stdin is redirected\n");
2588  return;
2589  }
2590  ok(ret == INVALID_FILE_SIZE, "expected INVALID_FILE_SIZE, got %#x\n", ret);
2592  GetLastError() == ERROR_INVALID_FUNCTION, /* Win 8, 10 */
2593  "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2594 
2595  bytes = 0xdeadbeef;
2596  SetLastError(0xdeadbeef);
2597  ret = ReadFile(std_input, buf, -128, &bytes, NULL);
2598  ok(!ret, "expected 0, got %u\n", ret);
2600  GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */
2601  "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
2602  ok(!bytes, "expected 0, got %u\n", bytes);
2603 
2604  bytes = 0xdeadbeef;
2605  SetLastError(0xdeadbeef);
2606  ret = ReadConsoleA(std_input, buf, -128, &bytes, NULL);
2607  ok(!ret, "expected 0, got %u\n", ret);
2609  GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */
2610  "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
2611  ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
2612 
2613  bytes = 0xdeadbeef;
2614  SetLastError(0xdeadbeef);
2615  ret = ReadConsoleW(std_input, buf, -128, &bytes, NULL);
2616  ok(!ret, "expected 0, got %u\n", ret);
2618  GetLastError() == ERROR_NOACCESS, /* Win 8, 10 */
2619  "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
2620  ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
2621 }
2622 
2623 static void test_GetCurrentConsoleFont(HANDLE std_output)
2624 {
2625  BOOL ret;
2626  CONSOLE_FONT_INFO cfi;
2628  short int width, height;
2629  COORD c;
2630 
2631  memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
2632  SetLastError(0xdeadbeef);
2633  ret = GetCurrentConsoleFont(NULL, FALSE, &cfi);
2634  ok(!ret, "got %d, expected 0\n", ret);
2635  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2636  ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X);
2637  ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y);
2638 
2639  memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
2640  SetLastError(0xdeadbeef);
2641  ret = GetCurrentConsoleFont(NULL, TRUE, &cfi);
2642  ok(!ret, "got %d, expected 0\n", ret);
2643  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2644  ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X);
2645  ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y);
2646 
2647  memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
2648  SetLastError(0xdeadbeef);
2650  ok(!ret, "got %d, expected 0\n", ret);
2651  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2652  ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X);
2653  ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y);
2654 
2655  memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
2656  SetLastError(0xdeadbeef);
2658  ok(!ret, "got %d, expected 0\n", ret);
2659  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2660  ok(!cfi.dwFontSize.X, "got %d, expected 0\n", cfi.dwFontSize.X);
2661  ok(!cfi.dwFontSize.Y, "got %d, expected 0\n", cfi.dwFontSize.Y);
2662 
2663  memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
2664  SetLastError(0xdeadbeef);
2665  ret = GetCurrentConsoleFont(std_output, FALSE, &cfi);
2666  ok(ret, "got %d, expected non-zero\n", ret);
2667  ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
2668  GetConsoleScreenBufferInfo(std_output, &csbi);
2669  width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
2670  height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
2671  c = GetConsoleFontSize(std_output, cfi.nFont);
2672  ok(cfi.dwFontSize.X == width || cfi.dwFontSize.X == c.X /* Vista and higher */,
2673  "got %d, expected %d\n", cfi.dwFontSize.X, width);
2674  ok(cfi.dwFontSize.Y == height || cfi.dwFontSize.Y == c.Y /* Vista and higher */,
2675  "got %d, expected %d\n", cfi.dwFontSize.Y, height);
2676 
2677  memset(&cfi, 0, sizeof(CONSOLE_FONT_INFO));
2678  SetLastError(0xdeadbeef);
2679  ret = GetCurrentConsoleFont(std_output, TRUE, &cfi);
2680  ok(ret, "got %d, expected non-zero\n", ret);
2681  ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
2682  ok(cfi.dwFontSize.X == csbi.dwMaximumWindowSize.X,
2683  "got %d, expected %d\n", cfi.dwFontSize.X, csbi.dwMaximumWindowSize.X);
2684  ok(cfi.dwFontSize.Y == csbi.dwMaximumWindowSize.Y,
2685  "got %d, expected %d\n", cfi.dwFontSize.Y, csbi.dwMaximumWindowSize.Y);
2686 }
2687 
2688 static void test_GetConsoleFontSize(HANDLE std_output)
2689 {
2690  COORD c;
2691  DWORD index = 0;
2692  CONSOLE_FONT_INFO cfi;
2693  RECT r;
2695  LONG font_width, font_height;
2696  HMODULE hmod;
2697  DWORD (WINAPI *pGetNumberOfConsoleFonts)(void);
2698 
2699  memset(&c, 10, sizeof(COORD));
2700  SetLastError(0xdeadbeef);
2702  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2703  ok(!c.X, "got %d, expected 0\n", c.X);
2704  ok(!c.Y, "got %d, expected 0\n", c.Y);
2705 
2706  memset(&c, 10, sizeof(COORD));
2707  SetLastError(0xdeadbeef);
2709  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2710  ok(!c.X, "got %d, expected 0\n", c.X);
2711  ok(!c.Y, "got %d, expected 0\n", c.Y);
2712 
2713  GetCurrentConsoleFont(std_output, FALSE, &cfi);
2714  memset(&c, 10, sizeof(COORD));
2715  SetLastError(0xdeadbeef);
2716  c = GetConsoleFontSize(std_output, cfi.nFont);
2717  ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
2719  GetConsoleScreenBufferInfo(std_output, &csbi);
2720  font_width = (r.right - r.left + 1) / csbi.srWindow.Right;
2721  font_height = (r.bottom - r.top + 1) / csbi.srWindow.Bottom;
2722  ok(c.X == font_width, "got %d, expected %d\n", c.X, font_width);
2723  ok(c.Y == font_height, "got %d, expected %d\n", c.Y, font_height);
2724 
2725  hmod = GetModuleHandleA("kernel32.dll");
2726  pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts");
2727  if (!pGetNumberOfConsoleFonts)
2728  {
2729  win_skip("GetNumberOfConsoleFonts is not available\n");
2730  return;
2731  }
2732  index = pGetNumberOfConsoleFonts();
2733 
2734  memset(&c, 10, sizeof(COORD));
2735  SetLastError(0xdeadbeef);
2736  c = GetConsoleFontSize(std_output, index);
2737  ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
2738  ok(!c.X, "got %d, expected 0\n", c.X);
2739  ok(!c.Y, "got %d, expected 0\n", c.Y);
2740 }
2741 
2743 {
2744  COORD c, font;
2745  RECT r;
2746  LONG workarea_w, workarea_h, maxcon_w, maxcon_h;
2748  CONSOLE_FONT_INFO cfi;
2749  DWORD index, i;
2750  HMODULE hmod;
2751  BOOL ret;
2752  DWORD (WINAPI *pGetNumberOfConsoleFonts)(void);
2753  BOOL (WINAPI *pSetConsoleFont)(HANDLE, DWORD);
2754 
2755  memset(&c, 10, sizeof(COORD));
2756  SetLastError(0xdeadbeef);
2758  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2759  ok(!c.X, "got %d, expected 0\n", c.X);
2760  ok(!c.Y, "got %d, expected 0\n", c.Y);
2761 
2762  memset(&c, 10, sizeof(COORD));
2763  SetLastError(0xdeadbeef);
2765  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2766  ok(!c.X, "got %d, expected 0\n", c.X);
2767  ok(!c.Y, "got %d, expected 0\n", c.Y);
2768 
2769  SystemParametersInfoW(SPI_GETWORKAREA, 0, &r, 0);
2770  workarea_w = r.right - r.left;
2771  workarea_h = r.bottom - r.top - GetSystemMetrics(SM_CYCAPTION);
2772 
2773  GetCurrentConsoleFont(std_output, FALSE, &cfi);
2774  index = cfi.nFont; /* save current font index */
2775 
2776  hmod = GetModuleHandleA("kernel32.dll");
2777  pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts");
2778  if (!pGetNumberOfConsoleFonts)
2779  {
2780  win_skip("GetNumberOfConsoleFonts is not available\n");
2781  return;
2782  }
2783  pSetConsoleFont = (void *)GetProcAddress(hmod, "SetConsoleFont");
2784  if (!pSetConsoleFont)
2785  {
2786  win_skip("SetConsoleFont is not available\n");
2787  return;
2788  }
2789 
2790  for (i = 0; i < pGetNumberOfConsoleFonts(); i++)
2791  {
2792  pSetConsoleFont(std_output, i);
2793  memset(&c, 10, sizeof(COORD));
2794  SetLastError(0xdeadbeef);
2795  c = GetLargestConsoleWindowSize(std_output);
2796  ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
2797  GetCurrentConsoleFont(std_output, FALSE, &cfi);
2798  font = GetConsoleFontSize(std_output, cfi.nFont);
2799  maxcon_w = workarea_w / font.X;
2800  maxcon_h = workarea_h / font.Y;
2801  ok(c.X == maxcon_w || c.X == maxcon_w - 1 /* Win10 */, "got %d, expected %d\n", c.X, maxcon_w);
2802  ok(c.Y == maxcon_h || c.Y == maxcon_h - 1 /* Win10 */, "got %d, expected %d\n", c.Y, maxcon_h);
2803 
2804  ret = GetConsoleScreenBufferInfo(std_output, &sbi);
2805  ok(ret, "GetConsoleScreenBufferInfo failed %u\n", GetLastError());
2806  ok(sbi.dwMaximumWindowSize.X == min(c.X, sbi.dwSize.X), "got %d, expected %d\n",
2807  sbi.dwMaximumWindowSize.X, min(c.X, sbi.dwSize.X));
2808  ok(sbi.dwMaximumWindowSize.Y == min(c.Y, sbi.dwSize.Y), "got %d, expected %d\n",
2809  sbi.dwMaximumWindowSize.Y, min(c.Y, sbi.dwSize.Y));
2810  }
2811  pSetConsoleFont(std_output, index); /* restore original font size */
2812 }
2813 
2814 static void test_GetConsoleFontInfo(HANDLE std_output)
2815 {
2816  HANDLE hmod;
2817  BOOL (WINAPI *pGetConsoleFontInfo)(HANDLE, BOOL, DWORD, CONSOLE_FONT_INFO *);
2818  DWORD (WINAPI *pGetNumberOfConsoleFonts)(void);
2819  DWORD num_fonts, index, i;
2820  int memsize, win_width, win_height, tmp_w, tmp_h;
2821  CONSOLE_FONT_INFO *cfi;
2822  BOOL ret;
2824  COORD orig_sb_size, tmp_sb_size, orig_font, tmp_font;
2825 
2826  hmod = GetModuleHandleA("kernel32.dll");
2827  pGetConsoleFontInfo = (void *)GetProcAddress(hmod, "GetConsoleFontInfo");
2828  if (!pGetConsoleFontInfo)
2829  {
2830  win_skip("GetConsoleFontInfo is not available\n");
2831  return;
2832  }
2833 
2834  pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts");
2835  if (!pGetNumberOfConsoleFonts)
2836  {
2837  win_skip("GetNumberOfConsoleFonts is not available\n");
2838  return;
2839  }
2840 
2841  num_fonts = pGetNumberOfConsoleFonts();
2842  memsize = num_fonts * sizeof(CONSOLE_FONT_INFO);
2843  cfi = HeapAlloc(GetProcessHeap(), 0, memsize);
2844  memset(cfi, 0, memsize);
2845 
2846  GetConsoleScreenBufferInfo(std_output, &csbi);
2847  orig_sb_size = csbi.dwSize;
2848  tmp_sb_size.X = csbi.dwSize.X + 3;
2849  tmp_sb_size.Y = csbi.dwSize.Y + 5;
2850  SetConsoleScreenBufferSize(std_output, tmp_sb_size);
2851 
2852  SetLastError(0xdeadbeef);
2853  ret = pGetConsoleFontInfo(NULL, FALSE, 0, cfi);
2854  ok(!ret, "got %d, expected zero\n", ret);
2855  todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2856 
2857  SetLastError(0xdeadbeef);
2858  ret = pGetConsoleFontInfo(GetStdHandle(STD_INPUT_HANDLE), FALSE, 0, cfi);
2859  ok(!ret, "got %d, expected zero\n", ret);
2860  todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2861 
2862  SetLastError(0xdeadbeef);
2863  ret = pGetConsoleFontInfo(std_output, FALSE, 0, cfi);
2864  ok(!ret, "got %d, expected zero\n", ret);
2865  todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
2866 
2867  GetConsoleScreenBufferInfo(std_output, &csbi);
2868  win_width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
2869  win_height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
2870 
2871  GetCurrentConsoleFont(std_output, FALSE, &cfi[0]);
2872  index = cfi[0].nFont;
2873  orig_font = GetConsoleFontSize(std_output, index);
2874 
2875  memset(cfi, 0, memsize);
2876  ret = pGetConsoleFontInfo(std_output, FALSE, num_fonts, cfi);
2877  todo_wine ok(ret, "got %d, expected non-zero\n", ret);
2878 
2879  todo_wine ok(cfi[index].dwFontSize.X == win_width, "got %d, expected %d\n",
2880  cfi[index].dwFontSize.X, win_width);
2881  todo_wine ok(cfi[index].dwFontSize.Y == win_height, "got %d, expected %d\n",
2882  cfi[index].dwFontSize.Y, win_height);
2883 
2884  for (i = 0; i < num_fonts; i++)
2885  {
2886  ok(cfi[i].nFont == i, "element out of order, got nFont %d, expected %d\n", cfi[i].nFont, i);
2887  tmp_font = GetConsoleFontSize(std_output, cfi[i].nFont);
2888  tmp_w = (double)orig_font.X / tmp_font.X * win_width;
2889  tmp_h = (double)orig_font.Y / tmp_font.Y * win_height;
2890  todo_wine ok(cfi[i].dwFontSize.X == tmp_w, "got %d, expected %d\n", cfi[i].dwFontSize.X, tmp_w);
2891  todo_wine ok(cfi[i].dwFontSize.Y == tmp_h, "got %d, expected %d\n", cfi[i].dwFontSize.Y, tmp_h);
2892  }
2893 
2894  SetLastError(0xdeadbeef);
2895  ret = pGetConsoleFontInfo(NULL, TRUE, 0, cfi);
2896  ok(!ret, "got %d, expected zero\n", ret);
2897  todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2898 
2899  SetLastError(0xdeadbeef);
2900  ret = pGetConsoleFontInfo(GetStdHandle(STD_INPUT_HANDLE), TRUE, 0, cfi);
2901  ok(!ret, "got %d, expected zero\n", ret);
2902  todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2903 
2904  SetLastError(0xdeadbeef);
2905  ret = pGetConsoleFontInfo(std_output, TRUE, 0, cfi);
2906  ok(!ret, "got %d, expected zero\n", ret);
2907  todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
2908 
2909  memset(cfi, 0, memsize);
2910  ret = pGetConsoleFontInfo(std_output, TRUE, num_fonts, cfi);
2911  todo_wine ok(ret, "got %d, expected non-zero\n", ret);
2912 
2913  todo_wine ok(cfi[index].dwFontSize.X == csbi.dwMaximumWindowSize.X, "got %d, expected %d\n",
2914  cfi[index].dwFontSize.X, csbi.dwMaximumWindowSize.X);
2915  todo_wine ok(cfi[index].dwFontSize.Y == csbi.dwMaximumWindowSize.Y, "got %d, expected %d\n",
2916  cfi[index].dwFontSize.Y, csbi.dwMaximumWindowSize.Y);
2917 
2918  for (i = 0; i < num_fonts; i++)
2919  {
2920  ok(cfi[i].nFont == i, "element out of order, got nFont %d, expected %d\n", cfi[i].nFont, i);
2921  tmp_font = GetConsoleFontSize(std_output, cfi[i].nFont);
2922  tmp_w = (double)orig_font.X / tmp_font.X * csbi.dwMaximumWindowSize.X;
2923  tmp_h = (double)orig_font.Y / tmp_font.Y * csbi.dwMaximumWindowSize.Y;
2924  todo_wine ok(cfi[i].dwFontSize.X == tmp_w, "got %d, expected %d\n", cfi[i].dwFontSize.X, tmp_w);
2925  todo_wine ok(cfi[i].dwFontSize.Y == tmp_h, "got %d, expected %d\n", cfi[i].dwFontSize.Y, tmp_h);
2926  }
2927 
2928  HeapFree(GetProcessHeap(), 0, cfi);
2929  SetConsoleScreenBufferSize(std_output, orig_sb_size);
2930 }
2931 
2932 static void test_SetConsoleFont(HANDLE std_output)
2933 {
2934  HANDLE hmod;
2935  BOOL (WINAPI *pSetConsoleFont)(HANDLE, DWORD);
2936  BOOL ret;
2937  DWORD (WINAPI *pGetNumberOfConsoleFonts)(void);
2938  DWORD num_fonts;
2939 
2940  hmod = GetModuleHandleA("kernel32.dll");
2941  pSetConsoleFont = (void *)GetProcAddress(hmod, "SetConsoleFont");
2942  if (!pSetConsoleFont)
2943  {
2944  win_skip("SetConsoleFont is not available\n");
2945  return;
2946  }
2947 
2948  SetLastError(0xdeadbeef);
2949  ret = pSetConsoleFont(NULL, 0);
2950  ok(!ret, "got %d, expected zero\n", ret);
2951  todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2952 
2953  SetLastError(0xdeadbeef);
2954  ret = pSetConsoleFont(GetStdHandle(STD_INPUT_HANDLE), 0);
2955  ok(!ret, "got %d, expected zero\n", ret);
2956  todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
2957 
2958  pGetNumberOfConsoleFonts = (void *)GetProcAddress(hmod, "GetNumberOfConsoleFonts");
2959  if (!pGetNumberOfConsoleFonts)
2960  {
2961  win_skip("GetNumberOfConsoleFonts is not available\n");
2962  return;
2963  }
2964 
2965  num_fonts = pGetNumberOfConsoleFonts();
2966 
2967  SetLastError(0xdeadbeef);
2968  ret = pSetConsoleFont(std_output, num_fonts);
2969  ok(!ret, "got %d, expected zero\n", ret);
2970  todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
2971 }
2972 
2974 {
2975  HANDLE hmod;
2976  BOOL (WINAPI *pGetConsoleScreenBufferInfoEx)(HANDLE, CONSOLE_SCREEN_BUFFER_INFOEX *);
2977  CONSOLE_SCREEN_BUFFER_INFOEX csbix;
2978  BOOL ret;
2979  HANDLE std_input = GetStdHandle(STD_INPUT_HANDLE);
2980 
2981  hmod = GetModuleHandleA("kernel32.dll");
2982  pGetConsoleScreenBufferInfoEx = (void *)GetProcAddress(hmod, "GetConsoleScreenBufferInfoEx");
2983  if (!pGetConsoleScreenBufferInfoEx)
2984  {
2985  win_skip("GetConsoleScreenBufferInfoEx is not available\n");
2986  return;
2987  }
2988 
2989  SetLastError(0xdeadbeef);
2990  ret = pGetConsoleScreenBufferInfoEx(NULL, &csbix);
2991  ok(!ret, "got %d, expected zero\n", ret);
2992  ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
2993 
2994  SetLastError(0xdeadbeef);
2995  ret = pGetConsoleScreenBufferInfoEx(std_input, &csbix);
2996  ok(!ret, "got %d, expected zero\n", ret);
2997  ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
2998 
2999  SetLastError(0xdeadbeef);
3000  ret = pGetConsoleScreenBufferInfoEx(std_output, &csbix);
3001  ok(!ret, "got %d, expected zero\n", ret);
3002  ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError());
3003 
3004  csbix.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
3005 
3006  SetLastError(0xdeadbeef);
3007  ret = pGetConsoleScreenBufferInfoEx(NULL, &csbix);
3008  ok(!ret, "got %d, expected zero\n", ret);
3009  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
3010 
3011  SetLastError(0xdeadbeef);
3012  ret = pGetConsoleScreenBufferInfoEx(std_input, &csbix);
3013  ok(!ret, "got %d, expected zero\n", ret);
3014  ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError());
3015 
3016  SetLastError(0xdeadbeef);
3017  ret = pGetConsoleScreenBufferInfoEx(std_output, &csbix);
3018  ok(ret, "got %d, expected non-zero\n", ret);
3019  ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError());
3020 }
3021 
3022 START_TEST(console)
3023 {
3024  static const char font_name[] = "Lucida Console";
3025  HANDLE hConIn, hConOut;
3026  BOOL ret;
3028  LONG err;
3029  HKEY console_key;
3030  char old_font[LF_FACESIZE];
3031  BOOL delete = FALSE;
3032  DWORD size;
3033 
3035 
3036  /* be sure we have a clean console (and that's our own)
3037  * FIXME: this will make the test fail (currently) if we don't run
3038  * under X11
3039  * Another solution would be to rerun the test under wineconsole with
3040  * the curses backend
3041  */
3042 
3043  /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
3044  * correctly for characters that don't have a glyph in the console font. So,
3045  * we first set the console font to Lucida Console (which has a wider
3046  * selection of glyphs available than the default raster fonts). We want
3047  * to be able to restore the original font afterwards, so don't change
3048  * if we can't read the original font.
3049  */
3050  err = RegOpenKeyExA(HKEY_CURRENT_USER, "Console", 0,
3051  KEY_QUERY_VALUE | KEY_SET_VALUE, &console_key);
3052  if (err == ERROR_SUCCESS)
3053  {
3054  size = sizeof(old_font);
3055  err = RegQueryValueExA(console_key, "FaceName", NULL, NULL,
3056  (LPBYTE) old_font, &size);
3058  {
3059  delete = (err == ERROR_FILE_NOT_FOUND);
3060  err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
3061  (const BYTE *) font_name, sizeof(font_name));
3062  if (err != ERROR_SUCCESS)
3063  trace("Unable to change default console font, error %d\n", err);
3064  }
3065  else
3066  {
3067  trace("Unable to query default console font, error %d\n", err);
3068  RegCloseKey(console_key);
3069  console_key = NULL;
3070  }
3071  }
3072  else
3073  {
3074  trace("Unable to open HKCU\\Console, error %d\n", err);
3075  console_key = NULL;
3076  }
3077 
3078  /* Now detach and open a fresh console to play with */
3079  FreeConsole();
3080  ok(AllocConsole(), "Couldn't alloc console\n");
3081 
3082  /* Restore default console font if needed */
3083  if (console_key != NULL)
3084  {
3085  if (delete)
3086  err = RegDeleteValueA(console_key, "FaceName");
3087  else
3088  err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
3089  (const BYTE *) old_font, strlen(old_font) + 1);
3090  ok(err == ERROR_SUCCESS, "Unable to restore default console font, error %d\n", err);
3091  }
3092  hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3093  hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3094 
3095  /* now verify everything's ok */
3096  ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
3097  ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
3098 
3099  ret = GetConsoleScreenBufferInfo(hConOut, &sbi);
3100  ok(ret, "Getting sb info\n");
3101  if (!ret) return;
3102 
3103  /* Reduce the size of the buffer to the visible area plus 3 lines to speed
3104  * up the tests.
3105  */
3106  trace("Visible area: %dx%d - %dx%d Buffer size: %dx%d\n", sbi.srWindow.Left, sbi.srWindow.Top, sbi.srWindow.Right, sbi.srWindow.Bottom, sbi.dwSize.X, sbi.dwSize.Y);
3107  sbi.dwSize.Y = size = (sbi.srWindow.Bottom + 1) + 3;
3108  ret = SetConsoleScreenBufferSize(hConOut, sbi.dwSize);
3109  ok(ret, "Setting sb info\n");
3110  ret = GetConsoleScreenBufferInfo(hConOut, &sbi);
3111  ok(ret, "Getting sb info\n");
3112  ok(sbi.dwSize.Y == size, "Unexpected buffer size: %d instead of %d\n", sbi.dwSize.Y, size);
3113  if (!ret) return;
3114 
3115  test_ReadConsole();
3116  /* Non interactive tests */
3117  testCursor(hConOut, sbi.dwSize);
3118  /* test parameters (FIXME: test functionality) */
3119  testCursorInfo(hConOut);
3120  /* will test wrapped (on/off) & processed (on/off) strings output */
3121  testWrite(hConOut, sbi.dwSize);
3122  /* will test line scrolling at the bottom of the screen */
3123  /* testBottomScroll(); */
3124  /* will test all the scrolling operations */
3125  testScroll(hConOut, sbi.dwSize);
3126  /* will test sb creation / modification / codepage handling */
3127  testScreenBuffer(hConOut);
3128  /* Test waiting for a console handle */
3129  testWaitForConsoleInput(hConIn);
3130 
3131  /* clear duplicated console font table */
3132  CloseHandle(hConIn);
3133  CloseHandle(hConOut);
3134  FreeConsole();
3135  ok(AllocConsole(), "Couldn't alloc console\n");
3136  hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3137  hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
3138  ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
3139  ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
3140 
3141  testCtrlHandler();
3142  /* still to be done: access rights & access on objects */
3143 
3144  if (!pGetConsoleInputExeNameA || !pSetConsoleInputExeNameA)
3145  win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
3146  else
3148 
3151  test_CreateFileW();
3152  test_OpenCON();
3153  test_VerifyConsoleIoHandle(hConOut);
3156  test_WriteConsoleInputA(hConIn);
3157  test_WriteConsoleInputW(hConIn);
3167  test_GetCurrentConsoleFont(hConOut);
3168  test_GetConsoleFontSize(hConOut);
3170  test_GetConsoleFontInfo(hConOut);
3171  test_SetConsoleFont(hConOut);
3173 }
static void test_GetConsoleScreenBufferInfoEx(HANDLE std_output)
Definition: console.c:2973
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static void test_GetCurrentConsoleFont(HANDLE std_output)
Definition: console.c:2623
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4023
DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleInputExeNameA(IN DWORD nBufferLength, OUT LPSTR lpExeName)
Definition: console.c:2945
static void test_ReadConsoleOutputCharacterA(HANDLE output_handle)
Definition: console.c:2324
#define trace(...)
Definition: kmt_test.h:217
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3835
GLint GLint GLsizei width
Definition: gl.h:1546
BOOL WINAPI SetConsoleOutputCP(IN UINT wCodepage)
Definition: console.c:644
static BOOL
Definition: console.c:28
#define GENERIC_ALL
Definition: nt_native.h:92
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
BOOL WINAPI AllocConsole(VOID)
Definition: console.c:48
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
#define CloseHandle
Definition: compat.h:398
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
#define LF_FACESIZE
Definition: dimm.idl:39
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
BOOL WINAPI FillConsoleOutputAttribute(IN HANDLE hConsoleOutput, IN WORD wAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten)
Definition: console.c:474
static void test_GetConsoleFontInfo(HANDLE std_output)
Definition: console.c:2814
#define ERROR_SUCCESS
Definition: deptool.c:10
static void test_WriteConsoleOutputCharacterA(HANDLE output_handle)
Definition: console.c:1891
#define error(str)
Definition: mkdosfs.c:1605
#define KEY_SET_VALUE
Definition: nt_native.h:1017
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
static HANDLE(WINAPI *pOpenConsoleW)(LPCWSTR
static HANDLE complete_event
Definition: url.c:178
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
Definition: mk_font.cpp:20
#define ERROR_BUFFER_OVERFLOW
Definition: winerror.h:185
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define HKEY_CURRENT_USER
Definition: winreg.h:11
WCHAR UnicodeChar
Definition: wincon.h:169
char CHAR
Definition: xmlstorage.h:175
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1571
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
static const WCHAR invalidW[]
Definition: locale.c:46
#define CALLBACK