ReactOS 0.4.16-dev-136-g52192f1
ConsoleCP.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Tests for i18n console.
5 * COPYRIGHT: Copyright 2017-2020 Katayama Hirofumi MZ
6 * Copyright 2020-2022 Hermès Bélusca-Maïto
7 */
8
9#include "precomp.h"
10
11#define okCURSOR(hCon, c) \
12do { \
13 CONSOLE_SCREEN_BUFFER_INFO __sbi; \
14 BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
15 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
16 ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
17 (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
18} while (0)
19
20#define ATTR (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
21
22static const WCHAR u0414[] = {0x0414, 0}; /* Д */
23static const WCHAR u9580[] = {0x9580, 0}; /* 門 */
24static const WCHAR space[] = {L' ', 0};
25static const WCHAR ideograph_space = (WCHAR)0x3000; /* fullwidth space */
26static const WCHAR s_str[] = {L'A', 0x9580, 'B', 0};
29
32
33static BOOL IsCJKCodePage(_In_ UINT CodePage)
34{
35 switch (CodePage)
36 {
37 case 932: // Japanese
38 case 949: // Korean
39 case 1361: // Korean (Johab)
40 case 936: // Chinese PRC
41 case 950: // Taiwan
42 return TRUE;
43 }
44 return FALSE;
45}
46
47static __inline
49{
50 switch (CodePage)
51 {
52 case 932: // Japanese (Shift-JIS)
54 case 949: // Korean (Hangul/Wansung)
55 // case 1361: // Korean (Johab)
57 case 936: // Chinese PRC (Chinese Simplified)
59 case 950: // Taiwan (Chinese Traditional)
61 default:
63 }
64}
65
67 _In_ const char* file,
68 _In_ int line,
69 _In_ UINT CodePage)
70{
72
73 /* Validate the code page */
74 bSuccess = IsValidCodePage(CodePage);
75 if (!bSuccess)
76 {
77 skip_(file, line)("Code page %d not available\n", CodePage);
78 return FALSE;
79 }
80
81 /* Set the new code page */
82 SetLastError(0xdeadbeef);
83 bSuccess = SetConsoleOutputCP(CodePage);
84 if (!bSuccess)
85 skip_(file, line)("SetConsoleOutputCP(%d) failed with last error %lu\n", CodePage, GetLastError());
86 return bSuccess;
87}
88
89#define ChangeOutputCP(CodePage) \
90 ChangeOutputCP_(__FILE__, __LINE__, CodePage)
91
92
93#define cmpThreadLangId(file, line, ExpectedLangId) \
94do { \
95 LANGID ThreadLangId; \
96 ThreadLangId = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale); \
97 trace_((file), (line))("Thread LangId %d, expecting %d...\n", \
98 ThreadLangId, (ExpectedLangId)); \
99 ok_((file), (line))(ThreadLangId == (ExpectedLangId), \
100 "Thread LangId %d, expected %d\n", \
101 ThreadLangId, (ExpectedLangId)); \
102} while (0)
103
104static BOOL
106 _In_ const char* file,
107 _In_ int line,
108 _In_ UINT CodePage,
109 _In_ LANGID ExpectedLangId)
110{
111 UINT newcp;
112
113 /* Verify and set the new code page */
114 if (!ChangeOutputCP_(file, line, CodePage))
115 {
116 skip_(file, line)("Code page %d expected to be valid!\n", CodePage);
117 return FALSE;
118 }
119
120 newcp = GetConsoleOutputCP();
121 ok_(file, line)(newcp == CodePage, "Console output CP is %d, expected %d\n", newcp, CodePage);
122
123 /* Verify that the thread lang ID is the expected one */
124 cmpThreadLangId(file, line, ExpectedLangId);
125 return TRUE;
126}
127
128#define doTest_CP_ThreadLang(...) \
129 doTest_CP_ThreadLang_(__FILE__, __LINE__, ##__VA_ARGS__)
130
132{
133 /* Save the initial current thread locale. It is (re)initialized after
134 * attaching to a console. Don't use GetThreadLocale() as the latter
135 * can return a replacement value in case CurrentLocale is 0. */
136 LANGID ThreadLangId = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale);
137 UINT oldcp = GetConsoleOutputCP();
138
140 {
141 /* We are on a CJK system */
142
143 /* Is the console in CJK? If so, current thread should be in CJK language */
144 if (!IsCJKCodePage(oldcp))
145 {
146 skip("CJK system but console CP not in CJK\n");
147 }
148 else
149 {
150 /* Check that the thread lang ID matches what the console set */
151 LANGID LangId = MapCJKCPToLangId(oldcp);
152 cmpThreadLangId(__FILE__, __LINE__, LangId);
153 }
154
155 /* Set the code page to OEM USA (non-CJK codepage that is supported).
156 * Verify that the thread lang ID has changed to non-CJK language. */
158
159 /* Set the code page to the default system CJK codepage.
160 * Check that the thread lang ID matches what the console set. */
162 }
163 else
164 {
165 /* We are on a non-CJK system */
166
167 /* Code pages: Japanese, Korean, Chinese Simplified/Traditional */
168 UINT CJKCodePages[] = {932, 949, 936, 950};
169 UINT newcp;
170 USHORT i;
171
172 /* Switch to a different code page (OEM USA) than the current one.
173 * In such setup, the current thread lang ID should not change. */
174 newcp = (s_uOEMCP == 437 ? 850 : 437);
175 doTest_CP_ThreadLang(newcp, ThreadLangId);
176
177 /* Try switching to a CJK codepage, if possible, but
178 * the thread lang ID should not change either... */
179
180 /* Retry as long as no valid CJK codepage has been found */
181 for (i = 0; i < ARRAYSIZE(CJKCodePages); ++i)
182 {
183 newcp = CJKCodePages[i];
184 if (IsValidCodePage(newcp))
185 break; // Found a valid one.
186 }
187 if (i >= ARRAYSIZE(CJKCodePages))
188 {
189 /* No valid CJK code pages on the system */
190 skip("CJK system but console CP not in CJK\n");
191 }
192 else
193 {
194 /* Verify that the thread lang ID remains the same */
195 doTest_CP_ThreadLang(newcp, ThreadLangId);
196 }
197 }
198
199 /* Restore code page */
200 SetConsoleOutputCP(oldcp);
201}
202
203
204/* Russian Code Page 855 */
205// NOTE that CP 866 can also be used
206static void test_cp855(HANDLE hConOut)
207{
208 BOOL ret;
209 UINT oldcp;
210 int n;
211 DWORD len;
212 COORD c;
214 int count;
215 WCHAR str[32];
216 WORD attrs[16];
217
218 /* Set code page */
219 oldcp = GetConsoleOutputCP();
220 if (!ChangeOutputCP(855))
221 {
222 skip("Codepage 855 not available\n");
223 return;
224 }
225
226 /* Get info */
227 ret = GetConsoleScreenBufferInfo(hConOut, &csbi);
228 ok(ret, "GetConsoleScreenBufferInfo failed\n");
229 trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi.dwSize.X, csbi.dwSize.Y);
230 count = 200;
231
232 /* "\u0414" */
233 {
234 /* Output u0414 "count" times at (0,0) */
235 c.X = c.Y = 0;
236 SetConsoleCursorPosition(hConOut, c);
237 okCURSOR(hConOut, c);
238 for (n = 0; n < count; ++n)
239 {
240 ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
241 ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
242 }
243
244 /* Check cursor */
245 len = count; /* u0414 is normal width in Russian */
246 c.X = (SHORT)(len % csbi.dwSize.X);
247 c.Y = (SHORT)(len / csbi.dwSize.X);
248 okCURSOR(hConOut, c);
249
250 /* Read characters at (0,0) */
251 c.X = c.Y = 0;
252 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
253 ok(ret, "ReadConsoleOutputCharacterW failed\n");
254 ok_long(len, 6);
255 ok_int(str[0], 0x414);
256 ok_int(str[1], 0x414);
257 ok_int(str[2], 0x414);
258
259 /* Read attributes at (0,0) */
260 c.X = c.Y = 0;
261 ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
262 ok(ret, "ReadConsoleOutputAttribute failed\n");
263 ok_long(len, 6);
264 ok_int(attrs[0], ATTR);
265
266 /* Check cursor */
267 c.X = 1;
268 c.Y = 0;
269 ret = SetConsoleCursorPosition(hConOut, c);
270 ok(ret, "SetConsoleCursorPosition failed\n");
271 okCURSOR(hConOut, c);
272
273 /* Fill by space */
274 c.X = c.Y = 0;
275 FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
276
277 /* Output u0414 "count" times at (1,0) */
278 c.X = 1;
279 c.Y = 0;
280 SetConsoleCursorPosition(hConOut, c);
281 okCURSOR(hConOut, c);
282 for (n = 0; n < count; ++n)
283 {
284 ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
285 ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
286 }
287
288 /* Check cursor */
289 len = 1 + count;
290 c.X = (SHORT)(len % csbi.dwSize.X);
291 c.Y = (SHORT)(len / csbi.dwSize.X);
292 okCURSOR(hConOut, c);
293
294 /* Read characters at (0,0) */
295 c.X = c.Y = 0;
296 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
297 ok(ret, "ReadConsoleOutputCharacterW failed\n");
298 ok_long(len, 6);
299 ok_int(str[0], L' ');
300 ok_int(str[1], 0x414);
301 ok_int(str[2], 0x414);
302 }
303
304 /* "\u9580" */
305 {
306 /* Output u9580 "count" times at (0,0) */
307 c.X = c.Y = 0;
308 SetConsoleCursorPosition(hConOut, c);
309 okCURSOR(hConOut, c);
310 for (n = 0; n < count; ++n)
311 {
312 ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
313 ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
314 }
315
316 /* Check cursor */
317 len = count; /* u9580 is normal width in Russian */
318 c.X = (SHORT)(len % csbi.dwSize.X);
319 c.Y = (SHORT)(len / csbi.dwSize.X);
320 okCURSOR(hConOut, c);
321
322 /* Check cursor */
323 c.X = 1;
324 c.Y = 0;
325 ret = SetConsoleCursorPosition(hConOut, c);
326 ok(ret, "SetConsoleCursorPosition failed\n");
327 okCURSOR(hConOut, c);
328
329 /* Fill by space */
330 c.X = c.Y = 0;
331 ret = FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
332 ok(ret, "FillConsoleOutputCharacterW failed\n");
333 ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
334
335 /* Output u9580 "count" times at (1,0) */
336 c.X = 1;
337 c.Y = 0;
338 SetConsoleCursorPosition(hConOut, c);
339 okCURSOR(hConOut, c);
340 for (n = 0; n < count; ++n)
341 {
342 ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
343 ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
344 }
345
346 /* Check cursor */
347 len = 1 + count;
348 c.X = (SHORT)(len % csbi.dwSize.X);
349 c.Y = (SHORT)(len / csbi.dwSize.X);
350 okCURSOR(hConOut, c);
351
352 /* Fill by ideograph space */
353 c.X = c.Y = 0;
354 ret = FillConsoleOutputCharacterW(hConOut, ideograph_space, csbi.dwSize.X * csbi.dwSize.Y, c, &len);
355 ok(ret, "FillConsoleOutputCharacterW failed\n");
356 ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
357
358 /* Read characters at (0,0) */
359 c.X = c.Y = 0;
360 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
361 ok(ret, "ReadConsoleOutputCharacterW failed\n");
362 ok_long(len, 6);
363 ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
364 ok(str[1] == ideograph_space || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
365 ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
366
367 /* Read attributes at (0,0) */
368 c.X = c.Y = 0;
369 ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
370 ok(ret, "ReadConsoleOutputAttribute failed\n");
371 ok_long(len, 6);
372 ok_int(attrs[0], ATTR);
373
374 /* Read characters at (1,0) */
375 c.X = 1;
376 c.Y = 0;
377 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
378 ok(ret, "ReadConsoleOutputCharacterW failed\n");
379 ok_long(len, 6);
380 ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
381 ok(str[1] == ideograph_space || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
382 ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
383
384 /* Output u9580 "count" once at (1,0) */
385 c.X = 1;
386 c.Y = 0;
387 SetConsoleCursorPosition(hConOut, c);
388 okCURSOR(hConOut, c);
389 ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
390 ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
391
392 /* Read attributes at (1,0) */
393 c.X = 1;
394 c.Y = 0;
395 ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
396 ok(ret, "ReadConsoleOutputAttribute failed\n");
397 ok_long(len, 1);
398 ok_int(attrs[0], ATTR);
399
400 /* Check cursor */
401 c.X = 2;
402 c.Y = 0;
403 okCURSOR(hConOut, c);
404
405 /* Read characters at (0,0) */
406 c.X = c.Y = 0;
407 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
408 ok(ret, "ReadConsoleOutputCharacterW failed\n");
409 ok_long(len, 6);
410 ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
411 ok(str[1] == u9580[0] || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
412 ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
413 }
414
415 /* Restore code page */
416 SetConsoleOutputCP(oldcp);
417}
418
419/* Japanese Code Page 932 */
420static void test_cp932(HANDLE hConOut)
421{
422 BOOL ret;
423 UINT oldcp;
424 int n;
425 DWORD len;
426 COORD c, buffSize;
428 int count;
429 WCHAR str[32];
430 WORD attrs[16];
431 CHAR_INFO buff[16];
432 SMALL_RECT sr;
433
434 /* Set code page */
435 oldcp = GetConsoleOutputCP();
436 if (!ChangeOutputCP(932))
437 {
438 skip("Codepage 932 not available\n");
439 return;
440 }
441
442 /* Get info */
443 ret = GetConsoleScreenBufferInfo(hConOut, &csbi);
444 ok(ret, "GetConsoleScreenBufferInfo failed\n");
445 trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi.dwSize.X, csbi.dwSize.Y);
446 count = 200;
447
448 /* "\u0414" */
449 {
450 /* Output u0414 "count" times at (0,0) */
451 c.X = c.Y = 0;
452 SetConsoleCursorPosition(hConOut, c);
453 okCURSOR(hConOut, c);
454 for (n = 0; n < count; ++n)
455 {
456 ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
457 ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
458 }
459
460 /* Check cursor */
461 GetConsoleScreenBufferInfo(hConOut, &csbi);
462 len = count * 2; /* u0414 is fullwidth in Japanese */
463 c.X = (SHORT)(len % csbi.dwSize.X);
464 c.Y = (SHORT)(len / csbi.dwSize.X);
465 okCURSOR(hConOut, c);
466
467 /* Read characters at (0,0) */
468 c.X = c.Y = 0;
469 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
470 ok(ret, "ReadConsoleOutputCharacterW failed\n");
471 ok_long(len, 3);
472 ok_int(str[0], 0x414);
473 ok_int(str[1], 0x414);
474 ok_int(str[2], 0x414);
475
476 /* Read attributes at (0,0) */
477 c.X = c.Y = 0;
478 ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
479 ok(ret, "ReadConsoleOutputAttribute failed\n");
480 ok_long(len, 6);
483
484 /* Check cursor */
485 c.X = 1;
486 c.Y = 0;
487 ret = SetConsoleCursorPosition(hConOut, c);
488 ok(ret, "SetConsoleCursorPosition failed\n");
489 okCURSOR(hConOut, c);
490
491 /* Fill by space */
492 c.X = c.Y = 0;
493 FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
494
495 /* Output u0414 "count" times at (1,0) */
496 c.X = 1;
497 c.Y = 0;
498 SetConsoleCursorPosition(hConOut, c);
499 okCURSOR(hConOut, c);
500 for (n = 0; n < count; ++n)
501 {
502 ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
503 ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
504 }
505
506 /* Check cursor */
507 len = csbi.dwSize.X + (count - (csbi.dwSize.X - 1) / 2) * 2;
508 c.X = (SHORT)(len % csbi.dwSize.X);
509 c.Y = (SHORT)(len / csbi.dwSize.X);
510 okCURSOR(hConOut, c);
511
512 /* Read characters at (0,0) */
513 c.X = 0;
514 c.Y = 0;
515 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
516 ok(ret, "ReadConsoleOutputCharacterW failed\n");
517 ok_long(len, 4);
518 ok_int(str[0], L' ');
519 ok_int(str[1], 0x414);
520 ok_int(str[2], 0x414);
521 }
522
523 /* "\u9580" */
524 {
525 /* Output u9580 "count" times at (0,0) */
526 c.X = c.Y = 0;
527 SetConsoleCursorPosition(hConOut, c);
528 okCURSOR(hConOut, c);
529 for (n = 0; n < count; ++n)
530 {
531 ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
532 ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
533 }
534
535 /* Check cursor */
536 len = count * 2; /* u9580 is fullwidth in Japanese */
537 c.X = (SHORT)(len % csbi.dwSize.X);
538 c.Y = (SHORT)(len / csbi.dwSize.X);
539 okCURSOR(hConOut, c);
540
541 /* Check cursor */
542 c.X = 1;
543 c.Y = 0;
544 ret = SetConsoleCursorPosition(hConOut, c);
545 ok(ret, "SetConsoleCursorPosition failed\n");
546 okCURSOR(hConOut, c);
547
548 /* Fill by space */
549 c.X = c.Y = 0;
550 ret = FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
551 ok(ret, "FillConsoleOutputCharacterW failed\n");
552 ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
553
554 /* Output u9580 "count" times at (1,0) */
555 c.X = 1;
556 c.Y = 0;
557 SetConsoleCursorPosition(hConOut, c);
558 okCURSOR(hConOut, c);
559 for (n = 0; n < count; ++n)
560 {
561 ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
562 ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
563 }
564
565 /* Check cursor */
566 len = csbi.dwSize.X + (count - (csbi.dwSize.X - 1) / 2) * 2;
567 c.X = (SHORT)(len % csbi.dwSize.X);
568 c.Y = (SHORT)(len / csbi.dwSize.X);
569 okCURSOR(hConOut, c);
570
571 /* Fill by ideograph space */
572 c.X = c.Y = 0;
573 ret = FillConsoleOutputCharacterW(hConOut, ideograph_space, csbi.dwSize.X * csbi.dwSize.Y, c, &len);
574 ok(ret, "FillConsoleOutputCharacterW failed\n");
575 if (s_bIs8Plus)
576 ok_long(len, csbi.dwSize.X * csbi.dwSize.Y / 2);
577 else
578 ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
579
580 /* Read characters at (0,0) */
581 c.X = c.Y = 0;
582 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
583 ok(ret, "ReadConsoleOutputCharacterW failed\n");
584 ok_long(len, 3);
588
589 /* Read attributes at (0,0) */
590 c.X = c.Y = 0;
591 ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
592 ok(ret, "ReadConsoleOutputAttribute failed\n");
593 ok_long(len, 6);
600
601 /* Output u9580 "count" once at (1,0) */
602 c.X = 1;
603 c.Y = 0;
604 SetConsoleCursorPosition(hConOut, c);
605 okCURSOR(hConOut, c);
606 ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
607 ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
608
609 /*
610 * Read attributes at (1,0) -
611 * Note that if only one attribute of a fullwidth character
612 * is retrieved, no leading/trailing byte flag is set!
613 */
614 c.X = 1;
615 c.Y = 0;
616 ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
617 ok(ret, "ReadConsoleOutputAttribute failed\n");
618 ok_long(len, 1);
619 ok_int(attrs[0], ATTR);
620
621 /* Check that the same problem happens for the trailing byte */
622 c.X = 2;
623 c.Y = 0;
624 ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
625 ok(ret, "ReadConsoleOutputAttribute failed\n");
626 ok_long(len, 1);
627 ok_int(attrs[0], ATTR);
628
629 /* Read attributes at (1,0) */
630 c.X = 1;
631 c.Y = 0;
632 ret = ReadConsoleOutputAttribute(hConOut, attrs, 2, c, &len);
633 ok(ret, "ReadConsoleOutputAttribute failed\n");
634 ok_long(len, 2);
637
638 /* Read attributes at (1,0) */
639 ret = ReadConsoleOutputAttribute(hConOut, attrs, 3, c, &len);
640 ok(ret, "ReadConsoleOutputAttribute failed\n");
641 ok_long(len, 3);
644 if (s_bIs8Plus)
646 else
647 ok_int(attrs[2], ATTR);
648
649 /* Read attributes at (0,0) */
650 c.X = c.Y = 0;
651 ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
652 ok(ret, "ReadConsoleOutputAttribute failed\n");
653 ok_long(len, 4);
654 if (s_bIs8Plus)
656 else
657 ok_int(attrs[0], ATTR);
660 if (s_bIs8Plus)
662 else
663 ok_int(attrs[3], ATTR);
664
665 /* Check cursor */
666 c.X = 3;
667 c.Y = 0;
668 okCURSOR(hConOut, c);
669
670 /* Read characters */
671 c.X = c.Y = 0;
672 ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
673 ok(ret, "ReadConsoleOutputCharacterW failed\n");
674 if (s_bIs8Plus)
675 {
676 ok_long(len, 3);
678 ok_int(str[1], u9580[0]);
680 }
681 else
682 {
683 ok_long(len, 4);
684 ok_int(str[0], L' ');
685 ok_int(str[1], u9580[0]);
686 ok_int(str[2], L' ');
687 }
688 }
689
690 /* COMMON_LVB_LEADING_BYTE and COMMON_LVB_TRAILING_BYTE for u0414 */
691 {
692 /* set cursor */
693 c.X = c.Y = 0;
694 SetConsoleCursorPosition(hConOut, c);
695 okCURSOR(hConOut, c);
696
697 /* fill by 'A' */
698 ret = FillConsoleOutputCharacterW(hConOut, L'A', csbi.dwSize.X * 2, c, &len);
699 ok_int(ret, 1);
700 ok_long(len, csbi.dwSize.X * 2);
701
702 /* reset buff */
703 buffSize.X = ARRAYSIZE(buff);
704 buffSize.Y = 1;
705 memset(buff, 0x7F, sizeof(buff));
706
707 /* read output */
708 c.X = c.Y = 0;
709 ZeroMemory(&sr, sizeof(sr));
710 sr.Right = buffSize.X - 1;
711 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
712 ok_int(ret, 1);
713 ok_int(sr.Left, 0);
714 ok_int(sr.Top, 0);
715 ok_int(sr.Right, buffSize.X - 1);
716 ok_int(sr.Bottom, 0);
717
718 /* check buff */
719 ok_int(buff[0].Char.UnicodeChar, L'A');
721
722 /* read attr */
723 ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
724 ok_int(ret, 1);
725 ok_long(len, 1);
726 ok_int(attrs[0], ATTR);
727
728 /* read char */
729 c.X = c.Y = 0;
730 memset(str, 0x7F, sizeof(str));
731 ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
732 ok_int(ret, 1);
733 ok_long(len, 4);
734 ok_int(str[0], L'A');
735 ok_int(str[1], L'A');
736 ok_int(str[2], L'A');
737 ok_int(str[3], L'A');
738
739 /* set cursor */
740 c.X = c.Y = 0;
741 SetConsoleCursorPosition(hConOut, c);
742 okCURSOR(hConOut, c);
743
744 /* write u0414 */
745 ret = WriteConsoleW(hConOut, u0414, 1, &len, NULL);
746 ok_int(ret, 1);
747 ok_long(len, 1);
748
749 /* reset buff */
750 buffSize.X = ARRAYSIZE(buff);
751 buffSize.Y = 1;
752 memset(buff, 0x7F, sizeof(buff));
753
754 /* read output */
755 c.X = c.Y = 0;
756 ZeroMemory(&sr, sizeof(sr));
757 sr.Right = buffSize.X - 1;
758 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
759 ok_int(ret, 1);
760 ok_int(sr.Left, 0);
761 ok_int(sr.Top, 0);
762 ok_int(sr.Right, buffSize.X - 1);
763 ok_int(sr.Bottom, 0);
764
765 /* check buff */
766 if (s_bIs8Plus)
767 {
768 ok_int(buff[0].Char.UnicodeChar, 0x0414);
770 ok_int(buff[1].Char.UnicodeChar, 0x0414);
772 }
773 else
774 {
775 ok_int(buff[0].Char.UnicodeChar, 0x0414);
777 ok_int(buff[1].Char.UnicodeChar, L'A');
779 }
780 ok_int(buff[2].Char.UnicodeChar, L'A');
782 ok_int(buff[3].Char.UnicodeChar, L'A');
784
785 /* read attr */
786 ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
787 ok_int(ret, 1);
788 ok_long(len, ARRAYSIZE(attrs));
791 ok_int(attrs[2], ATTR);
792 ok_int(attrs[3], ATTR);
793
794 /* read char */
795 c.X = c.Y = 0;
796 memset(str, 0x7F, sizeof(str));
797 ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
798 ok_int(ret, 1);
799 ok_long(len, 3);
800 ok_int(str[0], 0x0414);
801 ok_int(str[1], L'A');
802 ok_int(str[2], L'A');
803 if (s_bIs8Plus)
804 ok_int(str[3], 0);
805 else
806 ok_int(str[3], 0x7F7F);
807
808 /* set cursor */
809 c.X = 1;
810 c.Y = 0;
811 SetConsoleCursorPosition(hConOut, c);
812 okCURSOR(hConOut, c);
813
814 /* write u0414 */
815 ret = WriteConsoleW(hConOut, u0414, 1, &len, NULL);
816 ok_int(ret, 1);
817 ok_long(len, 1);
818
819 /* read output */
820 c.X = c.Y = 0;
821 ZeroMemory(&sr, sizeof(sr));
822 sr.Right = buffSize.X - 1;
823 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
824 ok_int(ret, 1);
825 ok_int(sr.Left, 0);
826 ok_int(sr.Top, 0);
827 ok_int(sr.Right, buffSize.X - 1);
828 ok_int(sr.Bottom, 0);
829
830 /* check buff */
831 if (s_bIs8Plus)
832 {
833 ok_int(buff[0].Char.UnicodeChar, 0x0414);
835 ok_int(buff[1].Char.UnicodeChar, 0x0414);
837 ok_int(buff[2].Char.UnicodeChar, 0x0414);
839 }
840 else
841 {
842 ok_int(buff[0].Char.UnicodeChar, L' ');
844 ok_int(buff[1].Char.UnicodeChar, 0x0414);
846 ok_int(buff[2].Char.UnicodeChar, L'A');
848 }
849 ok_int(buff[3].Char.UnicodeChar, L'A');
851
852 /* read attr */
853 c.X = c.Y = 0;
854 ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
855 ok_int(ret, 1);
856 ok_long(len, ARRAYSIZE(attrs));
857 if (s_bIs8Plus)
859 else
860 ok_int(attrs[0], ATTR);
863 ok_int(attrs[3], ATTR);
864
865 /* read char */
866 c.X = c.Y = 0;
867 memset(str, 0x7F, sizeof(str));
868 ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
869 ok_int(ret, 1);
870 ok_long(len, 3);
871 if (s_bIs8Plus)
872 {
873 ok_int(str[0], 0x0414);
874 ok_int(str[1], 0x0414);
875 ok_int(str[2], L'A');
876 ok_int(str[3], 0);
877 }
878 else
879 {
880 ok_int(str[0], L' ');
881 ok_int(str[1], 0x0414);
882 ok_int(str[2], L'A');
883 ok_int(str[3], 0x7F7F);
884 }
885
886 /* set cursor */
887 c.X = csbi.dwSize.X - 1;
888 c.Y = 0;
889 SetConsoleCursorPosition(hConOut, c);
890 okCURSOR(hConOut, c);
891
892 /* write u0414 */
893 WriteConsoleW(hConOut, u0414, 1, &len, NULL);
894 ok_int(ret, 1);
895 ok_long(len, 1);
896
897 /* reset buff */
898 buffSize.X = ARRAYSIZE(buff);
899 buffSize.Y = 1;
900 memset(buff, 0x7F, sizeof(buff));
901
902 /* read output */
903 c.X = c.Y = 0;
904 sr.Left = csbi.dwSize.X - 2;
905 sr.Top = 0;
906 sr.Right = csbi.dwSize.X - 1;
907 sr.Bottom = 0;
908 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
909 ok_int(ret, 1);
910 ok_int(sr.Left, csbi.dwSize.X - 2);
911 ok_int(sr.Top, 0);
912 ok_int(sr.Right, csbi.dwSize.X - 1);
913 ok_int(sr.Bottom, 0);
914
915 /* check buff */
916 ok_int(buff[0].Char.UnicodeChar, L'A');
918 ok_int(buff[1].Char.UnicodeChar, L'A');
920
921 /* read attrs */
922 c.X = csbi.dwSize.X - 2;
923 c.Y = 0;
924 ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
925 ok_int(ret, 1);
926 ok_long(len, ARRAYSIZE(attrs));
927 ok_int(attrs[0], ATTR);
928 ok_int(attrs[1], ATTR);
929
930 /* read char */
931 ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
932 ok_int(ret, 1);
933 ok_long(len, 2);
934 ok_int(str[0], L'A');
935 ok_int(str[1], L'A');
936
937 /* fill by 'A' */
938 c.X = c.Y = 0;
939 ret = FillConsoleOutputCharacterW(hConOut, L'A', 10, c, &len);
940 ok_int(ret, 1);
941 ok_long(len, 10);
942
943 /* fill by u0414 */
944 c.X = 1;
945 c.Y = 0;
946 ret = FillConsoleOutputCharacterW(hConOut, 0x0414, 1, c, &len);
947 c.X = c.Y = 0;
948 ok_int(ret, 1);
949 ok_long(len, 1);
950
951 /* reset buff */
952 buffSize.X = ARRAYSIZE(buff);
953 buffSize.Y = 1;
954 memset(buff, 0x7F, sizeof(buff));
955
956 /* read output */
957 c.X = c.Y = 0;
958 sr.Left = 0;
959 sr.Top = 0;
960 sr.Right = 4;
961 sr.Bottom = 0;
962 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
963 ok_int(ret, 1);
964 ok_int(sr.Left, 0);
965 ok_int(sr.Top, 0);
966 ok_int(sr.Right, 4);
967 ok_int(sr.Bottom, 0);
968
969 /* check buff */
970 ok_int(buff[0].Char.UnicodeChar, L'A');
972 if (s_bIs8Plus)
973 {
974 ok_int(buff[1].Char.UnicodeChar, 0x0414);
976 ok_int(buff[2].Char.UnicodeChar, 0x0414);
978 }
979 else
980 {
981 ok_int(buff[1].Char.UnicodeChar, L' ');
983 ok_int(buff[2].Char.UnicodeChar, L'A');
985 }
986 ok_int(buff[3].Char.UnicodeChar, L'A');
988 ok_int(buff[4].Char.UnicodeChar, L'A');
990
991 /* read attrs */
992 c.X = 0;
993 c.Y = 0;
994 ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
995 ok_int(ret, 1);
996 ok_long(len, 4);
997 ok_int(attrs[0], ATTR);
998 if (s_bIs8Plus)
999 {
1000 ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1002 }
1003 else
1004 {
1005 ok_int(attrs[1], ATTR);
1006 ok_int(attrs[2], ATTR);
1007 }
1008 ok_int(attrs[3], ATTR);
1009 }
1010
1011 /* COMMON_LVB_LEADING_BYTE and COMMON_LVB_TRAILING_BYTE for u9580 */
1012 {
1013 /* set cursor */
1014 c.X = c.Y = 0;
1015 SetConsoleCursorPosition(hConOut, c);
1016 okCURSOR(hConOut, c);
1017
1018 /* fill by 'A' */
1019 ret = FillConsoleOutputCharacterW(hConOut, L'A', csbi.dwSize.X * 2, c, &len);
1020 ok_int(ret, 1);
1021 ok_long(len, csbi.dwSize.X * 2);
1022
1023 /* reset buff */
1024 buffSize.X = ARRAYSIZE(buff);
1025 buffSize.Y = 1;
1026 memset(buff, 0x7F, sizeof(buff));
1027
1028 /* read output */
1029 c.X = c.Y = 0;
1030 ZeroMemory(&sr, sizeof(sr));
1031 sr.Right = buffSize.X - 1;
1032 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1033 ok_int(ret, 1);
1034 ok_int(sr.Left, 0);
1035 ok_int(sr.Top, 0);
1036 ok_int(sr.Right, buffSize.X - 1);
1037 ok_int(sr.Bottom, 0);
1038
1039 /* check buff */
1040 ok_int(buff[0].Char.UnicodeChar, L'A');
1042
1043 /* read attr */
1044 ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
1045 ok_int(ret, 1);
1046 ok_long(len, 1);
1047 ok_int(attrs[0], ATTR);
1048
1049 /* read char */
1050 memset(str, 0x7F, sizeof(str));
1051 ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
1052 ok_int(ret, 1);
1053 ok_long(len, 2);
1054 ok_int(str[0], L'A');
1055 ok_int(str[1], L'A');
1056
1057 /* set cursor */
1058 c.X = 0;
1059 c.Y = 0;
1060 SetConsoleCursorPosition(hConOut, c);
1061 okCURSOR(hConOut, c);
1062
1063 /* write u9580 */
1064 ret = WriteConsoleW(hConOut, u9580, 1, &len, NULL);
1065 ok_int(ret, 1);
1066 ok_long(len, 1);
1067
1068 /* reset buff */
1069 buffSize.X = ARRAYSIZE(buff);
1070 buffSize.Y = 1;
1071 memset(buff, 0x7F, sizeof(buff));
1072
1073 /* read output */
1074 c.X = c.Y = 0;
1075 ZeroMemory(&sr, sizeof(sr));
1076 sr.Right = buffSize.X - 1;
1077 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1078 ok_int(ret, 1);
1079 ok_int(sr.Left, 0);
1080 ok_int(sr.Top, 0);
1081 ok_int(sr.Right, buffSize.X - 1);
1082 ok_int(sr.Bottom, 0);
1083
1084 /* check buff */
1085 if (s_bIs8Plus)
1086 {
1087 ok_int(buff[0].Char.UnicodeChar, u9580[0]);
1089 ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1091 }
1092 else
1093 {
1094 ok_int(buff[0].Char.UnicodeChar, u9580[0]);
1096 ok_int(buff[1].Char.UnicodeChar, L'A');
1098 }
1099 ok_int(buff[2].Char.UnicodeChar, L'A');
1101 ok_int(buff[3].Char.UnicodeChar, L'A');
1103
1104 /* read attr */
1105 ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
1106 ok_int(ret, 1);
1107 ok_long(len, ARRAYSIZE(attrs));
1108
1109 ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
1111 ok_int(attrs[2], ATTR);
1112 ok_int(attrs[3], ATTR);
1113
1114 /* read char */
1115 c.X = c.Y = 0;
1116 memset(str, 0x7F, sizeof(str));
1117 ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
1118 ok_int(ret, 1);
1119 ok_long(len, 3);
1120 ok_int(str[0], u9580[0]);
1121 ok_int(str[1], L'A');
1122 ok_int(str[2], L'A');
1123 if (s_bIs8Plus)
1124 ok_int(str[3], 0);
1125 else
1126 ok_int(str[3], 0x7F7F);
1127
1128 /* set cursor */
1129 c.X = 1;
1130 c.Y = 0;
1131 SetConsoleCursorPosition(hConOut, c);
1132 okCURSOR(hConOut, c);
1133
1134 /* write u9580 */
1135 ret = WriteConsoleW(hConOut, u9580, 1, &len, NULL);
1136 ok_int(ret, 1);
1137 ok_long(len, 1);
1138
1139 /* read output */
1140 c.X = c.Y = 0;
1141 ZeroMemory(&sr, sizeof(sr));
1142 sr.Right = buffSize.X - 1;
1143 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1144 ok_int(ret, 1);
1145 ok_int(sr.Left, 0);
1146 ok_int(sr.Top, 0);
1147 ok_int(sr.Right, buffSize.X - 1);
1148 ok_int(sr.Bottom, 0);
1149
1150 /* check buff */
1151 if (s_bIs8Plus)
1152 {
1153 ok_int(buff[0].Char.UnicodeChar, u9580[0]);
1155 ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1157 ok_int(buff[2].Char.UnicodeChar, u9580[0]);
1159 }
1160 else
1161 {
1162 ok_int(buff[0].Char.UnicodeChar, L' ');
1164 ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1166 ok_int(buff[2].Char.UnicodeChar, L'A');
1168 }
1169 ok_int(buff[3].Char.UnicodeChar, L'A');
1171
1172 /* read attr */
1173 c.X = c.Y = 0;
1174 ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
1175 ok_int(ret, 1);
1176 ok_long(len, ARRAYSIZE(attrs));
1177
1178 if (s_bIs8Plus)
1179 {
1180 ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
1181 }
1182 else
1183 {
1184 ok_int(attrs[0], ATTR);
1185 }
1186 ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1188 ok_int(attrs[3], ATTR);
1189
1190 /* set cursor */
1191 c.X = csbi.dwSize.X - 1;
1192 c.Y = 0;
1193 SetConsoleCursorPosition(hConOut, c);
1194 okCURSOR(hConOut, c);
1195
1196 /* write u9580 */
1197 WriteConsoleW(hConOut, u9580, 1, &len, NULL);
1198 ok_int(ret, 1);
1199 ok_long(len, 1);
1200
1201 /* reset buff */
1202 buffSize.X = ARRAYSIZE(buff);
1203 buffSize.Y = 1;
1204 memset(buff, 0x7F, sizeof(buff));
1205
1206 /* read output */
1207 c.X = c.Y = 0;
1208 sr.Left = csbi.dwSize.X - 2;
1209 sr.Top = 0;
1210 sr.Right = csbi.dwSize.X - 1;
1211 sr.Bottom = 0;
1212 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1213 ok_int(ret, 1);
1214 ok_int(sr.Left, csbi.dwSize.X - 2);
1215 ok_int(sr.Top, 0);
1216 ok_int(sr.Right, csbi.dwSize.X - 1);
1217 ok_int(sr.Bottom, 0);
1218
1219 /* check buff */
1220 ok_int(buff[0].Char.UnicodeChar, L'A');
1222 ok_int(buff[1].Char.UnicodeChar, L'A');
1224
1225 /* read attr */
1226 c.X = csbi.dwSize.X - 2;
1227 c.Y = 0;
1228 ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
1229 ok_int(ret, 1);
1230 ok_long(len, ARRAYSIZE(attrs));
1231 ok_int(attrs[0], ATTR);
1232 ok_int(attrs[1], ATTR);
1233
1234 /* read char */
1235 memset(str, 0x7F, sizeof(str));
1236 ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
1237 ok_int(ret, 1);
1238 ok_long(len, 2);
1239 ok_int(str[0], L'A');
1240 ok_int(str[1], L'A');
1241
1242 /* fill by 'A' */
1243 c.X = c.Y = 0;
1244 ret = FillConsoleOutputCharacterW(hConOut, L'A', 10, c, &len);
1245 ok_int(ret, 1);
1246 ok_long(len, 10);
1247
1248 /* fill by u9580 */
1249 c.X = 1;
1250 c.Y = 0;
1251 ret = FillConsoleOutputCharacterW(hConOut, u9580[0], 1, c, &len);
1252 c.X = c.Y = 0;
1253 ok_int(ret, 1);
1254 ok_long(len, 1);
1255
1256 /* reset buff */
1257 buffSize.X = ARRAYSIZE(buff);
1258 buffSize.Y = 1;
1259 memset(buff, 0x7F, sizeof(buff));
1260
1261 /* read output */
1262 c.X = c.Y = 0;
1263 sr.Left = 0;
1264 sr.Top = 0;
1265 sr.Right = 4;
1266 sr.Bottom = 0;
1267 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1268 ok_int(ret, 1);
1269 ok_int(sr.Left, 0);
1270 ok_int(sr.Top, 0);
1271 ok_int(sr.Right, 4);
1272 ok_int(sr.Bottom, 0);
1273
1274 /* check buff */
1275 ok_int(buff[0].Char.UnicodeChar, L'A');
1277 if (s_bIs8Plus)
1278 {
1279 ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1281 ok_int(buff[2].Char.UnicodeChar, u9580[0]);
1283 }
1284 else
1285 {
1286 ok_int(buff[1].Char.UnicodeChar, L' ');
1288 ok_int(buff[2].Char.UnicodeChar, L'A');
1290 }
1291 ok_int(buff[3].Char.UnicodeChar, L'A');
1293 ok_int(buff[4].Char.UnicodeChar, L'A');
1295
1296 /* read attrs */
1297 c.X = 0;
1298 c.Y = 0;
1299 ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
1300 ok_int(ret, 1);
1301 ok_long(len, 4);
1302 ok_int(attrs[0], ATTR);
1303 if (s_bIs8Plus)
1304 {
1305 ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1307 }
1308 else
1309 {
1310 ok_int(attrs[1], ATTR);
1311 ok_int(attrs[2], ATTR);
1312 }
1313 ok_int(attrs[3], ATTR);
1314 }
1315
1316 /* FillConsoleOutputAttribute and WriteConsoleOutput */
1317 {
1318 c.X = c.Y = 0;
1319 SetConsoleCursorPosition(hConOut, c);
1320 okCURSOR(hConOut, c);
1321 for (n = 0; n < count; ++n)
1322 {
1323 ret = WriteConsoleW(hConOut, space, lstrlenW(space), &len, NULL);
1324 ok_int(ret, 1);
1325 ok_long(len, 1);
1326 }
1327
1328 /* fill attrs */
1329 c.X = c.Y = 0;
1330 SetConsoleCursorPosition(hConOut, c);
1331 okCURSOR(hConOut, c);
1332 ret = FillConsoleOutputAttribute(hConOut, 0xFFFF, 2, c, &len);
1333 ok_int(ret, 1);
1334 ok_long(len, 2);
1335
1336 /* read attrs */
1337 memset(attrs, 0x7F, sizeof(attrs));
1338 ret = ReadConsoleOutputAttribute(hConOut, attrs, 3, c, &len);
1339 ok_int(ret, 1);
1340 ok_long(len, 3);
1341 if (s_bIs8Plus)
1342 {
1343 ok_int(attrs[0], 0xDCFF);
1344 ok_int(attrs[1], 0xDCFF);
1345 }
1346 else
1347 {
1348 ok_int(attrs[0], 0xFCFF);
1349 ok_int(attrs[1], 0xFCFF);
1350 }
1351 ok_int(attrs[2], ATTR);
1352
1353 /* fill attrs */
1354 c.X = c.Y = 0;
1355 SetConsoleCursorPosition(hConOut, c);
1356 okCURSOR(hConOut, c);
1357 ret = FillConsoleOutputAttribute(hConOut, ATTR, 4, c, &len);
1358 ok_int(ret, 1);
1359 ok_long(len, 4);
1360
1361 /* write */
1362 c.X = c.Y = 0;
1363 sr.Left = 0;
1364 sr.Top = 0;
1365 sr.Right = 4;
1366 sr.Bottom = 0;
1367 // Check how Read/WriteConsoleOutput() handle inconsistent DBCS flags.
1368 buff[0].Char.UnicodeChar = u9580[0];
1369 buff[0].Attributes = ATTR | COMMON_LVB_LEADING_BYTE;
1370 buff[1].Char.UnicodeChar = u9580[0];
1371 buff[1].Attributes = ATTR | COMMON_LVB_LEADING_BYTE;
1372 buff[2].Char.UnicodeChar = u9580[0];
1373 buff[2].Attributes = ATTR | COMMON_LVB_TRAILING_BYTE;
1374 buff[3].Char.UnicodeChar = L'A';
1375 buff[3].Attributes = ATTR;
1376 buff[4].Char.UnicodeChar = L' ';
1377 buff[4].Attributes = 0xFFFF;
1378 buffSize.X = 4;
1379 buffSize.Y = 1;
1380 ret = WriteConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1381 ok_int(ret, 1);
1382 ok_int(sr.Left, 0);
1383 ok_int(sr.Top, 0);
1384 ok_int(sr.Right, 3);
1385 ok_int(sr.Bottom, 0);
1386
1387 /* read output */
1388 sr.Left = 0;
1389 sr.Top = 0;
1390 sr.Right = 4;
1391 sr.Bottom = 0;
1392 memset(buff, 0x7F, sizeof(buff));
1393 ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1394 ok_int(ret, 1);
1395 ok_int(sr.Left, 0);
1396 ok_int(sr.Top, 0);
1397 ok_int(sr.Right, 3);
1398 ok_int(sr.Bottom, 0);
1399
1400 /* check buff */
1401 if (s_bIs8Plus)
1402 {
1403 ok_int(buff[0].Char.UnicodeChar, u9580[0]);
1405 ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1407 ok_int(buff[2].Char.UnicodeChar, u9580[0]);
1409 ok_int(buff[3].Char.UnicodeChar, L'A');
1411 ok_int(buff[4].Char.UnicodeChar, 0x7F7F);
1412 ok_int(buff[4].Attributes, 0x7F7F);
1413 }
1414 else
1415 {
1416 ok_int(buff[0].Char.UnicodeChar, u9580[0]);
1418 ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1420 ok_int(buff[2].Char.UnicodeChar, 0);
1421 ok_int(buff[2].Attributes, 0);
1422 ok_int(buff[3].Char.UnicodeChar, 0);
1423 ok_int(buff[3].Attributes, 0);
1424 ok_int(buff[4].Char.UnicodeChar, 0x7F7F);
1425 ok_int(buff[4].Attributes, 0x7F7F);
1426 }
1427
1428 /* read attrs */
1429 c.X = c.Y = 0;
1430 memset(attrs, 0x7F, sizeof(attrs));
1431 ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
1432 ok_int(ret, 1);
1433 ok_long(len, 6);
1434 ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
1435 if (s_bIs8Plus)
1436 {
1437 ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1439 ok_int(attrs[3], ATTR);
1440 }
1441 else
1442 {
1444 ok_int(attrs[2], ATTR | COMMON_LVB_LEADING_BYTE);
1446 }
1447 ok_int(attrs[4], ATTR);
1448 ok_int(attrs[5], ATTR);
1449 }
1450
1451 /* WriteConsoleOutputCharacterW and WriteConsoleOutputAttribute */
1452 {
1453 c.X = c.Y = 0;
1454 SetConsoleCursorPosition(hConOut, c);
1455 okCURSOR(hConOut, c);
1456 for (n = 0; n < count; ++n)
1457 {
1458 ret = WriteConsoleW(hConOut, space, lstrlenW(space), &len, NULL);
1459 ok_int(ret, 1);
1460 ok_long(len, 1);
1461 }
1462
1463 /* write attrs */
1464 attrs[0] = ATTR;
1465 attrs[1] = 0xFFFF;
1466 attrs[2] = ATTR;
1467 attrs[3] = 0;
1468 ret = WriteConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
1469 ok_int(ret, 1);
1470 ok_long(len, 4);
1471
1472 /* read attrs */
1473 memset(attrs, 0x7F, sizeof(attrs));
1474 ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
1475 ok_int(ret, 1);
1476 ok_long(len, 4);
1477 ok_int(attrs[0], ATTR);
1478 if (s_bIs8Plus)
1479 ok_int(attrs[1], 0xDCFF);
1480 else
1481 ok_int(attrs[1], 0xFCFF);
1482 ok_int(attrs[2], ATTR);
1483 ok_int(attrs[3], 0);
1484
1485 /* fill attr */
1486 ret = FillConsoleOutputAttribute(hConOut, ATTR, 4, c, &len);
1487 ok_int(ret, 1);
1488 ok_long(len, 4);
1489
1490 /* write char */
1491 ret = WriteConsoleOutputCharacterW(hConOut, s_str, 4, c, &len);
1492 ok_int(ret, 1);
1493 ok_long(len, 4);
1494
1495 /* read attrs */
1496 memset(attrs, 0x7F, sizeof(attrs));
1497 ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
1498 ok_int(ret, 1);
1499 ok_long(len, 4);
1500 ok_int(attrs[0], ATTR);
1501 ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1503 ok_int(attrs[3], ATTR);
1504 }
1505
1506 /* Restore code page */
1507 SetConsoleOutputCP(oldcp);
1508}
1509
1510
1511START_TEST(ConsoleCP)
1512{
1513 HANDLE hConIn, hConOut;
1514 OSVERSIONINFOA osver = { sizeof(osver) };
1515
1516 // https://github.com/reactos/reactos/pull/2131#issuecomment-563189380
1517 GetVersionExA(&osver);
1518 s_bIs8Plus = (osver.dwMajorVersion > 6) ||
1519 (osver.dwMajorVersion == 6 && osver.dwMinorVersion >= 2);
1520
1521 FreeConsole();
1522 ok(AllocConsole(), "Couldn't alloc console\n");
1523
1524 hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1525 hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1526 ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
1527 ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
1528
1529 /* Retrieve the system OEM code page */
1530 s_uOEMCP = GetOEMCP();
1531 trace("Running on %s system (codepage %d)\n",
1532 IsCJKCodePage(s_uOEMCP) ? "CJK" : "Non-CJK",
1533 s_uOEMCP);
1534
1535 /* Test thread lang ID syncing with console code page */
1537
1539 {
1540 if (!IsCJKCodePage(s_uOEMCP))
1541 test_cp855(hConOut);
1542 else
1543 skip("Russian testcase is skipped because of CJK\n");
1544 }
1545 else
1546 {
1547 skip("Russian locale is not installed\n");
1548 }
1549
1551 {
1553 test_cp932(hConOut);
1554 else
1555 skip("Japanese testcase is skipped because of not CJK\n");
1556 }
1557 else
1558 {
1559 skip("Japanese locale is not installed\n");
1560 }
1561
1562 CloseHandle(hConIn);
1563 CloseHandle(hConOut);
1564 FreeConsole();
1565 ok(AllocConsole(), "Couldn't alloc console\n");
1566}
static BOOL doTest_CP_ThreadLang_(_In_ const char *file, _In_ int line, _In_ UINT CodePage, _In_ LANGID ExpectedLangId)
Definition: ConsoleCP.c:105
static void test_cp932(HANDLE hConOut)
Definition: ConsoleCP.c:420
static __inline LANGID MapCJKCPToLangId(_In_ UINT CodePage)
Definition: ConsoleCP.c:48
#define ATTR
Definition: ConsoleCP.c:20
#define ChangeOutputCP(CodePage)
Definition: ConsoleCP.c:89
static BOOL s_bIs8Plus
Definition: ConsoleCP.c:31
static BOOL ChangeOutputCP_(_In_ const char *file, _In_ int line, _In_ UINT CodePage)
Definition: ConsoleCP.c:66
static const LCID lcidRussian
Definition: ConsoleCP.c:28
static VOID test_CP_ThreadLang(VOID)
Definition: ConsoleCP.c:131
#define okCURSOR(hCon, c)
Definition: ConsoleCP.c:11
static const WCHAR ideograph_space
Definition: ConsoleCP.c:25
static UINT s_uOEMCP
Definition: ConsoleCP.c:30
#define cmpThreadLangId(file, line, ExpectedLangId)
Definition: ConsoleCP.c:93
static const WCHAR u0414[]
Definition: ConsoleCP.c:22
static const WCHAR u9580[]
Definition: ConsoleCP.c:23
static void test_cp855(HANDLE hConOut)
Definition: ConsoleCP.c:206
#define doTest_CP_ThreadLang(...)
Definition: ConsoleCP.c:128
static const WCHAR s_str[]
Definition: ConsoleCP.c:26
static const LCID lcidJapanese
Definition: ConsoleCP.c:27
#define ok_long(expression, result)
Definition: atltest.h:133
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define ok_int(expression, result)
Definition: atltest.h:134
BOOL WINAPI SetConsoleOutputCP(IN UINT wCodepage)
Definition: console.c:695
BOOL WINAPI SetConsoleCursorPosition(IN HANDLE hConsoleOutput, IN COORD dwCursorPosition)
Definition: console.c:641
BOOL WINAPI WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, IN LPCWSTR lpCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten)
Definition: console.c:451
BOOL WINAPI AllocConsole(VOID)
Definition: console.c:74
BOOL WINAPI FreeConsole(VOID)
Definition: console.c:156
BOOL WINAPI FillConsoleOutputAttribute(IN HANDLE hConsoleOutput, IN WORD wAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten)
Definition: console.c:525
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:595
#define IsCJKCodePage(CodePage)
Definition: cjkcode.h:27
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define lstrlenW
Definition: compat.h:750
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2451
BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput, OUT LPWORD lpAttribute, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfAttrsRead)
Definition: readwrite.c:1422
BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput, OUT LPWSTR lpCharacter, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfCharsRead)
Definition: readwrite.c:1380
BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleW(IN HANDLE hConsoleOutput, IN CONST VOID *lpBuffer, IN DWORD nNumberOfCharsToWrite, OUT LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
Definition: readwrite.c:1447
BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleOutputW(IN HANDLE hConsoleOutput, IN CONST CHAR_INFO *lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpWriteRegion)
Definition: readwrite.c:1569
BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleOutputW(IN HANDLE hConsoleOutput, OUT PCHAR_INFO lpBuffer, IN COORD dwBufferSize, IN COORD dwBufferCoord, IN OUT PSMALL_RECT lpReadRegion)
Definition: readwrite.c:1338
BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput, IN CONST WORD *lpAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten)
Definition: readwrite.c:1653
BOOL WINAPI DECLSPEC_HOTPATCH FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput, IN WCHAR cCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten)
Definition: readwrite.c:1674
BOOL WINAPI GetVersionExA(IN LPOSVERSIONINFOA lpVersionInformation)
Definition: version.c:69
BOOL WINAPI IsValidCodePage(UINT codepage)
Definition: locale.c:2078
BOOL WINAPI IsValidLocale(LCID lcid, DWORD flags)
Definition: locale.c:2922
UINT WINAPI GetOEMCP(void)
Definition: locale.c:2059
static BOOLEAN bSuccess
Definition: drive.cpp:477
static unsigned char buff[32768]
Definition: fatten.c:17
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble n
Definition: glext.h:7729
const GLubyte * c
Definition: glext.h:8905
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define NtCurrentTeb
#define c
Definition: ke_i.h:80
#define skip_(test, file, line,...)
Definition: kmt_test.h:224
USHORT LANGID
Definition: mui.h:9
#define _In_
Definition: ms_sal.h:308
unsigned int UINT
Definition: ndis.h:50
#define GENERIC_WRITE
Definition: nt_native.h:90
#define SORT_DEFAULT
#define MAKELCID(lgid, srtid)
#define L(x)
Definition: ntvdm.h:50
short SHORT
Definition: pedump.c:59
unsigned short USHORT
Definition: pedump.c:61
const WCHAR * str
#define MAKELANGID(p, s)
Definition: nls.h:15
#define LANG_ENGLISH
Definition: nls.h:52
#define LANGIDFROMLCID(l)
Definition: nls.h:18
#define SUBLANG_CHINESE_TRADITIONAL
Definition: nls.h:208
#define SUBLANG_CHINESE_SIMPLIFIED
Definition: nls.h:209
#define SUBLANG_DEFAULT
Definition: nls.h:168
#define LANG_RUSSIAN
Definition: nls.h:113
#define LANG_CHINESE
Definition: nls.h:42
DWORD LCID
Definition: nls.h:13
#define LANG_JAPANESE
Definition: nls.h:76
#define LANG_KOREAN
Definition: nls.h:84
#define SUBLANG_ENGLISH_US
Definition: nls.h:222
#define SUBLANG_KOREAN
Definition: nls.h:280
#define memset(x, y, z)
Definition: compat.h:39
Definition: bl.h:1338
ULONG Y
Definition: bl.h:1340
ULONG X
Definition: bl.h:1339
ULONG dwMajorVersion
Definition: rtltypes.h:238
ULONG dwMinorVersion
Definition: rtltypes.h:239
SHORT Top
Definition: tui.c:25
SHORT Right
Definition: tui.c:26
SHORT Left
Definition: tui.c:24
SHORT Bottom
Definition: tui.c:27
Definition: fci.c:127
Definition: parser.c:49
SHORT Y
Definition: blue.h:27
SHORT X
Definition: blue.h:26
int ret
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define COMMON_LVB_TRAILING_BYTE
Definition: wincon.h:49
#define COMMON_LVB_LEADING_BYTE
Definition: wincon.h:48
#define LCID_INSTALLED
Definition: winnls.h:201
__wchar_t WCHAR
Definition: xmlstorage.h:180