5928e8c7ea708ae9629d3395ecdcf5d9f9e7ffe9
[reactos.git] / rostests / winetests / kernel32 / console.c
1 /*
2 * Unit tests for console API
3 *
4 * Copyright (c) 2003,2004 Eric Pouech
5 * Copyright (c) 2007 Kirill K. Smirnov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "wine/test.h"
23 #include <windows.h>
24 #include <stdio.h>
25
26 static BOOL (WINAPI *pGetConsoleInputExeNameA)(DWORD, LPSTR);
27 static DWORD (WINAPI *pGetConsoleProcessList)(LPDWORD, DWORD);
28 static HANDLE (WINAPI *pOpenConsoleW)(LPCWSTR,DWORD,BOOL,DWORD);
29 static BOOL (WINAPI *pSetConsoleInputExeNameA)(LPCSTR);
30 static BOOL (WINAPI *pVerifyConsoleIoHandle)(HANDLE handle);
31
32 /* DEFAULT_ATTRIB is used for all initial filling of the console.
33 * all modifications are made with TEST_ATTRIB so that we could check
34 * what has to be modified or not
35 */
36 #define TEST_ATTRIB (BACKGROUND_BLUE | FOREGROUND_GREEN)
37 #define DEFAULT_ATTRIB (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED)
38 /* when filling the screen with non-blank chars, this macro defines
39 * what character should be at position 'c'
40 */
41 #define CONTENT(c) ('A' + (((c).Y * 17 + (c).X) % 23))
42
43 #define okCURSOR(hCon, c) do { \
44 CONSOLE_SCREEN_BUFFER_INFO __sbi; \
45 BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
46 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
47 ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
48 (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
49 } while (0)
50
51 #define okCHAR(hCon, c, ch, attr) do { \
52 char __ch; WORD __attr; DWORD __len; BOOL expect; \
53 expect = 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");
68 KERNEL32_GET_PROC(GetConsoleInputExeNameA);
69 KERNEL32_GET_PROC(GetConsoleProcessList);
70 KERNEL32_GET_PROC(OpenConsoleW);
71 KERNEL32_GET_PROC(SetConsoleInputExeNameA);
72 KERNEL32_GET_PROC(VerifyConsoleIoHandle);
73
74 #undef KERNEL32_GET_PROC
75 }
76
77 /* FIXME: this could be optimized on a speed point of view */
78 static void resetContent(HANDLE hCon, COORD sbSize, BOOL content)
79 {
80 COORD c;
81 WORD attr = DEFAULT_ATTRIB;
82 char ch;
83 DWORD len;
84
85 for (c.X = 0; c.X < sbSize.X; c.X++)
86 {
87 for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
88 {
89 ch = (content) ? CONTENT(c) : ' ';
90 WriteConsoleOutputAttribute(hCon, &attr, 1, c, &len);
91 WriteConsoleOutputCharacterA(hCon, &ch, 1, c, &len);
92 }
93 }
94 }
95
96 static void testCursor(HANDLE hCon, COORD sbSize)
97 {
98 COORD c;
99
100 c.X = c.Y = 0;
101 ok(SetConsoleCursorPosition(0, c) == 0, "No handle\n");
102 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
103 ERROR_INVALID_HANDLE, GetLastError());
104
105 c.X = c.Y = 0;
106 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
107 okCURSOR(hCon, c);
108
109 c.X = sbSize.X - 1;
110 c.Y = sbSize.Y - 1;
111 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in lower-right\n");
112 okCURSOR(hCon, c);
113
114 c.X = sbSize.X;
115 c.Y = sbSize.Y - 1;
116 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
117 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n",
118 ERROR_INVALID_PARAMETER, GetLastError());
119
120 c.X = sbSize.X - 1;
121 c.Y = sbSize.Y;
122 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
123 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n",
124 ERROR_INVALID_PARAMETER, GetLastError());
125
126 c.X = -1;
127 c.Y = 0;
128 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
129 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n",
130 ERROR_INVALID_PARAMETER, GetLastError());
131
132 c.X = 0;
133 c.Y = -1;
134 ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
135 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %u\n",
136 ERROR_INVALID_PARAMETER, GetLastError());
137 }
138
139 static void testCursorInfo(HANDLE hCon)
140 {
141 BOOL ret;
142 CONSOLE_CURSOR_INFO info;
143
144 SetLastError(0xdeadbeef);
145 ret = GetConsoleCursorInfo(NULL, NULL);
146 ok(!ret, "Expected failure\n");
147 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
148 ERROR_INVALID_HANDLE, GetLastError());
149
150 SetLastError(0xdeadbeef);
151 info.dwSize = -1;
152 ret = GetConsoleCursorInfo(NULL, &info);
153 ok(!ret, "Expected failure\n");
154 ok(info.dwSize == -1, "Expected no change for dwSize\n");
155 ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n",
156 ERROR_INVALID_HANDLE, GetLastError());
157
158 /* Test the correct call first to distinguish between win9x and the rest */
159 SetLastError(0xdeadbeef);
160 ret = GetConsoleCursorInfo(hCon, &info);
161 ok(ret, "Expected success\n");
162 ok(info.dwSize == 25 ||
163 info.dwSize == 12 /* win9x */,
164 "Expected 12 or 25, got %d\n", info.dwSize);
165 ok(info.bVisible, "Expected the cursor to be visible\n");
166 ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %u\n",
167 0xdeadbeef, GetLastError());
168
169 /* Don't test NULL CONSOLE_CURSOR_INFO, it crashes on win9x and win7 */
170 }
171
172 static void testEmptyWrite(HANDLE hCon)
173 {
174 static const char emptybuf[16];
175 COORD c;
176 DWORD len;
177
178 c.X = c.Y = 0;
179 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
180
181 len = -1;
182 ok(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
233 static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize)
234 {
235 COORD c;
236 DWORD len, mode;
237 const char* mytest = "123";
238 const int mylen = strlen(mytest);
239 int ret;
240 int p;
241
242 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode & ~(ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT)),
243 "clearing wrap at EOL & processed output\n");
244
245 /* write line, wrapping disabled, buffer exceeds sb width */
246 c.X = sbSize.X - 3; c.Y = 0;
247 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
248
249 ret = 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
281 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, (mode | ENABLE_PROCESSED_OUTPUT) & ~ENABLE_WRAP_AT_EOL_OUTPUT),
282 "clearing wrap at EOL & setting processed output\n");
283
284 /* write line, wrapping disabled, buffer exceeds sb width */
285 c.X = sbSize.X - 5; c.Y = 0;
286 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-5\n");
287
288 ok(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
365 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon,(mode | ENABLE_WRAP_AT_EOL_OUTPUT) & ~(ENABLE_PROCESSED_OUTPUT)),
366 "setting wrap at EOL & clearing processed output\n");
367
368 /* write line, wrapping enabled, buffer doesn't exceed sb width */
369 c.X = sbSize.X - 9; c.Y = 0;
370 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n");
371
372 ok(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
402 ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode | (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)),
403 "setting wrap at EOL & processed output\n");
404
405 /* write line, wrapping enabled, buffer doesn't exceed sb width */
406 c.X = sbSize.X - 9; c.Y = 0;
407 ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n");
408
409 ok(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 */
599 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY,
600 "Expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
601 }
602
603 /* clipping, src & dst rect do overlap */
604 resetContent(hCon, sbSize, TRUE);
605
606 scroll.Left = 0;
607 scroll.Right = W - 1;
608 scroll.Top = 0;
609 scroll.Bottom = H - 1;
610 dst.X = W / 2 - 3;
611 dst.Y = H / 2 - 3;
612 ci.Char.UnicodeChar = '#';
613 ci.Attributes = TEST_ATTRIB;
614
615 clip.Left = W / 2;
616 clip.Right = min(W + W / 2, sbSize.X - 1);
617 clip.Top = H / 2;
618 clip.Bottom = min(H + H / 2, sbSize.Y - 1);
619
620 ok(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 */
644 static HANDLE mch_event;
645 static BOOL WINAPI mch(DWORD event)
646 {
647 mch_count++;
648 SetEvent(mch_event);
649 return TRUE;
650 }
651
652 static void testCtrlHandler(void)
653 {
654 ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n");
655 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %u\n", GetLastError());
656 ok(SetConsoleCtrlHandler(mch, TRUE), "Couldn't set handler\n");
657 /* wine requires the event for the test, as we cannot ensure, so far, that
658 * events are processed synchronously in GenerateConsoleCtrlEvent()
659 */
660 mch_event = CreateEventA(NULL, TRUE, FALSE, NULL);
661 mch_count = 0;
662 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n");
663 /* FIXME: it isn't synchronous on wine but it can still happen before we test */
664 if (0) ok(mch_count == 1, "Event isn't synchronous\n");
665 ok(WaitForSingleObject(mch_event, 3000) == WAIT_OBJECT_0, "event sending didn't work\n");
666 CloseHandle(mch_event);
667
668 /* Turning off ctrl-c handling doesn't work on win9x such way ... */
669 ok(SetConsoleCtrlHandler(NULL, TRUE), "Couldn't turn off ctrl-c handling\n");
670 mch_event = CreateEventA(NULL, TRUE, FALSE, NULL);
671 mch_count = 0;
672 if(!(GetVersion() & 0x80000000))
673 /* ... and next line leads to an unhandled exception on 9x. Avoid it on 9x. */
674 ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n");
675 ok(WaitForSingleObject(mch_event, 3000) == WAIT_TIMEOUT && mch_count == 0, "Event shouldn't have been sent\n");
676 CloseHandle(mch_event);
677 ok(SetConsoleCtrlHandler(mch, FALSE), "Couldn't remove handler\n");
678 ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n");
679 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %u\n", GetLastError());
680 }
681
682 /*
683 * Test console screen buffer:
684 * 1) Try to set invalid handle.
685 * 2) Try to set non-console handles.
686 * 3) Use CONOUT$ file as active SB.
687 * 4) Test cursor.
688 * 5) Test output codepage to show it is not a property of SB.
689 * 6) Test switching to old SB if we close all handles to current SB - works
690 * in Windows, TODO in wine.
691 *
692 * What is not tested but should be:
693 * 1) ScreenBufferInfo
694 */
695 static void testScreenBuffer(HANDLE hConOut)
696 {
697 HANDLE hConOutRW, hConOutRO, hConOutWT;
698 HANDLE hFileOutRW, hFileOutRO, hFileOutWT;
699 HANDLE hConOutNew;
700 char test_str1[] = "Test for SB1";
701 char test_str2[] = "Test for SB2";
702 char test_cp866[] = {0xe2, 0xa5, 0xe1, 0xe2, 0};
703 char test_cp1251[] = {0xf2, 0xe5, 0xf1, 0xf2, 0};
704 WCHAR test_unicode[] = {0x0442, 0x0435, 0x0441, 0x0442, 0};
705 WCHAR str_wbuf[20];
706 char str_buf[20];
707 DWORD len, 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);
722 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
723 {
724 win_skip("SetConsoleOutputCP is not implemented\n");
725 return;
726 }
727 ok(ret, "Cannot set output codepage to 866\n");
728
729 hConOutRW = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
730 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
731 CONSOLE_TEXTMODE_BUFFER, NULL);
732 ok(hConOutRW != INVALID_HANDLE_VALUE,
733 "Cannot create a new screen buffer for ReadWrite\n");
734 hConOutRO = CreateConsoleScreenBuffer(GENERIC_READ,
735 FILE_SHARE_READ, NULL,
736 CONSOLE_TEXTMODE_BUFFER, NULL);
737 ok(hConOutRO != INVALID_HANDLE_VALUE,
738 "Cannot create a new screen buffer for ReadOnly\n");
739 hConOutWT = CreateConsoleScreenBuffer(GENERIC_WRITE,
740 FILE_SHARE_WRITE, NULL,
741 CONSOLE_TEXTMODE_BUFFER, NULL);
742 ok(hConOutWT != INVALID_HANDLE_VALUE,
743 "Cannot create a new screen buffer for WriteOnly\n");
744
745 hFileOutRW = CreateFileA("NUL", GENERIC_READ | GENERIC_WRITE,
746 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
747 OPEN_EXISTING, 0, NULL);
748 ok(hFileOutRW != INVALID_HANDLE_VALUE, "Cannot open NUL for ReadWrite\n");
749 hFileOutRO = CreateFileA("NUL", GENERIC_READ, FILE_SHARE_READ,
750 NULL, OPEN_EXISTING, 0, NULL);
751 ok(hFileOutRO != INVALID_HANDLE_VALUE, "Cannot open NUL for ReadOnly\n");
752 hFileOutWT = CreateFileA("NUL", GENERIC_WRITE, FILE_SHARE_WRITE,
753 NULL, OPEN_EXISTING, 0, NULL);
754 ok(hFileOutWT != INVALID_HANDLE_VALUE, "Cannot open NUL for WriteOnly\n");
755
756 /* Trying to set invalid handle */
757 SetLastError(0);
758 ok(!SetConsoleActiveScreenBuffer(INVALID_HANDLE_VALUE),
759 "Shouldn't succeed\n");
760 ok(GetLastError() == ERROR_INVALID_HANDLE,
761 "GetLastError: expecting %u got %u\n",
762 ERROR_INVALID_HANDLE, GetLastError());
763
764 /* Trying to set non-console handles */
765 SetLastError(0);
766 ok(!SetConsoleActiveScreenBuffer(hFileOutRW), "Shouldn't succeed\n");
767 ok(GetLastError() == ERROR_INVALID_HANDLE,
768 "GetLastError: expecting %u got %u\n",
769 ERROR_INVALID_HANDLE, GetLastError());
770
771 SetLastError(0);
772 ok(!SetConsoleActiveScreenBuffer(hFileOutRO), "Shouldn't succeed\n");
773 ok(GetLastError() == ERROR_INVALID_HANDLE,
774 "GetLastError: expecting %u got %u\n",
775 ERROR_INVALID_HANDLE, GetLastError());
776
777 SetLastError(0);
778 ok(!SetConsoleActiveScreenBuffer(hFileOutWT), "Shouldn't succeed\n");
779 ok(GetLastError() == ERROR_INVALID_HANDLE,
780 "GetLastError: expecting %u got %u\n",
781 ERROR_INVALID_HANDLE, GetLastError());
782
783 /* trying to write non-console handle */
784 SetLastError(0xdeadbeef);
785 ret = WriteConsoleA(hFileOutRW, test_str1, lstrlenA(test_str1), &len, NULL);
786 error = GetLastError();
787 ok(!ret, "Shouldn't succeed\n");
788 ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION,
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");
795 ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION,
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");
802 todo_wine ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION,
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");
812 ok(GetLastError() == ERROR_INVALID_HANDLE,
813 "GetLastError: expecting %u got %u\n",
814 ERROR_INVALID_HANDLE, GetLastError());
815
816 ok(SetConsoleActiveScreenBuffer(hConOutWT), "Couldn't set new WriteOnly SB\n");
817
818 ok(SetConsoleActiveScreenBuffer(hConOutRW), "Couldn't set new ReadWrite SB\n");
819
820 CloseHandle(hConOutWT);
821 CloseHandle(hConOutRO);
822
823 /* Now we have two ReadWrite SB, active must be hConOutRW */
824 /* Open current SB via CONOUT$ */
825 hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0,
826 NULL, OPEN_EXISTING, 0, 0);
827 ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n");
828
829
830 /* test cursor */
831 c.X = c.Y = 10;
832 SetConsoleCursorPosition(hConOut, c);
833 c.X = c.Y = 5;
834 SetConsoleCursorPosition(hConOutRW, c);
835 okCURSOR(hConOutNew, c);
836 c.X = c.Y = 10;
837 okCURSOR(hConOut, c);
838
839
840 c.X = c.Y = 0;
841
842 /* Write using hConOutNew... */
843 SetConsoleCursorPosition(hConOutNew, c);
844 ret = WriteConsoleA(hConOutNew, test_str2, lstrlenA(test_str2), &len, NULL);
845 ok (ret && len == lstrlenA(test_str2), "WriteConsoleA failed\n");
846 /* ... and read it back via hConOutRW */
847 ret = ReadConsoleOutputCharacterA(hConOutRW, str_buf, lstrlenA(test_str2), c, &len);
848 ok(ret && len == lstrlenA(test_str2), "ReadConsoleOutputCharacterA failed\n");
849 str_buf[lstrlenA(test_str2)] = 0;
850 ok(!lstrcmpA(str_buf, test_str2), "got '%s' expected '%s'\n", str_buf, test_str2);
851
852
853 /* Now test output codepage handling. Current is 866 as we set earlier. */
854 SetConsoleCursorPosition(hConOutRW, c);
855 ret = WriteConsoleA(hConOutRW, test_cp866, lstrlenA(test_cp866), &len, NULL);
856 ok(ret && len == lstrlenA(test_cp866), "WriteConsoleA failed\n");
857 ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp866), c, &len);
858 ok(ret && len == lstrlenA(test_cp866), "ReadConsoleOutputCharacterW failed\n");
859 str_wbuf[lstrlenA(test_cp866)] = 0;
860 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
861
862 /*
863 * cp866 is OK, let's switch to cp1251.
864 * We expect that this codepage will be used in every SB - active and not.
865 */
866 ok(SetConsoleOutputCP(1251), "Cannot set output cp to 1251\n");
867 SetConsoleCursorPosition(hConOutRW, c);
868 ret = WriteConsoleA(hConOutRW, test_cp1251, lstrlenA(test_cp1251), &len, NULL);
869 ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n");
870 ret = ReadConsoleOutputCharacterW(hConOutRW, str_wbuf, lstrlenA(test_cp1251), c, &len);
871 ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n");
872 str_wbuf[lstrlenA(test_cp1251)] = 0;
873 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
874
875 /* Check what has happened to hConOut. */
876 SetConsoleCursorPosition(hConOut, c);
877 ret = WriteConsoleA(hConOut, test_cp1251, lstrlenA(test_cp1251), &len, NULL);
878 ok(ret && len == lstrlenA(test_cp1251), "WriteConsoleA failed\n");
879 ret = ReadConsoleOutputCharacterW(hConOut, str_wbuf, lstrlenA(test_cp1251), c, &len);
880 ok(ret && len == lstrlenA(test_cp1251), "ReadConsoleOutputCharacterW failed\n");
881 str_wbuf[lstrlenA(test_cp1251)] = 0;
882 ok(!lstrcmpW(str_wbuf, test_unicode), "string does not match the pattern\n");
883
884 /* Close all handles of current console SB */
885 CloseHandle(hConOutNew);
886 CloseHandle(hConOutRW);
887
888 /* Now active SB should be hConOut */
889 hConOutNew = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0,
890 NULL, OPEN_EXISTING, 0, 0);
891 ok(hConOutNew != INVALID_HANDLE_VALUE, "CONOUT$ is not opened\n");
892
893 /* Write using hConOutNew... */
894 SetConsoleCursorPosition(hConOutNew, c);
895 ret = WriteConsoleA(hConOutNew, test_str1, lstrlenA(test_str1), &len, NULL);
896 ok (ret && len == lstrlenA(test_str1), "WriteConsoleA failed\n");
897 /* ... and read it back via hConOut */
898 ret = ReadConsoleOutputCharacterA(hConOut, str_buf, lstrlenA(test_str1), c, &len);
899 ok(ret && len == lstrlenA(test_str1), "ReadConsoleOutputCharacterA failed\n");
900 str_buf[lstrlenA(test_str1)] = 0;
901 todo_wine ok(!lstrcmpA(str_buf, test_str1), "got '%s' expected '%s'\n", str_buf, test_str1);
902 CloseHandle(hConOutNew);
903
904 /* This is not really needed under Windows */
905 SetConsoleActiveScreenBuffer(hConOut);
906
907 /* restore codepage */
908 SetConsoleOutputCP(oldcp);
909 }
910
911 static void test_GetSetConsoleInputExeName(void)
912 {
913 BOOL ret;
914 DWORD error;
915 char buffer[MAX_PATH], module[MAX_PATH], *p;
916 static char input_exe[MAX_PATH] = "winetest.exe";
917
918 SetLastError(0xdeadbeef);
919 ret = pGetConsoleInputExeNameA(0, NULL);
920 error = GetLastError();
921 ok(ret, "GetConsoleInputExeNameA failed\n");
922 ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
923
924 SetLastError(0xdeadbeef);
925 ret = pGetConsoleInputExeNameA(0, buffer);
926 error = GetLastError();
927 ok(ret, "GetConsoleInputExeNameA failed\n");
928 ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
929
930 GetModuleFileNameA(GetModuleHandleA(NULL), module, sizeof(module));
931 p = strrchr(module, '\\') + 1;
932
933 ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
934 ok(ret, "GetConsoleInputExeNameA failed\n");
935 todo_wine ok(!lstrcmpA(buffer, p), "got %s expected %s\n", buffer, p);
936
937 SetLastError(0xdeadbeef);
938 ret = pSetConsoleInputExeNameA(NULL);
939 error = GetLastError();
940 ok(!ret, "SetConsoleInputExeNameA failed\n");
941 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
942
943 SetLastError(0xdeadbeef);
944 ret = pSetConsoleInputExeNameA("");
945 error = GetLastError();
946 ok(!ret, "SetConsoleInputExeNameA failed\n");
947 ok(error == ERROR_INVALID_PARAMETER, "got %u expected ERROR_INVALID_PARAMETER\n", error);
948
949 ret = pSetConsoleInputExeNameA(input_exe);
950 ok(ret, "SetConsoleInputExeNameA failed\n");
951
952 ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
953 ok(ret, "GetConsoleInputExeNameA failed\n");
954 ok(!lstrcmpA(buffer, input_exe), "got %s expected %s\n", buffer, input_exe);
955 }
956
957 static void test_GetConsoleProcessList(void)
958 {
959 DWORD ret, *list = NULL;
960
961 if (!pGetConsoleProcessList)
962 {
963 win_skip("GetConsoleProcessList is not available\n");
964 return;
965 }
966
967 SetLastError(0xdeadbeef);
968 ret = pGetConsoleProcessList(NULL, 0);
969 ok(ret == 0, "Expected failure\n");
970 ok(GetLastError() == ERROR_INVALID_PARAMETER,
971 "Expected ERROR_INVALID_PARAMETER, got %d\n",
972 GetLastError());
973
974 SetLastError(0xdeadbeef);
975 ret = pGetConsoleProcessList(NULL, 1);
976 ok(ret == 0, "Expected failure\n");
977 ok(GetLastError() == ERROR_INVALID_PARAMETER,
978 "Expected ERROR_INVALID_PARAMETER, got %d\n",
979 GetLastError());
980
981 /* We should only have 1 process but only for these specific unit tests as
982 * we created our own console. An AttachConsole(ATTACH_PARENT_PROCESS) would
983 * give us two processes for example.
984 */
985 list = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD));
986
987 SetLastError(0xdeadbeef);
988 ret = pGetConsoleProcessList(list, 0);
989 ok(ret == 0, "Expected failure\n");
990 ok(GetLastError() == ERROR_INVALID_PARAMETER,
991 "Expected ERROR_INVALID_PARAMETER, got %d\n",
992 GetLastError());
993
994 SetLastError(0xdeadbeef);
995 ret = pGetConsoleProcessList(list, 1);
996 todo_wine
997 ok(ret == 1, "Expected 1, got %d\n", ret);
998
999 HeapFree(GetProcessHeap(), 0, list);
1000
1001 list = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(DWORD));
1002
1003 SetLastError(0xdeadbeef);
1004 ret = pGetConsoleProcessList(list, ret);
1005 todo_wine
1006 ok(ret == 1, "Expected 1, got %d\n", ret);
1007
1008 if (ret == 1)
1009 {
1010 DWORD pid = GetCurrentProcessId();
1011 ok(list[0] == pid, "Expected %d, got %d\n", pid, list[0]);
1012 }
1013
1014 HeapFree(GetProcessHeap(), 0, list);
1015 }
1016
1017 static void test_OpenCON(void)
1018 {
1019 static const WCHAR conW[] = {'C','O','N',0};
1020 static const DWORD accesses[] = {CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING,
1021 OPEN_ALWAYS, TRUNCATE_EXISTING};
1022 unsigned i;
1023 HANDLE h;
1024
1025 for (i = 0; i < sizeof(accesses) / sizeof(accesses[0]); i++)
1026 {
1027 h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1028 ok(h != INVALID_HANDLE_VALUE || broken(accesses[i] == TRUNCATE_EXISTING /* Win8 */),
1029 "Expected to open the CON device on write (%x)\n", accesses[i]);
1030 CloseHandle(h);
1031
1032 h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL);
1033 /* Windows versions differ here:
1034 * MSDN states in CreateFile that TRUNCATE_EXISTING requires GENERIC_WRITE
1035 * NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING
1036 * So don't test when disposition is TRUNCATE_EXISTING
1037 */
1038 ok(h != INVALID_HANDLE_VALUE || broken(accesses[i] == TRUNCATE_EXISTING /* Win7+ */),
1039 "Expected to open the CON device on read (%x)\n", accesses[i]);
1040 CloseHandle(h);
1041 h = CreateFileW(conW, GENERIC_READ|GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
1042 ok(h == INVALID_HANDLE_VALUE, "Expected not to open the CON device on read-write (%x)\n", accesses[i]);
1043 ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_PARAMETER,
1044 "Unexpected error %x\n", GetLastError());
1045 }
1046 }
1047
1048 static void test_OpenConsoleW(void)
1049 {
1050 static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1051 static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1052 static const WCHAR emptyW[] = {0};
1053 static const WCHAR invalidW[] = {'I','N','V','A','L','I','D',0};
1054 DWORD gle;
1055
1056 static const struct
1057 {
1058 LPCWSTR name;
1059 DWORD access;
1060 BOOL inherit;
1061 DWORD creation;
1062 DWORD gle, gle2;
1063 } invalid_table[] = {
1064 {NULL, 0, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1065 {NULL, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1066 {NULL, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1067 {NULL, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1068 {NULL, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1069 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1070 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1071 {NULL, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1072 {emptyW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1073 {emptyW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1074 {emptyW, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1075 {emptyW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1076 {emptyW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1077 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1078 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1079 {emptyW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
1080 {invalidW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
1081 {invalidW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1082 {invalidW, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
1083 {invalidW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1084 {invalidW, 0, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
1085 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
1086 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
1087 {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING, ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
1088 {coninW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1089 {coninW, 0xdeadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED},
1090 {coninW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1091 {conoutW, 0, FALSE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1092 {conoutW, 0xceadbeef, FALSE, 0, ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED},
1093 {conoutW, 0xdeadbeef, TRUE, 0xdeadbeef, ERROR_INVALID_PARAMETER, 0},
1094 };
1095 static const struct
1096 {
1097 LPCWSTR name;
1098 DWORD access;
1099 BOOL inherit;
1100 DWORD creation;
1101 } valid_table[] = {
1102 {coninW, 0, FALSE, 0 },
1103 {coninW, 0, TRUE, 0 },
1104 {coninW, GENERIC_EXECUTE, TRUE, 0 },
1105 {coninW, GENERIC_ALL, TRUE, 0 },
1106 {coninW, 0, FALSE, OPEN_ALWAYS },
1107 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, 0 },
1108 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW },
1109 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS },
1110 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS },
1111 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, TRUNCATE_EXISTING},
1112 {conoutW, 0, FALSE, 0 },
1113 {conoutW, 0, FALSE, OPEN_ALWAYS },
1114 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, 0 },
1115 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, },
1116 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS },
1117 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS },
1118 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, TRUNCATE_EXISTING},
1119 };
1120
1121 int index;
1122 HANDLE ret;
1123
1124 if (!pOpenConsoleW)
1125 {
1126 win_skip("OpenConsoleW is not available\n");
1127 return;
1128 }
1129
1130 for (index = 0; index < sizeof(invalid_table)/sizeof(invalid_table[0]); index++)
1131 {
1132 SetLastError(0xdeadbeef);
1133 ret = pOpenConsoleW(invalid_table[index].name, invalid_table[index].access,
1134 invalid_table[index].inherit, invalid_table[index].creation);
1135 gle = GetLastError();
1136 ok(ret == INVALID_HANDLE_VALUE,
1137 "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
1138 index, ret);
1139 ok(gle == invalid_table[index].gle || (gle != 0 && gle == invalid_table[index].gle2),
1140 "Expected GetLastError() to return %u/%u for index %d, got %u\n",
1141 invalid_table[index].gle, invalid_table[index].gle2, index, gle);
1142 }
1143
1144 for (index = 0; index < sizeof(valid_table)/sizeof(valid_table[0]); index++)
1145 {
1146 ret = pOpenConsoleW(valid_table[index].name, valid_table[index].access,
1147 valid_table[index].inherit, valid_table[index].creation);
1148 todo_wine
1149 ok(ret != INVALID_HANDLE_VALUE || broken(ret == INVALID_HANDLE_VALUE /* until Win7 */),
1150 "Expected OpenConsoleW to succeed for index %d, got %p\n", index, ret);
1151 if (ret != INVALID_HANDLE_VALUE)
1152 CloseHandle(ret);
1153 }
1154
1155 ret = pOpenConsoleW(coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1156 ok(ret != INVALID_HANDLE_VALUE, "Expected OpenConsoleW to return a valid handle\n");
1157 if (ret != INVALID_HANDLE_VALUE)
1158 CloseHandle(ret);
1159
1160 ret = pOpenConsoleW(conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
1161 ok(ret != INVALID_HANDLE_VALUE, "Expected OpenConsoleW to return a valid handle\n");
1162 if (ret != INVALID_HANDLE_VALUE)
1163 CloseHandle(ret);
1164 }
1165
1166 static void test_CreateFileW(void)
1167 {
1168 static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
1169 static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
1170
1171 static const struct
1172 {
1173 LPCWSTR name;
1174 DWORD access;
1175 BOOL inherit;
1176 DWORD creation;
1177 DWORD gle;
1178 BOOL is_broken;
1179 } cf_table[] = {
1180 {coninW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE},
1181 {coninW, 0, FALSE, OPEN_ALWAYS, 0, FALSE},
1182 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE},
1183 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, 0, FALSE},
1184 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, 0, FALSE},
1185 {coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, 0, FALSE},
1186 {conoutW, 0, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE},
1187 {conoutW, 0, FALSE, OPEN_ALWAYS, 0, FALSE},
1188 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, 0, ERROR_INVALID_PARAMETER, TRUE},
1189 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_NEW, 0, FALSE},
1190 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, CREATE_ALWAYS, 0, FALSE},
1191 {conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_ALWAYS, 0, FALSE},
1192 /* TRUNCATE_EXISTING is forbidden starting with Windows 8 */
1193 };
1194
1195 int index;
1196 HANDLE ret;
1197 SECURITY_ATTRIBUTES sa;
1198
1199 for (index = 0; index < sizeof(cf_table)/sizeof(cf_table[0]); index++)
1200 {
1201 SetLastError(0xdeadbeef);
1202
1203 sa.nLength = sizeof(sa);
1204 sa.lpSecurityDescriptor = NULL;
1205 sa.bInheritHandle = cf_table[index].inherit;
1206
1207 ret = CreateFileW(cf_table[index].name, cf_table[index].access,
1208 FILE_SHARE_READ|FILE_SHARE_WRITE, &sa,
1209 cf_table[index].creation, FILE_ATTRIBUTE_NORMAL, NULL);
1210 if (ret == INVALID_HANDLE_VALUE)
1211 {
1212 ok(cf_table[index].gle,
1213 "Expected CreateFileW not to return INVALID_HANDLE_VALUE for index %d\n", index);
1214 ok(GetLastError() == cf_table[index].gle,
1215 "Expected GetLastError() to return %u for index %d, got %u\n",
1216 cf_table[index].gle, index, GetLastError());
1217 }
1218 else
1219 {
1220 ok(!cf_table[index].gle || broken(cf_table[index].is_broken) /* Win7 */,
1221 "Expected CreateFileW to succeed for index %d\n", index);
1222 CloseHandle(ret);
1223 }
1224 }
1225 }
1226
1227 static void test_VerifyConsoleIoHandle( HANDLE handle )
1228 {
1229 BOOL ret;
1230 DWORD error;
1231
1232 if (!pVerifyConsoleIoHandle)
1233 {
1234 win_skip("VerifyConsoleIoHandle is not available\n");
1235 return;
1236 }
1237
1238 /* invalid handle */
1239 SetLastError(0xdeadbeef);
1240 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee0);
1241 error = GetLastError();
1242 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1243 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1244
1245 /* invalid handle + 1 */
1246 SetLastError(0xdeadbeef);
1247 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee1);
1248 error = GetLastError();
1249 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1250 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1251
1252 /* invalid handle + 2 */
1253 SetLastError(0xdeadbeef);
1254 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee2);
1255 error = GetLastError();
1256 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1257 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1258
1259 /* invalid handle + 3 */
1260 SetLastError(0xdeadbeef);
1261 ret = pVerifyConsoleIoHandle((HANDLE)0xdeadbee3);
1262 error = GetLastError();
1263 ok(!ret, "expected VerifyConsoleIoHandle to fail\n");
1264 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1265
1266 /* valid handle */
1267 SetLastError(0xdeadbeef);
1268 ret = pVerifyConsoleIoHandle(handle);
1269 error = GetLastError();
1270 ok(ret, "expected VerifyConsoleIoHandle to succeed\n");
1271 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1272 }
1273
1274 static void test_GetSetStdHandle(void)
1275 {
1276 HANDLE handle;
1277 DWORD error;
1278 BOOL ret;
1279
1280 /* get invalid std handle */
1281 SetLastError(0xdeadbeef);
1282 handle = GetStdHandle(42);
1283 error = GetLastError();
1284 ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1285 "wrong GetLastError() %d\n", error);
1286 ok(handle == INVALID_HANDLE_VALUE, "expected INVALID_HANDLE_VALUE\n");
1287
1288 /* get valid */
1289 SetLastError(0xdeadbeef);
1290 handle = GetStdHandle(STD_INPUT_HANDLE);
1291 error = GetLastError();
1292 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1293
1294 /* set invalid std handle */
1295 SetLastError(0xdeadbeef);
1296 ret = SetStdHandle(42, handle);
1297 error = GetLastError();
1298 ok(!ret, "expected SetStdHandle to fail\n");
1299 ok(error == ERROR_INVALID_HANDLE || broken(error == ERROR_INVALID_FUNCTION)/* Win9x */,
1300 "wrong GetLastError() %d\n", error);
1301
1302 /* set valid (restore old value) */
1303 SetLastError(0xdeadbeef);
1304 ret = SetStdHandle(STD_INPUT_HANDLE, handle);
1305 error = GetLastError();
1306 ok(ret, "expected SetStdHandle to succeed\n");
1307 ok(error == 0xdeadbeef, "wrong GetLastError() %d\n", error);
1308 }
1309
1310 static void test_GetNumberOfConsoleInputEvents(HANDLE input_handle)
1311 {
1312 DWORD count;
1313 BOOL ret;
1314 int i;
1315
1316 const struct
1317 {
1318 HANDLE handle;
1319 LPDWORD nrofevents;
1320 DWORD last_error;
1321 } invalid_table[] =
1322 {
1323 {NULL, NULL, ERROR_INVALID_HANDLE},
1324 {NULL, &count, ERROR_INVALID_HANDLE},
1325 {INVALID_HANDLE_VALUE, NULL, ERROR_INVALID_HANDLE},
1326 {INVALID_HANDLE_VALUE, &count, ERROR_INVALID_HANDLE},
1327 };
1328
1329 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1330 {
1331 SetLastError(0xdeadbeef);
1332 if (invalid_table[i].nrofevents) count = 0xdeadbeef;
1333 ret = GetNumberOfConsoleInputEvents(invalid_table[i].handle,
1334 invalid_table[i].nrofevents);
1335 ok(!ret, "[%d] Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", i, ret);
1336 if (invalid_table[i].nrofevents)
1337 {
1338 ok(count == 0xdeadbeef,
1339 "[%d] Expected output count to be unmodified, got %u\n", i, count);
1340 }
1341 ok(GetLastError() == invalid_table[i].last_error,
1342 "[%d] Expected last error to be %u, got %u\n",
1343 i, invalid_table[i].last_error, GetLastError());
1344 }
1345
1346 /* Test crashes on Windows 7. */
1347 if (0)
1348 {
1349 SetLastError(0xdeadbeef);
1350 ret = GetNumberOfConsoleInputEvents(input_handle, NULL);
1351 ok(!ret, "Expected GetNumberOfConsoleInputEvents to return FALSE, got %d\n", ret);
1352 ok(GetLastError() == ERROR_INVALID_ACCESS,
1353 "Expected last error to be ERROR_INVALID_ACCESS, got %u\n",
1354 GetLastError());
1355 }
1356
1357 count = 0xdeadbeef;
1358 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1359 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1360 ok(count != 0xdeadbeef, "Expected output count to initialized\n");
1361 }
1362
1363 static void test_WriteConsoleInputA(HANDLE input_handle)
1364 {
1365 INPUT_RECORD event;
1366 INPUT_RECORD event_list[5];
1367 MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1368 KEY_EVENT_RECORD key_event;
1369 DWORD count, console_mode, gle;
1370 BOOL ret;
1371 int i;
1372
1373 const struct
1374 {
1375 HANDLE handle;
1376 const INPUT_RECORD *buffer;
1377 DWORD count;
1378 LPDWORD written;
1379 DWORD expected_count;
1380 DWORD gle, gle2;
1381 int win_crash;
1382 } invalid_table[] =
1383 {
1384 {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1385 {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1386 {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1387 {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
1388 {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1389 {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1390 {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1391 {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1392 {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1393 {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1394 {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1395 {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS},
1396 {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1397 {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1398 {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1399 {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1400 {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1401 {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1402 {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
1403 {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1404 {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1405 };
1406
1407 /* Suppress external sources of input events for the duration of the test. */
1408 ret = GetConsoleMode(input_handle, &console_mode);
1409 ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1410 if (!ret)
1411 {
1412 skip("GetConsoleMode failed with last error %u\n", GetLastError());
1413 return;
1414 }
1415
1416 ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1417 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1418 if (!ret)
1419 {
1420 skip("SetConsoleMode failed with last error %u\n", GetLastError());
1421 return;
1422 }
1423
1424 /* Discard any events queued before the tests. */
1425 ret = FlushConsoleInputBuffer(input_handle);
1426 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1427
1428 event.EventType = MOUSE_EVENT;
1429 event.Event.MouseEvent = mouse_event;
1430
1431 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1432 {
1433 if (invalid_table[i].win_crash)
1434 continue;
1435
1436 SetLastError(0xdeadbeef);
1437 if (invalid_table[i].written) count = 0xdeadbeef;
1438 ret = WriteConsoleInputA(invalid_table[i].handle,
1439 invalid_table[i].buffer,
1440 invalid_table[i].count,
1441 invalid_table[i].written);
1442 ok(!ret, "[%d] Expected WriteConsoleInputA to return FALSE, got %d\n", i, ret);
1443 if (invalid_table[i].written)
1444 {
1445 ok(count == invalid_table[i].expected_count,
1446 "[%d] Expected output count to be %u, got %u\n",
1447 i, invalid_table[i].expected_count, count);
1448 }
1449 gle = GetLastError();
1450 ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2),
1451 "[%d] Expected last error to be %u or %u, got %u\n",
1452 i, invalid_table[i].gle, invalid_table[i].gle2, gle);
1453 }
1454
1455 count = 0xdeadbeef;
1456 ret = WriteConsoleInputA(input_handle, NULL, 0, &count);
1457 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1458 ok(count == 0, "Expected count to be 0, got %u\n", count);
1459
1460 count = 0xdeadbeef;
1461 ret = WriteConsoleInputA(input_handle, &event, 0, &count);
1462 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1463 ok(count == 0, "Expected count to be 0, got %u\n", count);
1464
1465 count = 0xdeadbeef;
1466 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1467 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1468 ok(count == 1, "Expected count to be 1, got %u\n", count);
1469
1470 ret = FlushConsoleInputBuffer(input_handle);
1471 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1472
1473 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1474 event.EventType = MOUSE_EVENT;
1475 event.Event.MouseEvent = mouse_event;
1476
1477 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1478 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1479 ok(count == 1, "Expected count to be 1, got %u\n", count);
1480
1481 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1482 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1483 ok(count == 1, "Expected count to be 1, got %u\n", count);
1484
1485 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1486 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1487 ok(count == 1, "Expected count to be 1, got %u\n", count);
1488
1489 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1490 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1491 todo_wine
1492 ok(count == 1, "Expected count to be 1, got %u\n", count);
1493
1494 ret = FlushConsoleInputBuffer(input_handle);
1495 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1496
1497 for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1498 {
1499 event_list[i].EventType = MOUSE_EVENT;
1500 event_list[i].Event.MouseEvent = mouse_event;
1501 }
1502
1503 /* Writing consecutive chunks of mouse events appears to work. */
1504 ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1505 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1506 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1507 "Expected count to be event list length, got %u\n", count);
1508
1509 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1510 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1511 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1512 "Expected count to be event list length, got %u\n", count);
1513
1514 ret = WriteConsoleInputA(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1515 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1516 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1517 "Expected count to be event list length, got %u\n", count);
1518
1519 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1520 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1521 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1522 "Expected count to be twice event list length, got %u\n", count);
1523
1524 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
1525 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1526 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1527 ok(count == 1, "Expected count to be 1, got %u\n", count);
1528
1529 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1530 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1531 todo_wine
1532 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1533 "Expected count to be twice event list length, got %u\n", count);
1534
1535 ret = FlushConsoleInputBuffer(input_handle);
1536 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1537
1538 key_event.bKeyDown = FALSE;
1539 key_event.wRepeatCount = 0;
1540 key_event.wVirtualKeyCode = VK_SPACE;
1541 key_event.wVirtualScanCode = VK_SPACE;
1542 key_event.uChar.AsciiChar = ' ';
1543 key_event.dwControlKeyState = 0;
1544
1545 event.EventType = KEY_EVENT;
1546 event.Event.KeyEvent = key_event;
1547
1548 /* Key events don't exhibit the same behavior as mouse events. */
1549 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1550 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1551 ok(count == 1, "Expected count to be 1, got %u\n", count);
1552
1553 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1554 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1555 ok(count == 1, "Expected count to be 1, got %u\n", count);
1556
1557 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1558 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1559 ok(count == 1, "Expected count to be 1, got %u\n", count);
1560
1561 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1562 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1563 ok(count == 2, "Expected count to be 2, got %u\n", count);
1564
1565 ret = FlushConsoleInputBuffer(input_handle);
1566 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1567
1568 /* Try interleaving mouse and key events. */
1569 event.EventType = MOUSE_EVENT;
1570 event.Event.MouseEvent = mouse_event;
1571
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 ok(count == 1, "Expected count to be 1, got %u\n", count);
1579
1580 event.EventType = KEY_EVENT;
1581 event.Event.KeyEvent = key_event;
1582
1583 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1584 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1585 ok(count == 1, "Expected count to be 1, got %u\n", count);
1586
1587 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1588 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1589 ok(count == 2, "Expected count to be 2, got %u\n", count);
1590
1591 event.EventType = MOUSE_EVENT;
1592 event.Event.MouseEvent = mouse_event;
1593
1594 ret = WriteConsoleInputA(input_handle, &event, 1, &count);
1595 ok(ret == TRUE, "Expected WriteConsoleInputA to return TRUE, got %d\n", ret);
1596 ok(count == 1, "Expected count to be 1, got %u\n", count);
1597
1598 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1599 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1600 ok(count == 3, "Expected count to be 3, got %u\n", count);
1601
1602 /* Restore the old console mode. */
1603 ret = SetConsoleMode(input_handle, console_mode);
1604 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1605 }
1606
1607 static void test_WriteConsoleInputW(HANDLE input_handle)
1608 {
1609 INPUT_RECORD event;
1610 INPUT_RECORD event_list[5];
1611 MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
1612 KEY_EVENT_RECORD key_event;
1613 DWORD count, console_mode, gle;
1614 BOOL ret;
1615 int i;
1616
1617 const struct
1618 {
1619 HANDLE handle;
1620 const INPUT_RECORD *buffer;
1621 DWORD count;
1622 LPDWORD written;
1623 DWORD expected_count;
1624 DWORD gle, gle2;
1625 int win_crash;
1626 } invalid_table[] =
1627 {
1628 {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1629 {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1630 {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1631 {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
1632 {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1633 {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1634 {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1635 {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1636 {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1637 {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
1638 {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1639 {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS},
1640 {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1641 {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
1642 {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1643 {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
1644 {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1645 {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1646 {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
1647 {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1648 {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
1649 };
1650
1651 /* Suppress external sources of input events for the duration of the test. */
1652 ret = GetConsoleMode(input_handle, &console_mode);
1653 ok(ret == TRUE, "Expected GetConsoleMode to return TRUE, got %d\n", ret);
1654 if (!ret)
1655 {
1656 skip("GetConsoleMode failed with last error %u\n", GetLastError());
1657 return;
1658 }
1659
1660 ret = SetConsoleMode(input_handle, console_mode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
1661 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1662 if (!ret)
1663 {
1664 skip("SetConsoleMode failed with last error %u\n", GetLastError());
1665 return;
1666 }
1667
1668 /* Discard any events queued before the tests. */
1669 ret = FlushConsoleInputBuffer(input_handle);
1670 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1671
1672 event.EventType = MOUSE_EVENT;
1673 event.Event.MouseEvent = mouse_event;
1674
1675 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1676 {
1677 if (invalid_table[i].win_crash)
1678 continue;
1679
1680 SetLastError(0xdeadbeef);
1681 if (invalid_table[i].written) count = 0xdeadbeef;
1682 ret = WriteConsoleInputW(invalid_table[i].handle,
1683 invalid_table[i].buffer,
1684 invalid_table[i].count,
1685 invalid_table[i].written);
1686 ok(!ret, "[%d] Expected WriteConsoleInputW to return FALSE, got %d\n", i, ret);
1687 if (invalid_table[i].written)
1688 {
1689 ok(count == invalid_table[i].expected_count,
1690 "[%d] Expected output count to be %u, got %u\n",
1691 i, invalid_table[i].expected_count, count);
1692 }
1693 gle = GetLastError();
1694 ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2),
1695 "[%d] Expected last error to be %u or %u, got %u\n",
1696 i, invalid_table[i].gle, invalid_table[i].gle2, gle);
1697 }
1698
1699 count = 0xdeadbeef;
1700 ret = WriteConsoleInputW(input_handle, NULL, 0, &count);
1701 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1702 ok(count == 0, "Expected count to be 0, got %u\n", count);
1703
1704 count = 0xdeadbeef;
1705 ret = WriteConsoleInputW(input_handle, &event, 0, &count);
1706 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1707 ok(count == 0, "Expected count to be 0, got %u\n", count);
1708
1709 count = 0xdeadbeef;
1710 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1711 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1712 ok(count == 1, "Expected count to be 1, got %u\n", count);
1713
1714 ret = FlushConsoleInputBuffer(input_handle);
1715 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1716
1717 /* Writing a single mouse event doesn't seem to affect the count if an adjacent mouse event is already queued. */
1718 event.EventType = MOUSE_EVENT;
1719 event.Event.MouseEvent = mouse_event;
1720
1721 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1722 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1723 ok(count == 1, "Expected count to be 1, got %u\n", count);
1724
1725 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1726 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1727 ok(count == 1, "Expected count to be 1, got %u\n", count);
1728
1729 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1730 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1731 ok(count == 1, "Expected count to be 1, got %u\n", count);
1732
1733 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1734 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1735 todo_wine
1736 ok(count == 1, "Expected count to be 1, got %u\n", count);
1737
1738 ret = FlushConsoleInputBuffer(input_handle);
1739 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1740
1741 for (i = 0; i < sizeof(event_list)/sizeof(event_list[0]); i++)
1742 {
1743 event_list[i].EventType = MOUSE_EVENT;
1744 event_list[i].Event.MouseEvent = mouse_event;
1745 }
1746
1747 /* Writing consecutive chunks of mouse events appears to work. */
1748 ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1749 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1750 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1751 "Expected count to be event list length, got %u\n", count);
1752
1753 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1754 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1755 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1756 "Expected count to be event list length, got %u\n", count);
1757
1758 ret = WriteConsoleInputW(input_handle, event_list, sizeof(event_list)/sizeof(event_list[0]), &count);
1759 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1760 ok(count == sizeof(event_list)/sizeof(event_list[0]),
1761 "Expected count to be event list length, got %u\n", count);
1762
1763 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1764 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1765 ok(count == 2*sizeof(event_list)/sizeof(event_list[0]),
1766 "Expected count to be twice event list length, got %u\n", count);
1767
1768 /* Again, writing a single mouse event with adjacent mouse events queued doesn't appear to affect the count. */
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 == 2*sizeof(event_list)/sizeof(event_list[0]),
1777 "Expected count to be twice event list length, got %u\n", count);
1778
1779 ret = FlushConsoleInputBuffer(input_handle);
1780 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1781
1782 key_event.bKeyDown = FALSE;
1783 key_event.wRepeatCount = 0;
1784 key_event.wVirtualKeyCode = VK_SPACE;
1785 key_event.wVirtualScanCode = VK_SPACE;
1786 key_event.uChar.UnicodeChar = ' ';
1787 key_event.dwControlKeyState = 0;
1788
1789 event.EventType = KEY_EVENT;
1790 event.Event.KeyEvent = key_event;
1791
1792 /* Key events don't exhibit the same behavior as mouse events. */
1793 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1794 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1795 ok(count == 1, "Expected count to be 1, got %u\n", count);
1796
1797 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1798 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1799 ok(count == 1, "Expected count to be 1, got %u\n", count);
1800
1801 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1802 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1803 ok(count == 1, "Expected count to be 1, got %u\n", count);
1804
1805 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1806 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1807 ok(count == 2, "Expected count to be 2, got %u\n", count);
1808
1809 ret = FlushConsoleInputBuffer(input_handle);
1810 ok(ret == TRUE, "Expected FlushConsoleInputBuffer to return TRUE, got %d\n", ret);
1811
1812 /* Try interleaving mouse and key events. */
1813 event.EventType = MOUSE_EVENT;
1814 event.Event.MouseEvent = mouse_event;
1815
1816 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1817 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1818 ok(count == 1, "Expected count to be 1, got %u\n", count);
1819
1820 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1821 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1822 ok(count == 1, "Expected count to be 1, got %u\n", count);
1823
1824 event.EventType = KEY_EVENT;
1825 event.Event.KeyEvent = key_event;
1826
1827 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1828 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1829 ok(count == 1, "Expected count to be 1, got %u\n", count);
1830
1831 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1832 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1833 ok(count == 2, "Expected count to be 2, got %u\n", count);
1834
1835 event.EventType = MOUSE_EVENT;
1836 event.Event.MouseEvent = mouse_event;
1837
1838 ret = WriteConsoleInputW(input_handle, &event, 1, &count);
1839 ok(ret == TRUE, "Expected WriteConsoleInputW to return TRUE, got %d\n", ret);
1840 ok(count == 1, "Expected count to be 1, got %u\n", count);
1841
1842 ret = GetNumberOfConsoleInputEvents(input_handle, &count);
1843 ok(ret == TRUE, "Expected GetNumberOfConsoleInputEvents to return TRUE, got %d\n", ret);
1844 ok(count == 3, "Expected count to be 3, got %u\n", count);
1845
1846 /* Restore the old console mode. */
1847 ret = SetConsoleMode(input_handle, console_mode);
1848 ok(ret == TRUE, "Expected SetConsoleMode to return TRUE, got %d\n", ret);
1849 }
1850
1851 static void test_WriteConsoleOutputCharacterA(HANDLE output_handle)
1852 {
1853 static const char output[] = {'a', 0};
1854
1855 COORD origin = {0, 0};
1856 DWORD count;
1857 BOOL ret;
1858 int i;
1859
1860 const struct
1861 {
1862 HANDLE hConsoleOutput;
1863 LPCSTR str;
1864 DWORD length;
1865 COORD coord;
1866 LPDWORD lpNumCharsWritten;
1867 DWORD expected_count;
1868 DWORD last_error;
1869 int win7_crash;
1870 } invalid_table[] =
1871 {
1872 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1873 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1874 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1875 {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1876 {NULL, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1877 {NULL, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1878 {NULL, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1879 {NULL, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1880 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1881 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1882 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1883 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1884 {INVALID_HANDLE_VALUE, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1885 {INVALID_HANDLE_VALUE, output, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1886 {INVALID_HANDLE_VALUE, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1887 {INVALID_HANDLE_VALUE, output, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1888 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1889 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1890 {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1891 {output_handle, output, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1892 {output_handle, output, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1893 };
1894
1895 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1896 {
1897 if (invalid_table[i].win7_crash)
1898 continue;
1899
1900 SetLastError(0xdeadbeef);
1901 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1902 ret = WriteConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
1903 invalid_table[i].str,
1904 invalid_table[i].length,
1905 invalid_table[i].coord,
1906 invalid_table[i].lpNumCharsWritten);
1907 ok(!ret, "[%d] Expected WriteConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
1908 if (invalid_table[i].lpNumCharsWritten)
1909 {
1910 ok(count == invalid_table[i].expected_count,
1911 "[%d] Expected count to be %u, got %u\n",
1912 i, invalid_table[i].expected_count, count);
1913 }
1914 ok(GetLastError() == invalid_table[i].last_error,
1915 "[%d] Expected last error to be %u, got %u\n",
1916 i, invalid_table[i].last_error, GetLastError());
1917 }
1918
1919 count = 0xdeadbeef;
1920 ret = WriteConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
1921 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1922 ok(count == 0, "Expected count to be 0, got %u\n", count);
1923
1924 count = 0xdeadbeef;
1925 ret = WriteConsoleOutputCharacterA(output_handle, output, 0, origin, &count);
1926 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1927 ok(count == 0, "Expected count to be 0, got %u\n", count);
1928
1929 count = 0xdeadbeef;
1930 ret = WriteConsoleOutputCharacterA(output_handle, output, 1, origin, &count);
1931 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterA to return TRUE, got %d\n", ret);
1932 ok(count == 1, "Expected count to be 1, got %u\n", count);
1933 }
1934
1935 static void test_WriteConsoleOutputCharacterW(HANDLE output_handle)
1936 {
1937 static const WCHAR outputW[] = {'a',0};
1938
1939 COORD origin = {0, 0};
1940 DWORD count;
1941 BOOL ret;
1942 int i;
1943
1944 const struct
1945 {
1946 HANDLE hConsoleOutput;
1947 LPCWSTR str;
1948 DWORD length;
1949 COORD coord;
1950 LPDWORD lpNumCharsWritten;
1951 DWORD expected_count;
1952 DWORD last_error;
1953 int win7_crash;
1954 } invalid_table[] =
1955 {
1956 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1957 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1958 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1959 {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1960 {NULL, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1961 {NULL, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1962 {NULL, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1963 {NULL, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1964 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1965 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1966 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1967 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1968 {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1969 {INVALID_HANDLE_VALUE, outputW, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1970 {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1971 {INVALID_HANDLE_VALUE, outputW, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
1972 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1973 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1974 {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1975 {output_handle, outputW, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1976 {output_handle, outputW, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
1977 };
1978
1979 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
1980 {
1981 if (invalid_table[i].win7_crash)
1982 continue;
1983
1984 SetLastError(0xdeadbeef);
1985 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
1986 ret = WriteConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
1987 invalid_table[i].str,
1988 invalid_table[i].length,
1989 invalid_table[i].coord,
1990 invalid_table[i].lpNumCharsWritten);
1991 ok(!ret, "[%d] Expected WriteConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
1992 if (invalid_table[i].lpNumCharsWritten)
1993 {
1994 ok(count == invalid_table[i].expected_count,
1995 "[%d] Expected count to be %u, got %u\n",
1996 i, invalid_table[i].expected_count, count);
1997 }
1998 ok(GetLastError() == invalid_table[i].last_error,
1999 "[%d] Expected last error to be %u, got %u\n",
2000 i, invalid_table[i].last_error, GetLastError());
2001 }
2002
2003 count = 0xdeadbeef;
2004 ret = WriteConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
2005 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2006 ok(count == 0, "Expected count to be 0, got %u\n", count);
2007
2008 count = 0xdeadbeef;
2009 ret = WriteConsoleOutputCharacterW(output_handle, outputW, 0, origin, &count);
2010 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2011 ok(count == 0, "Expected count to be 0, got %u\n", count);
2012
2013 count = 0xdeadbeef;
2014 ret = WriteConsoleOutputCharacterW(output_handle, outputW, 1, origin, &count);
2015 ok(ret == TRUE, "Expected WriteConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2016 ok(count == 1, "Expected count to be 1, got %u\n", count);
2017 }
2018
2019 static void test_WriteConsoleOutputAttribute(HANDLE output_handle)
2020 {
2021 WORD attr = FOREGROUND_BLUE;
2022 COORD origin = {0, 0};
2023 DWORD count;
2024 BOOL ret;
2025 int i;
2026
2027 const struct
2028 {
2029 HANDLE hConsoleOutput;
2030 const WORD *attr;
2031 DWORD length;
2032 COORD coord;
2033 LPDWORD lpNumAttrsWritten;
2034 DWORD expected_count;
2035 DWORD last_error;
2036 int win7_crash;
2037 } invalid_table[] =
2038 {
2039 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2040 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2041 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2042 {NULL, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2043 {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2044 {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2045 {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2046 {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2047 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2048 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2049 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2050 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2051 {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2052 {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2053 {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2054 {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2055 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2056 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2057 {output_handle, NULL, 1, {0, 0}, &count, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2058 {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2059 {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2060 };
2061
2062 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2063 {
2064 if (invalid_table[i].win7_crash)
2065 continue;
2066
2067 SetLastError(0xdeadbeef);
2068 if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2069 ret = WriteConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2070 invalid_table[i].attr,
2071 invalid_table[i].length,
2072 invalid_table[i].coord,
2073 invalid_table[i].lpNumAttrsWritten);
2074 ok(!ret, "[%d] Expected WriteConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2075 if (invalid_table[i].lpNumAttrsWritten)
2076 {
2077 ok(count == invalid_table[i].expected_count,
2078 "[%d] Expected count to be %u, got %u\n",
2079 i, invalid_table[i].expected_count, count);
2080 }
2081 ok(GetLastError() == invalid_table[i].last_error,
2082 "[%d] Expected last error to be %u, got %u\n",
2083 i, invalid_table[i].last_error, GetLastError());
2084 }
2085
2086 count = 0xdeadbeef;
2087 ret = WriteConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2088 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2089 ok(count == 0, "Expected count to be 0, got %u\n", count);
2090
2091 count = 0xdeadbeef;
2092 ret = WriteConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2093 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2094 ok(count == 0, "Expected count to be 0, got %u\n", count);
2095
2096 count = 0xdeadbeef;
2097 ret = WriteConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2098 ok(ret == TRUE, "Expected WriteConsoleOutputAttribute to return TRUE, got %d\n", ret);
2099 ok(count == 1, "Expected count to be 1, got %u\n", count);
2100 }
2101
2102 static void test_FillConsoleOutputCharacterA(HANDLE output_handle)
2103 {
2104 COORD origin = {0, 0};
2105 DWORD count;
2106 BOOL ret;
2107 int i;
2108
2109 const struct
2110 {
2111 HANDLE hConsoleOutput;
2112 CHAR ch;
2113 DWORD length;
2114 COORD coord;
2115 LPDWORD lpNumCharsWritten;
2116 DWORD expected_count;
2117 DWORD last_error;
2118 int win7_crash;
2119 } invalid_table[] =
2120 {
2121 {NULL, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2122 {NULL, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2123 {NULL, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2124 {NULL, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2125 {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2126 {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2127 {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2128 {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2129 {output_handle, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2130 {output_handle, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2131 };
2132
2133 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2134 {
2135 if (invalid_table[i].win7_crash)
2136 continue;
2137
2138 SetLastError(0xdeadbeef);
2139 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2140 ret = FillConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2141 invalid_table[i].ch,
2142 invalid_table[i].length,
2143 invalid_table[i].coord,
2144 invalid_table[i].lpNumCharsWritten);
2145 ok(!ret, "[%d] Expected FillConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2146 if (invalid_table[i].lpNumCharsWritten)
2147 {
2148 ok(count == invalid_table[i].expected_count,
2149 "[%d] Expected count to be %u, got %u\n",
2150 i, invalid_table[i].expected_count, count);
2151 }
2152 ok(GetLastError() == invalid_table[i].last_error,
2153 "[%d] Expected last error to be %u, got %u\n",
2154 i, invalid_table[i].last_error, GetLastError());
2155 }
2156
2157 count = 0xdeadbeef;
2158 ret = FillConsoleOutputCharacterA(output_handle, 'a', 0, origin, &count);
2159 ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2160 ok(count == 0, "Expected count to be 0, got %u\n", count);
2161
2162 count = 0xdeadbeef;
2163 ret = FillConsoleOutputCharacterA(output_handle, 'a', 1, origin, &count);
2164 ok(ret == TRUE, "Expected FillConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2165 ok(count == 1, "Expected count to be 1, got %u\n", count);
2166 }
2167
2168 static void test_FillConsoleOutputCharacterW(HANDLE output_handle)
2169 {
2170 COORD origin = {0, 0};
2171 DWORD count;
2172 BOOL ret;
2173 int i;
2174
2175 const struct
2176 {
2177 HANDLE hConsoleOutput;
2178 WCHAR ch;
2179 DWORD length;
2180 COORD coord;
2181 LPDWORD lpNumCharsWritten;
2182 DWORD expected_count;
2183 DWORD last_error;
2184 int win7_crash;
2185 } invalid_table[] =
2186 {
2187 {NULL, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2188 {NULL, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2189 {NULL, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2190 {NULL, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2191 {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2192 {INVALID_HANDLE_VALUE, 'a', 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2193 {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2194 {INVALID_HANDLE_VALUE, 'a', 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2195 {output_handle, 'a', 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2196 {output_handle, 'a', 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2197 };
2198
2199 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2200 {
2201 if (invalid_table[i].win7_crash)
2202 continue;
2203
2204 SetLastError(0xdeadbeef);
2205 if (invalid_table[i].lpNumCharsWritten) count = 0xdeadbeef;
2206 ret = FillConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2207 invalid_table[i].ch,
2208 invalid_table[i].length,
2209 invalid_table[i].coord,
2210 invalid_table[i].lpNumCharsWritten);
2211 ok(!ret, "[%d] Expected FillConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2212 if (invalid_table[i].lpNumCharsWritten)
2213 {
2214 ok(count == invalid_table[i].expected_count,
2215 "[%d] Expected count to be %u, got %u\n",
2216 i, invalid_table[i].expected_count, count);
2217 }
2218 ok(GetLastError() == invalid_table[i].last_error,
2219 "[%d] Expected last error to be %u, got %u\n",
2220 i, invalid_table[i].last_error, GetLastError());
2221 }
2222
2223 count = 0xdeadbeef;
2224 ret = FillConsoleOutputCharacterW(output_handle, 'a', 0, origin, &count);
2225 ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2226 ok(count == 0, "Expected count to be 0, got %u\n", count);
2227
2228 count = 0xdeadbeef;
2229 ret = FillConsoleOutputCharacterW(output_handle, 'a', 1, origin, &count);
2230 ok(ret == TRUE, "Expected FillConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2231 ok(count == 1, "Expected count to be 1, got %u\n", count);
2232 }
2233
2234 static void test_FillConsoleOutputAttribute(HANDLE output_handle)
2235 {
2236 COORD origin = {0, 0};
2237 DWORD count;
2238 BOOL ret;
2239 int i;
2240
2241 const struct
2242 {
2243 HANDLE hConsoleOutput;
2244 WORD attr;
2245 DWORD length;
2246 COORD coord;
2247 LPDWORD lpNumAttrsWritten;
2248 DWORD expected_count;
2249 DWORD last_error;
2250 int win7_crash;
2251 } invalid_table[] =
2252 {
2253 {NULL, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2254 {NULL, FOREGROUND_BLUE, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2255 {NULL, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2256 {NULL, FOREGROUND_BLUE, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2257 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2258 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2259 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2260 {INVALID_HANDLE_VALUE, FOREGROUND_BLUE, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2261 {output_handle, FOREGROUND_BLUE, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2262 {output_handle, FOREGROUND_BLUE, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2263 };
2264
2265 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2266 {
2267 if (invalid_table[i].win7_crash)
2268 continue;
2269
2270 SetLastError(0xdeadbeef);
2271 if (invalid_table[i].lpNumAttrsWritten) count = 0xdeadbeef;
2272 ret = FillConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2273 invalid_table[i].attr,
2274 invalid_table[i].length,
2275 invalid_table[i].coord,
2276 invalid_table[i].lpNumAttrsWritten);
2277 ok(!ret, "[%d] Expected FillConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2278 if (invalid_table[i].lpNumAttrsWritten)
2279 {
2280 ok(count == invalid_table[i].expected_count,
2281 "[%d] Expected count to be %u, got %u\n",
2282 i, invalid_table[i].expected_count, count);
2283 }
2284 ok(GetLastError() == invalid_table[i].last_error,
2285 "[%d] Expected last error to be %u, got %u\n",
2286 i, invalid_table[i].last_error, GetLastError());
2287 }
2288
2289 count = 0xdeadbeef;
2290 ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 0, origin, &count);
2291 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2292 ok(count == 0, "Expected count to be 0, got %u\n", count);
2293
2294 count = 0xdeadbeef;
2295 ret = FillConsoleOutputAttribute(output_handle, FOREGROUND_BLUE, 1, origin, &count);
2296 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2297 ok(count == 1, "Expected count to be 1, got %u\n", count);
2298
2299 count = 0xdeadbeef;
2300 ret = FillConsoleOutputAttribute(output_handle, ~0, 1, origin, &count);
2301 ok(ret == TRUE, "Expected FillConsoleOutputAttribute to return TRUE, got %d\n", ret);
2302 ok(count == 1, "Expected count to be 1, got %u\n", count);
2303 }
2304
2305 static void test_ReadConsoleOutputCharacterA(HANDLE output_handle)
2306 {
2307 CHAR read;
2308 COORD origin = {0, 0};
2309 DWORD count;
2310 BOOL ret;
2311 int i;
2312
2313 const struct
2314 {
2315 HANDLE hConsoleOutput;
2316 LPSTR lpstr;
2317 DWORD length;
2318 COORD coord;
2319 LPDWORD read_count;
2320 DWORD expected_count;
2321 DWORD last_error;
2322 int win7_crash;
2323 } invalid_table[] =
2324 {
2325 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2326 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2327 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2328 {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2329 {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2330 {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2331 {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2332 {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2333 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2334 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2335 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2336 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2337 {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2338 {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2339 {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2340 {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2341 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2342 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2343 {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2344 {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1},
2345 {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2346 {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2347 };
2348
2349 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2350 {
2351 if (invalid_table[i].win7_crash)
2352 continue;
2353
2354 SetLastError(0xdeadbeef);
2355 if (invalid_table[i].read_count) count = 0xdeadbeef;
2356 ret = ReadConsoleOutputCharacterA(invalid_table[i].hConsoleOutput,
2357 invalid_table[i].lpstr,
2358 invalid_table[i].length,
2359 invalid_table[i].coord,
2360 invalid_table[i].read_count);
2361 ok(!ret, "[%d] Expected ReadConsoleOutputCharacterA to return FALSE, got %d\n", i, ret);
2362 if (invalid_table[i].read_count)
2363 {
2364 ok(count == invalid_table[i].expected_count,
2365 "[%d] Expected count to be %u, got %u\n",
2366 i, invalid_table[i].expected_count, count);
2367 }
2368 ok(GetLastError() == invalid_table[i].last_error,
2369 "[%d] Expected last error to be %u, got %u\n",
2370 i, invalid_table[i].last_error, GetLastError());
2371 }
2372
2373 count = 0xdeadbeef;
2374 ret = ReadConsoleOutputCharacterA(output_handle, NULL, 0, origin, &count);
2375 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2376 ok(count == 0, "Expected count to be 0, got %u\n", count);
2377
2378 count = 0xdeadbeef;
2379 ret = ReadConsoleOutputCharacterA(output_handle, &read, 0, origin, &count);
2380 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2381 ok(count == 0, "Expected count to be 0, got %u\n", count);
2382
2383 count = 0xdeadbeef;
2384 ret = ReadConsoleOutputCharacterA(output_handle, &read, 1, origin, &count);
2385 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterA to return TRUE, got %d\n", ret);
2386 ok(count == 1, "Expected count to be 1, got %u\n", count);
2387 }
2388
2389 static void test_ReadConsoleOutputCharacterW(HANDLE output_handle)
2390 {
2391 WCHAR read;
2392 COORD origin = {0, 0};
2393 DWORD count;
2394 BOOL ret;
2395 int i;
2396
2397 const struct
2398 {
2399 HANDLE hConsoleOutput;
2400 LPWSTR buffer;
2401 DWORD length;
2402 COORD coord;
2403 LPDWORD read_count;
2404 DWORD expected_count;
2405 DWORD last_error;
2406 int win7_crash;
2407 } invalid_table[] =
2408 {
2409 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2410 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2411 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2412 {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2413 {NULL, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2414 {NULL, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2415 {NULL, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2416 {NULL, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2417 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2418 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2419 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2420 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2421 {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2422 {INVALID_HANDLE_VALUE, &read, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2423 {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2424 {INVALID_HANDLE_VALUE, &read, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2425 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2426 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2427 {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2428 {output_handle, NULL, 10, {0, 0}, &count, 10, ERROR_INVALID_ACCESS, 1},
2429 {output_handle, &read, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2430 {output_handle, &read, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2431 };
2432
2433 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2434 {
2435 if (invalid_table[i].win7_crash)
2436 continue;
2437
2438 SetLastError(0xdeadbeef);
2439 if (invalid_table[i].read_count) count = 0xdeadbeef;
2440 ret = ReadConsoleOutputCharacterW(invalid_table[i].hConsoleOutput,
2441 invalid_table[i].buffer,
2442 invalid_table[i].length,
2443 invalid_table[i].coord,
2444 invalid_table[i].read_count);
2445 ok(!ret, "[%d] Expected ReadConsoleOutputCharacterW to return FALSE, got %d\n", i, ret);
2446 if (invalid_table[i].read_count)
2447 {
2448 ok(count == invalid_table[i].expected_count,
2449 "[%d] Expected count to be %u, got %u\n",
2450 i, invalid_table[i].expected_count, count);
2451 }
2452 ok(GetLastError() == invalid_table[i].last_error,
2453 "[%d] Expected last error to be %u, got %u\n",
2454 i, invalid_table[i].last_error, GetLastError());
2455 }
2456
2457 count = 0xdeadbeef;
2458 ret = ReadConsoleOutputCharacterW(output_handle, NULL, 0, origin, &count);
2459 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2460 ok(count == 0, "Expected count to be 0, got %u\n", count);
2461
2462 count = 0xdeadbeef;
2463 ret = ReadConsoleOutputCharacterW(output_handle, &read, 0, origin, &count);
2464 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2465 ok(count == 0, "Expected count to be 0, got %u\n", count);
2466
2467 count = 0xdeadbeef;
2468 ret = ReadConsoleOutputCharacterW(output_handle, &read, 1, origin, &count);
2469 ok(ret == TRUE, "Expected ReadConsoleOutputCharacterW to return TRUE, got %d\n", ret);
2470 ok(count == 1, "Expected count to be 1, got %u\n", count);
2471 }
2472
2473 static void test_ReadConsoleOutputAttribute(HANDLE output_handle)
2474 {
2475 WORD attr;
2476 COORD origin = {0, 0};
2477 DWORD count;
2478 BOOL ret;
2479 int i;
2480
2481 const struct
2482 {
2483 HANDLE hConsoleOutput;
2484 LPWORD lpAttribute;
2485 DWORD length;
2486 COORD coord;
2487 LPDWORD read_count;
2488 DWORD expected_count;
2489 DWORD last_error;
2490 int win7_crash;
2491 } invalid_table[] =
2492 {
2493 {NULL, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2494 {NULL, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2495 {NULL, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2496 {NULL, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2497 {NULL, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2498 {NULL, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2499 {NULL, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2500 {NULL, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2501 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2502 {INVALID_HANDLE_VALUE, NULL, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2503 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2504 {INVALID_HANDLE_VALUE, NULL, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE, 1},
2505 {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2506 {INVALID_HANDLE_VALUE, &attr, 0, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2507 {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2508 {INVALID_HANDLE_VALUE, &attr, 1, {0, 0}, &count, 0, ERROR_INVALID_HANDLE},
2509 {output_handle, NULL, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2510 {output_handle, NULL, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2511 {output_handle, NULL, 1, {0, 0}, &count, 1, ERROR_INVALID_ACCESS, 1},
2512 {output_handle, &attr, 0, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2513 {output_handle, &attr, 1, {0, 0}, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
2514 };
2515
2516 for (i = 0; i < sizeof(invalid_table)/sizeof(invalid_table[0]); i++)
2517 {
2518 if (invalid_table[i].win7_crash)
2519 continue;
2520
2521 SetLastError(0xdeadbeef);
2522 if (invalid_table[i].read_count) count = 0xdeadbeef;
2523 ret = ReadConsoleOutputAttribute(invalid_table[i].hConsoleOutput,
2524 invalid_table[i].lpAttribute,
2525 invalid_table[i].length,
2526 invalid_table[i].coord,
2527 invalid_table[i].read_count);
2528 ok(!ret, "[%d] Expected ReadConsoleOutputAttribute to return FALSE, got %d\n", i, ret);
2529 if (invalid_table[i].read_count)
2530 {
2531 ok(count == invalid_table[i].expected_count,
2532 "[%d] Expected count to be %u, got %u\n",
2533 i, invalid_table[i].expected_count, count);
2534 }
2535 ok(GetLastError() == invalid_table[i].last_error,
2536 "[%d] Expected last error to be %u, got %u\n",
2537 i, invalid_table[i].last_error, GetLastError());
2538 }
2539
2540 count = 0xdeadbeef;
2541 ret = ReadConsoleOutputAttribute(output_handle, NULL, 0, origin, &count);
2542 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2543 ok(count == 0, "Expected count to be 0, got %u\n", count);
2544
2545 count = 0xdeadbeef;
2546 ret = ReadConsoleOutputAttribute(output_handle, &attr, 0, origin, &count);
2547 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2548 ok(count == 0, "Expected count to be 0, got %u\n", count);
2549
2550 count = 0xdeadbeef;
2551 ret = ReadConsoleOutputAttribute(output_handle, &attr, 1, origin, &count);
2552 ok(ret == TRUE, "Expected ReadConsoleOutputAttribute to return TRUE, got %d\n", ret);
2553 ok(count == 1, "Expected count to be 1, got %u\n", count);
2554 }
2555
2556 static void test_ReadConsole(void)
2557 {
2558 HANDLE std_input;
2559 DWORD ret, bytes;
2560 char buf[1024];
2561
2562 std_input = GetStdHandle(STD_INPUT_HANDLE);
2563
2564 SetLastError(0xdeadbeef);
2565 ret = GetFileSize(std_input, NULL);
2566 ok(ret == INVALID_FILE_SIZE, "expected INVALID_FILE_SIZE, got %#x\n", ret);
2567 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
2568
2569 bytes = 0xdeadbeef;
2570 SetLastError(0xdeadbeef);
2571 ret = ReadFile(std_input, buf, -128, &bytes, NULL);
2572 ok(!ret, "expected 0, got %u\n", ret);
2573 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
2574 ok(!bytes, "expected 0, got %u\n", bytes);
2575
2576 bytes = 0xdeadbeef;
2577 SetLastError(0xdeadbeef);
2578 ret = ReadConsoleA(std_input, buf, -128, &bytes, NULL);
2579 ok(!ret, "expected 0, got %u\n", ret);
2580 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
2581 ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
2582
2583 bytes = 0xdeadbeef;
2584 SetLastError(0xdeadbeef);
2585 ret = ReadConsoleW(std_input, buf, -128, &bytes, NULL);
2586 ok(!ret, "expected 0, got %u\n", ret);
2587 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
2588 ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
2589 }
2590
2591 START_TEST(console)
2592 {
2593 static const char font_name[] = "Lucida Console";
2594 HANDLE hConIn, hConOut;
2595 BOOL ret;
2596 CONSOLE_SCREEN_BUFFER_INFO sbi;
2597 LONG err;
2598 HKEY console_key;
2599 char old_font[LF_FACESIZE];
2600 BOOL delete = FALSE;
2601 DWORD size;
2602
2603 init_function_pointers();
2604
2605 /* be sure we have a clean console (and that's our own)
2606 * FIXME: this will make the test fail (currently) if we don't run
2607 * under X11
2608 * Another solution would be to rerun the test under wineconsole with
2609 * the curses backend
2610 */
2611
2612 /* ReadConsoleOutputW doesn't retrieve characters from the output buffer
2613 * correctly for characters that don't have a glyph in the console font. So,
2614 * we first set the console font to Lucida Console (which has a wider
2615 * selection of glyphs available than the default raster fonts). We want
2616 * to be able to restore the original font afterwards, so don't change
2617 * if we can't read the original font.
2618 */
2619 err = RegOpenKeyExA(HKEY_CURRENT_USER, "Console", 0,
2620 KEY_QUERY_VALUE | KEY_SET_VALUE, &console_key);
2621 if (err == ERROR_SUCCESS)
2622 {
2623 size = sizeof(old_font);
2624 err = RegQueryValueExA(console_key, "FaceName", NULL, NULL,
2625 (LPBYTE) old_font, &size);
2626 if (err == ERROR_SUCCESS || err == ERROR_FILE_NOT_FOUND)
2627 {
2628 delete = (err == ERROR_FILE_NOT_FOUND);
2629 err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
2630 (const BYTE *) font_name, sizeof(font_name));
2631 if (err != ERROR_SUCCESS)
2632 trace("Unable to change default console font, error %d\n", err);
2633 }
2634 else
2635 {
2636 trace("Unable to query default console font, error %d\n", err);
2637 RegCloseKey(console_key);
2638 console_key = NULL;
2639 }
2640 }
2641 else
2642 {
2643 trace("Unable to open HKCU\\Console, error %d\n", err);
2644 console_key = NULL;
2645 }
2646
2647 /* Now detach and open a fresh console to play with */
2648 FreeConsole();
2649 ok(AllocConsole(), "Couldn't alloc console\n");
2650
2651 /* Restore default console font if needed */
2652 if (console_key != NULL)
2653 {
2654 if (delete)
2655 err = RegDeleteValueA(console_key, "FaceName");
2656 else
2657 err = RegSetValueExA(console_key, "FaceName", 0, REG_SZ,
2658 (const BYTE *) old_font, strlen(old_font) + 1);
2659 ok(err == ERROR_SUCCESS, "Unable to restore default console font, error %d\n", err);
2660 }
2661 hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2662 hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
2663
2664 /* now verify everything's ok */
2665 ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
2666 ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
2667
2668 ret = GetConsoleScreenBufferInfo(hConOut, &sbi);
2669 ok(ret, "Getting sb info\n");
2670 if (!ret) return;
2671
2672 /* Reduce the size of the buffer to the visible area plus 3 lines to speed
2673 * up the tests.
2674 */
2675 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);
2676 sbi.dwSize.Y = size = (sbi.srWindow.Bottom + 1) + 3;
2677 ret = SetConsoleScreenBufferSize(hConOut, sbi.dwSize);
2678 ok(ret, "Setting sb info\n");
2679 ret = GetConsoleScreenBufferInfo(hConOut, &sbi);
2680 ok(ret, "Getting sb info\n");
2681 ok(sbi.dwSize.Y == size, "Unexpected buffer size: %d instead of %d\n", sbi.dwSize.Y, size);
2682 if (!ret) return;
2683
2684 test_ReadConsole();
2685 /* Non interactive tests */
2686 testCursor(hConOut, sbi.dwSize);
2687 /* test parameters (FIXME: test functionality) */
2688 testCursorInfo(hConOut);
2689 /* will test wrapped (on/off) & processed (on/off) strings output */
2690 testWrite(hConOut, sbi.dwSize);
2691 /* will test line scrolling at the bottom of the screen */
2692 /* testBottomScroll(); */
2693 /* will test all the scrolling operations */
2694 testScroll(hConOut, sbi.dwSize);
2695 /* will test sb creation / modification / codepage handling */
2696 testScreenBuffer(hConOut);
2697 testCtrlHandler();
2698 /* still to be done: access rights & access on objects */
2699
2700 if (!pGetConsoleInputExeNameA || !pSetConsoleInputExeNameA)
2701 win_skip("GetConsoleInputExeNameA and/or SetConsoleInputExeNameA is not available\n");
2702 else
2703 test_GetSetConsoleInputExeName();
2704
2705 test_GetConsoleProcessList();
2706 test_OpenConsoleW();
2707 test_CreateFileW();
2708 test_OpenCON();
2709 test_VerifyConsoleIoHandle(hConOut);
2710 test_GetSetStdHandle();
2711 test_GetNumberOfConsoleInputEvents(hConIn);
2712 test_WriteConsoleInputA(hConIn);
2713 test_WriteConsoleInputW(hConIn);
2714 test_WriteConsoleOutputCharacterA(hConOut);
2715 test_WriteConsoleOutputCharacterW(hConOut);
2716 test_WriteConsoleOutputAttribute(hConOut);
2717 test_FillConsoleOutputCharacterA(hConOut);
2718 test_FillConsoleOutputCharacterW(hConOut);
2719 test_FillConsoleOutputAttribute(hConOut);
2720 test_ReadConsoleOutputCharacterA(hConOut);
2721 test_ReadConsoleOutputCharacterW(hConOut);
2722 test_ReadConsoleOutputAttribute(hConOut);
2723 }