1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Tests for i18n console.
5  * COPYRIGHT:   Copyright 2017-2020 Katayama Hirofumi MZ
6  *              Copyright 2020 Hermes Belusca-Maito
7  */
8 
9 #include "precomp.h"
10 
11 #define okCURSOR(hCon, c) \
12 do { \
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 
22 static const WCHAR u0414[] = {0x0414, 0}; /* Д */
23 static const WCHAR u9580[] = {0x9580, 0}; /* 門 */
24 static const WCHAR space[] = {L' ', 0};
25 static const WCHAR ideograph_space = (WCHAR)0x3000; /* fullwidth space */
26 static const WCHAR s_str[] = {L'A', 0x9580, 'B', 0};
27 static LCID lcidJapanese = MAKELCID(MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT), SORT_DEFAULT);
28 static LCID lcidRussian  = MAKELCID(MAKELANGID(LANG_RUSSIAN , SUBLANG_DEFAULT), SORT_DEFAULT);
29 static BOOL s_bIs8Plus;
30 
31 static BOOL IsCJKCodePage(void)
32 {
33     switch (GetOEMCP())
34     {
35     case 936:   // Chinese PRC
36     case 932:   // Japanese
37     case 949:   // Korean
38     case 1361:  // Korean (Johab)
39     case 950:   // Taiwan
40         return TRUE;
41     }
42     return FALSE;
43 }
44 
45 /* Russian Code Page 855 */
46 // NOTE that CP 866 can also be used
47 static void test_cp855(HANDLE hConOut)
48 {
49     BOOL ret;
50     DWORD oldcp;
51     int n;
52     DWORD len;
53     COORD c;
54     CONSOLE_SCREEN_BUFFER_INFO csbi;
55     int count;
56     WCHAR str[32];
57     WORD attrs[16];
58 
59     if (!IsValidCodePage(855))
60     {
61         skip("Codepage 855 not available\n");
62         return;
63     }
64 
65     /* Set code page */
66     oldcp = GetConsoleOutputCP();
67     SetLastError(0xdeadbeef);
68     ret = SetConsoleOutputCP(855);
69     if (!ret)
70     {
71         skip("SetConsoleOutputCP failed with last error %lu\n", GetLastError());
72         return;
73     }
74 
75     /* Get info */
76     ret = GetConsoleScreenBufferInfo(hConOut, &csbi);
77     ok(ret, "GetConsoleScreenBufferInfo failed\n");
78     trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi.dwSize.X, csbi.dwSize.Y);
79     count = 200;
80 
81     /* "\u0414" */
82     {
83         /* Output u0414 "count" times at (0,0) */
84         c.X = c.Y = 0;
85         SetConsoleCursorPosition(hConOut, c);
86         okCURSOR(hConOut, c);
87         for (n = 0; n < count; ++n)
88         {
89             ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
90             ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
91         }
92 
93         /* Check cursor */
94         len = count;        /* u0414 is normal width in Russian */
95         c.X = (SHORT)(len % csbi.dwSize.X);
96         c.Y = (SHORT)(len / csbi.dwSize.X);
97         okCURSOR(hConOut, c);
98 
99         /* Read characters at (0,0) */
100         c.X = c.Y = 0;
101         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
102         ok(ret, "ReadConsoleOutputCharacterW failed\n");
103         ok_long(len, 6);
104         ok_int(str[0], 0x414);
105         ok_int(str[1], 0x414);
106         ok_int(str[2], 0x414);
107 
108         /* Read attributes at (0,0) */
109         c.X = c.Y = 0;
110         ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
111         ok(ret, "ReadConsoleOutputAttribute failed\n");
112         ok_long(len, 6);
113         ok_int(attrs[0], ATTR);
114 
115         /* Check cursor */
116         c.X = 1;
117         c.Y = 0;
118         ret = SetConsoleCursorPosition(hConOut, c);
119         ok(ret, "SetConsoleCursorPosition failed\n");
120         okCURSOR(hConOut, c);
121 
122         /* Fill by space */
123         c.X = c.Y = 0;
124         FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
125 
126         /* Output u0414 "count" times at (1,0) */
127         c.X = 1;
128         c.Y = 0;
129         SetConsoleCursorPosition(hConOut, c);
130         okCURSOR(hConOut, c);
131         for (n = 0; n < count; ++n)
132         {
133             ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
134             ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
135         }
136 
137         /* Check cursor */
138         len = 1 + count;
139         c.X = (SHORT)(len % csbi.dwSize.X);
140         c.Y = (SHORT)(len / csbi.dwSize.X);
141         okCURSOR(hConOut, c);
142 
143         /* Read characters at (0,0) */
144         c.X = c.Y = 0;
145         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
146         ok(ret, "ReadConsoleOutputCharacterW failed\n");
147         ok_long(len, 6);
148         ok_int(str[0], L' ');
149         ok_int(str[1], 0x414);
150         ok_int(str[2], 0x414);
151     }
152 
153     /* "\u9580" */
154     {
155         /* Output u9580 "count" times at (0,0) */
156         c.X = c.Y = 0;
157         SetConsoleCursorPosition(hConOut, c);
158         okCURSOR(hConOut, c);
159         for (n = 0; n < count; ++n)
160         {
161             ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
162             ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
163         }
164 
165         /* Check cursor */
166         len = count;        /* u9580 is normal width in Russian */
167         c.X = (SHORT)(len % csbi.dwSize.X);
168         c.Y = (SHORT)(len / csbi.dwSize.X);
169         okCURSOR(hConOut, c);
170 
171         /* Check cursor */
172         c.X = 1;
173         c.Y = 0;
174         ret = SetConsoleCursorPosition(hConOut, c);
175         ok(ret, "SetConsoleCursorPosition failed\n");
176         okCURSOR(hConOut, c);
177 
178         /* Fill by space */
179         c.X = c.Y = 0;
180         ret = FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
181         ok(ret, "FillConsoleOutputCharacterW failed\n");
182         ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
183 
184         /* Output u9580 "count" times at (1,0) */
185         c.X = 1;
186         c.Y = 0;
187         SetConsoleCursorPosition(hConOut, c);
188         okCURSOR(hConOut, c);
189         for (n = 0; n < count; ++n)
190         {
191             ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
192             ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
193         }
194 
195         /* Check cursor */
196         len = 1 + count;
197         c.X = (SHORT)(len % csbi.dwSize.X);
198         c.Y = (SHORT)(len / csbi.dwSize.X);
199         okCURSOR(hConOut, c);
200 
201         /* Fill by ideograph space */
202         c.X = c.Y = 0;
203         ret = FillConsoleOutputCharacterW(hConOut, ideograph_space, csbi.dwSize.X * csbi.dwSize.Y, c, &len);
204         ok(ret, "FillConsoleOutputCharacterW failed\n");
205         ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
206 
207         /* Read characters at (0,0) */
208         c.X = c.Y = 0;
209         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
210         ok(ret, "ReadConsoleOutputCharacterW failed\n");
211         ok_long(len, 6);
212         ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
213         ok(str[1] == ideograph_space || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
214         ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
215 
216         /* Read attributes at (0,0) */
217         c.X = c.Y = 0;
218         ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
219         ok(ret, "ReadConsoleOutputAttribute failed\n");
220         ok_long(len, 6);
221         ok_int(attrs[0], ATTR);
222 
223         /* Read characters at (1,0) */
224         c.X = 1;
225         c.Y = 0;
226         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
227         ok(ret, "ReadConsoleOutputCharacterW failed\n");
228         ok_long(len, 6);
229         ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
230         ok(str[1] == ideograph_space || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
231         ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
232 
233         /* Output u9580 "count" once at (1,0) */
234         c.X = 1;
235         c.Y = 0;
236         SetConsoleCursorPosition(hConOut, c);
237         okCURSOR(hConOut, c);
238         ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
239         ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
240 
241         /* Read attributes at (1,0) */
242         c.X = 1;
243         c.Y = 0;
244         ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
245         ok(ret, "ReadConsoleOutputAttribute failed\n");
246         ok_long(len, 1);
247         ok_int(attrs[0], ATTR);
248 
249         /* Check cursor */
250         c.X = 2;
251         c.Y = 0;
252         okCURSOR(hConOut, c);
253 
254         /* Read characters at (0,0) */
255         c.X = c.Y = 0;
256         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
257         ok(ret, "ReadConsoleOutputCharacterW failed\n");
258         ok_long(len, 6);
259         ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
260         ok(str[1] == u9580[0] || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
261         ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
262     }
263 
264     /* Restore code page */
265     SetConsoleOutputCP(oldcp);
266 }
267 
268 /* Japanese Code Page 932 */
269 static void test_cp932(HANDLE hConOut)
270 {
271     BOOL ret;
272     DWORD oldcp;
273     int n;
274     DWORD len;
275     COORD c, buffSize;
276     CONSOLE_SCREEN_BUFFER_INFO csbi;
277     int count;
278     WCHAR str[32];
279     WORD attrs[16];
280     CHAR_INFO buff[16];
281     SMALL_RECT sr;
282 
283     if (!IsValidCodePage(932))
284     {
285         skip("Codepage 932 not available\n");
286         return;
287     }
288 
289     /* Set code page */
290     oldcp = GetConsoleOutputCP();
291     SetLastError(0xdeadbeef);
292     ret = SetConsoleOutputCP(932);
293     if (!ret)
294     {
295         skip("SetConsoleOutputCP failed with last error %lu\n", GetLastError());
296         return;
297     }
298 
299     /* Get info */
300     ret = GetConsoleScreenBufferInfo(hConOut, &csbi);
301     ok(ret, "GetConsoleScreenBufferInfo failed\n");
302     trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi.dwSize.X, csbi.dwSize.Y);
303     count = 200;
304 
305     /* "\u0414" */
306     {
307         /* Output u0414 "count" times at (0,0) */
308         c.X = c.Y = 0;
309         SetConsoleCursorPosition(hConOut, c);
310         okCURSOR(hConOut, c);
311         for (n = 0; n < count; ++n)
312         {
313             ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
314             ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
315         }
316 
317         /* Check cursor */
318         GetConsoleScreenBufferInfo(hConOut, &csbi);
319         len = count * 2;     /* u0414 is fullwidth in Japanese */
320         c.X = (SHORT)(len % csbi.dwSize.X);
321         c.Y = (SHORT)(len / csbi.dwSize.X);
322         okCURSOR(hConOut, c);
323 
324         /* Read characters at (0,0) */
325         c.X = c.Y = 0;
326         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
327         ok(ret, "ReadConsoleOutputCharacterW failed\n");
328         ok_long(len, 3);
329         ok_int(str[0], 0x414);
330         ok_int(str[1], 0x414);
331         ok_int(str[2], 0x414);
332 
333         /* Read attributes at (0,0) */
334         c.X = c.Y = 0;
335         ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
336         ok(ret, "ReadConsoleOutputAttribute failed\n");
337         ok_long(len, 6);
338         ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
339         ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
340 
341         /* Check cursor */
342         c.X = 1;
343         c.Y = 0;
344         ret = SetConsoleCursorPosition(hConOut, c);
345         ok(ret, "SetConsoleCursorPosition failed\n");
346         okCURSOR(hConOut, c);
347 
348         /* Fill by space */
349         c.X = c.Y = 0;
350         FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
351 
352         /* Output u0414 "count" times at (1,0) */
353         c.X = 1;
354         c.Y = 0;
355         SetConsoleCursorPosition(hConOut, c);
356         okCURSOR(hConOut, c);
357         for (n = 0; n < count; ++n)
358         {
359             ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
360             ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
361         }
362 
363         /* Check cursor */
364         len = csbi.dwSize.X + (count - (csbi.dwSize.X - 1) / 2) * 2;
365         c.X = (SHORT)(len % csbi.dwSize.X);
366         c.Y = (SHORT)(len / csbi.dwSize.X);
367         okCURSOR(hConOut, c);
368 
369         /* Read characters at (0,0) */
370         c.X = 0;
371         c.Y = 0;
372         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
373         ok(ret, "ReadConsoleOutputCharacterW failed\n");
374         ok_long(len, 4);
375         ok_int(str[0], L' ');
376         ok_int(str[1], 0x414);
377         ok_int(str[2], 0x414);
378     }
379 
380     /* "\u9580" */
381     {
382         /* Output u9580 "count" times at (0,0) */
383         c.X = c.Y = 0;
384         SetConsoleCursorPosition(hConOut, c);
385         okCURSOR(hConOut, c);
386         for (n = 0; n < count; ++n)
387         {
388             ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
389             ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
390         }
391 
392         /* Check cursor */
393         len = count * 2;     /* u9580 is fullwidth in Japanese */
394         c.X = (SHORT)(len % csbi.dwSize.X);
395         c.Y = (SHORT)(len / csbi.dwSize.X);
396         okCURSOR(hConOut, c);
397 
398         /* Check cursor */
399         c.X = 1;
400         c.Y = 0;
401         ret = SetConsoleCursorPosition(hConOut, c);
402         ok(ret, "SetConsoleCursorPosition failed\n");
403         okCURSOR(hConOut, c);
404 
405         /* Fill by space */
406         c.X = c.Y = 0;
407         ret = FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
408         ok(ret, "FillConsoleOutputCharacterW failed\n");
409         ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
410 
411         /* Output u9580 "count" times at (1,0) */
412         c.X = 1;
413         c.Y = 0;
414         SetConsoleCursorPosition(hConOut, c);
415         okCURSOR(hConOut, c);
416         for (n = 0; n < count; ++n)
417         {
418             ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
419             ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
420         }
421 
422         /* Check cursor */
423         len = csbi.dwSize.X + (count - (csbi.dwSize.X - 1) / 2) * 2;
424         c.X = (SHORT)(len % csbi.dwSize.X);
425         c.Y = (SHORT)(len / csbi.dwSize.X);
426         okCURSOR(hConOut, c);
427 
428         /* Fill by ideograph space */
429         c.X = c.Y = 0;
430         ret = FillConsoleOutputCharacterW(hConOut, ideograph_space, csbi.dwSize.X * csbi.dwSize.Y, c, &len);
431         ok(ret, "FillConsoleOutputCharacterW failed\n");
432         if (s_bIs8Plus)
433             ok_long(len, csbi.dwSize.X * csbi.dwSize.Y / 2);
434         else
435             ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
436 
437         /* Read characters at (0,0) */
438         c.X = c.Y = 0;
439         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
440         ok(ret, "ReadConsoleOutputCharacterW failed\n");
441         ok_long(len, 3);
442         ok_int(str[0], ideograph_space);
443         ok_int(str[1], ideograph_space);
444         ok_int(str[2], ideograph_space);
445 
446         /* Read attributes at (0,0) */
447         c.X = c.Y = 0;
448         ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
449         ok(ret, "ReadConsoleOutputAttribute failed\n");
450         ok_long(len, 6);
451         ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
452         ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
453         ok_int(attrs[2], ATTR | COMMON_LVB_LEADING_BYTE);
454         ok_int(attrs[3], ATTR | COMMON_LVB_TRAILING_BYTE);
455         ok_int(attrs[4], ATTR | COMMON_LVB_LEADING_BYTE);
456         ok_int(attrs[5], ATTR | COMMON_LVB_TRAILING_BYTE);
457 
458         /* Output u9580 "count" once at (1,0) */
459         c.X = 1;
460         c.Y = 0;
461         SetConsoleCursorPosition(hConOut, c);
462         okCURSOR(hConOut, c);
463         ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
464         ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
465 
466         /*
467          * Read attributes at (1,0) -
468          * Note that if only one attribute of a fullwidth character
469          * is retrieved, no leading/trailing byte flag is set!
470          */
471         c.X = 1;
472         c.Y = 0;
473         ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
474         ok(ret, "ReadConsoleOutputAttribute failed\n");
475         ok_long(len, 1);
476         ok_int(attrs[0], ATTR);
477 
478         /* Check that the same problem happens for the trailing byte */
479         c.X = 2;
480         c.Y = 0;
481         ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
482         ok(ret, "ReadConsoleOutputAttribute failed\n");
483         ok_long(len, 1);
484         ok_int(attrs[0], ATTR);
485 
486         /* Read attributes at (1,0) */
487         c.X = 1;
488         c.Y = 0;
489         ret = ReadConsoleOutputAttribute(hConOut, attrs, 2, c, &len);
490         ok(ret, "ReadConsoleOutputAttribute failed\n");
491         ok_long(len, 2);
492         ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
493         ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
494 
495         /* Read attributes at (1,0) */
496         ret = ReadConsoleOutputAttribute(hConOut, attrs, 3, c, &len);
497         ok(ret, "ReadConsoleOutputAttribute failed\n");
498         ok_long(len, 3);
499         ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
500         ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
501         if (s_bIs8Plus)
502             ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
503         else
504             ok_int(attrs[2], ATTR);
505 
506         /* Read attributes at (0,0) */
507         c.X = c.Y = 0;
508         ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
509         ok(ret, "ReadConsoleOutputAttribute failed\n");
510         ok_long(len, 4);
511         if (s_bIs8Plus)
512             ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
513         else
514             ok_int(attrs[0], ATTR);
515         ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
516         ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
517         if (s_bIs8Plus)
518             ok_int(attrs[3], ATTR | COMMON_LVB_TRAILING_BYTE);
519         else
520             ok_int(attrs[3], ATTR);
521 
522         /* Check cursor */
523         c.X = 3;
524         c.Y = 0;
525         okCURSOR(hConOut, c);
526 
527         /* Read characters */
528         c.X = c.Y = 0;
529         ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
530         ok(ret, "ReadConsoleOutputCharacterW failed\n");
531         if (s_bIs8Plus)
532         {
533             ok_long(len, 3);
534             ok_int(str[0], ideograph_space);
535             ok_int(str[1], u9580[0]);
536             ok_int(str[2], ideograph_space);
537         }
538         else
539         {
540             ok_long(len, 4);
541             ok_int(str[0], L' ');
542             ok_int(str[1], u9580[0]);
543             ok_int(str[2], L' ');
544         }
545     }
546 
547     /* COMMON_LVB_LEADING_BYTE and COMMON_LVB_TRAILING_BYTE for u0414 */
548     {
549         /* set cursor */
550         c.X = c.Y = 0;
551         SetConsoleCursorPosition(hConOut, c);
552         okCURSOR(hConOut, c);
553 
554         /* fill by 'A' */
555         ret = FillConsoleOutputCharacterW(hConOut, L'A', csbi.dwSize.X * 2, c, &len);
556         ok_int(ret, 1);
557         ok_long(len, csbi.dwSize.X * 2);
558 
559         /* reset buff */
560         buffSize.X = ARRAYSIZE(buff);
561         buffSize.Y = 1;
562         memset(buff, 0x7F, sizeof(buff));
563 
564         /* read output */
565         c.X = c.Y = 0;
566         ZeroMemory(&sr, sizeof(sr));
567         sr.Right = buffSize.X - 1;
568         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
569         ok_int(ret, 1);
570         ok_int(sr.Left, 0);
571         ok_int(sr.Top, 0);
572         ok_int(sr.Right, buffSize.X - 1);
573         ok_int(sr.Bottom, 0);
574 
575         /* check buff */
576         ok_int(buff[0].Char.UnicodeChar, L'A');
577         ok_int(buff[0].Attributes, ATTR);
578 
579         /* read attr */
580         ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
581         ok_int(ret, 1);
582         ok_long(len, 1);
583         ok_int(attrs[0], ATTR);
584 
585         /* read char */
586         c.X = c.Y = 0;
587         memset(str, 0x7F, sizeof(str));
588         ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
589         ok_int(ret, 1);
590         ok_long(len, 4);
591         ok_int(str[0], L'A');
592         ok_int(str[1], L'A');
593         ok_int(str[2], L'A');
594         ok_int(str[3], L'A');
595 
596         /* set cursor */
597         c.X = c.Y = 0;
598         SetConsoleCursorPosition(hConOut, c);
599         okCURSOR(hConOut, c);
600 
601         /* write u0414 */
602         ret = WriteConsoleW(hConOut, u0414, 1, &len, NULL);
603         ok_int(ret, 1);
604         ok_long(len, 1);
605 
606         /* reset buff */
607         buffSize.X = ARRAYSIZE(buff);
608         buffSize.Y = 1;
609         memset(buff, 0x7F, sizeof(buff));
610 
611         /* read output */
612         c.X = c.Y = 0;
613         ZeroMemory(&sr, sizeof(sr));
614         sr.Right = buffSize.X - 1;
615         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
616         ok_int(ret, 1);
617         ok_int(sr.Left, 0);
618         ok_int(sr.Top, 0);
619         ok_int(sr.Right, buffSize.X - 1);
620         ok_int(sr.Bottom, 0);
621 
622         /* check buff */
623         if (s_bIs8Plus)
624         {
625             ok_int(buff[0].Char.UnicodeChar, 0x0414);
626             ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
627             ok_int(buff[1].Char.UnicodeChar, 0x0414);
628             ok_int(buff[1].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
629         }
630         else
631         {
632             ok_int(buff[0].Char.UnicodeChar, 0x0414);
633             ok_int(buff[0].Attributes, ATTR);
634             ok_int(buff[1].Char.UnicodeChar, L'A');
635             ok_int(buff[1].Attributes, ATTR);
636         }
637         ok_int(buff[2].Char.UnicodeChar, L'A');
638         ok_int(buff[2].Attributes, ATTR);
639         ok_int(buff[3].Char.UnicodeChar, L'A');
640         ok_int(buff[3].Attributes, ATTR);
641 
642         /* read attr */
643         ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
644         ok_int(ret, 1);
645         ok_long(len, ARRAYSIZE(attrs));
646         ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
647         ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
648         ok_int(attrs[2], ATTR);
649         ok_int(attrs[3], ATTR);
650 
651         /* read char */
652         c.X = c.Y = 0;
653         memset(str, 0x7F, sizeof(str));
654         ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
655         ok_int(ret, 1);
656         ok_long(len, 3);
657         ok_int(str[0], 0x0414);
658         ok_int(str[1], L'A');
659         ok_int(str[2], L'A');
660         if (s_bIs8Plus)
661             ok_int(str[3], 0);
662         else
663             ok_int(str[3], 0x7F7F);
664 
665         /* set cursor */
666         c.X = 1;
667         c.Y = 0;
668         SetConsoleCursorPosition(hConOut, c);
669         okCURSOR(hConOut, c);
670 
671         /* write u0414 */
672         ret = WriteConsoleW(hConOut, u0414, 1, &len, NULL);
673         ok_int(ret, 1);
674         ok_long(len, 1);
675 
676         /* read output */
677         c.X = c.Y = 0;
678         ZeroMemory(&sr, sizeof(sr));
679         sr.Right = buffSize.X - 1;
680         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
681         ok_int(ret, 1);
682         ok_int(sr.Left, 0);
683         ok_int(sr.Top, 0);
684         ok_int(sr.Right, buffSize.X - 1);
685         ok_int(sr.Bottom, 0);
686 
687         /* check buff */
688         if (s_bIs8Plus)
689         {
690             ok_int(buff[0].Char.UnicodeChar, 0x0414);
691             ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
692             ok_int(buff[1].Char.UnicodeChar, 0x0414);
693             ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
694             ok_int(buff[2].Char.UnicodeChar, 0x0414);
695             ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
696         }
697         else
698         {
699             ok_int(buff[0].Char.UnicodeChar, L' ');
700             ok_int(buff[0].Attributes, ATTR);
701             ok_int(buff[1].Char.UnicodeChar, 0x0414);
702             ok_int(buff[1].Attributes, ATTR);
703             ok_int(buff[2].Char.UnicodeChar, L'A');
704             ok_int(buff[2].Attributes, ATTR);
705         }
706         ok_int(buff[3].Char.UnicodeChar, L'A');
707         ok_int(buff[3].Attributes, ATTR);
708 
709         /* read attr */
710         c.X = c.Y = 0;
711         ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
712         ok_int(ret, 1);
713         ok_long(len, ARRAYSIZE(attrs));
714         if (s_bIs8Plus)
715             ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
716         else
717             ok_int(attrs[0], ATTR);
718         ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
719         ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
720         ok_int(attrs[3], ATTR);
721 
722         /* read char */
723         c.X = c.Y = 0;
724         memset(str, 0x7F, sizeof(str));
725         ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
726         ok_int(ret, 1);
727         ok_long(len, 3);
728         if (s_bIs8Plus)
729         {
730             ok_int(str[0], 0x0414);
731             ok_int(str[1], 0x0414);
732             ok_int(str[2], L'A');
733             ok_int(str[3], 0);
734         }
735         else
736         {
737             ok_int(str[0], L' ');
738             ok_int(str[1], 0x0414);
739             ok_int(str[2], L'A');
740             ok_int(str[3], 0x7F7F);
741         }
742 
743         /* set cursor */
744         c.X = csbi.dwSize.X - 1;
745         c.Y = 0;
746         SetConsoleCursorPosition(hConOut, c);
747         okCURSOR(hConOut, c);
748 
749         /* write u0414 */
750         WriteConsoleW(hConOut, u0414, 1, &len, NULL);
751         ok_int(ret, 1);
752         ok_long(len, 1);
753 
754         /* reset buff */
755         buffSize.X = ARRAYSIZE(buff);
756         buffSize.Y = 1;
757         memset(buff, 0x7F, sizeof(buff));
758 
759         /* read output */
760         c.X = c.Y = 0;
761         sr.Left = csbi.dwSize.X - 2;
762         sr.Top = 0;
763         sr.Right = csbi.dwSize.X - 1;
764         sr.Bottom = 0;
765         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
766         ok_int(ret, 1);
767         ok_int(sr.Left, csbi.dwSize.X - 2);
768         ok_int(sr.Top, 0);
769         ok_int(sr.Right, csbi.dwSize.X - 1);
770         ok_int(sr.Bottom, 0);
771 
772         /* check buff */
773         ok_int(buff[0].Char.UnicodeChar, L'A');
774         ok_int(buff[0].Attributes, ATTR);
775         ok_int(buff[1].Char.UnicodeChar, L'A');
776         ok_int(buff[1].Attributes, ATTR);
777 
778         /* read attrs */
779         c.X = csbi.dwSize.X - 2;
780         c.Y = 0;
781         ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
782         ok_int(ret, 1);
783         ok_long(len, ARRAYSIZE(attrs));
784         ok_int(attrs[0], ATTR);
785         ok_int(attrs[1], ATTR);
786 
787         /* read char */
788         ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
789         ok_int(ret, 1);
790         ok_long(len, 2);
791         ok_int(str[0], L'A');
792         ok_int(str[1], L'A');
793 
794         /* fill by 'A' */
795         c.X = c.Y = 0;
796         ret = FillConsoleOutputCharacterW(hConOut, L'A', 10, c, &len);
797         ok_int(ret, 1);
798         ok_long(len, 10);
799 
800         /* fill by u0414 */
801         c.X = 1;
802         c.Y = 0;
803         ret = FillConsoleOutputCharacterW(hConOut, 0x0414, 1, c, &len);
804         c.X = c.Y = 0;
805         ok_int(ret, 1);
806         ok_long(len, 1);
807 
808         /* reset buff */
809         buffSize.X = ARRAYSIZE(buff);
810         buffSize.Y = 1;
811         memset(buff, 0x7F, sizeof(buff));
812 
813         /* read output */
814         c.X = c.Y = 0;
815         sr.Left = 0;
816         sr.Top = 0;
817         sr.Right = 4;
818         sr.Bottom = 0;
819         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
820         ok_int(ret, 1);
821         ok_int(sr.Left, 0);
822         ok_int(sr.Top, 0);
823         ok_int(sr.Right, 4);
824         ok_int(sr.Bottom, 0);
825 
826         /* check buff */
827         ok_int(buff[0].Char.UnicodeChar, L'A');
828         ok_int(buff[0].Attributes, ATTR);
829         if (s_bIs8Plus)
830         {
831             ok_int(buff[1].Char.UnicodeChar, 0x0414);
832             ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
833             ok_int(buff[2].Char.UnicodeChar, 0x0414);
834             ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
835         }
836         else
837         {
838             ok_int(buff[1].Char.UnicodeChar, L' ');
839             ok_int(buff[1].Attributes, ATTR);
840             ok_int(buff[2].Char.UnicodeChar, L'A');
841             ok_int(buff[2].Attributes, ATTR);
842         }
843         ok_int(buff[3].Char.UnicodeChar, L'A');
844         ok_int(buff[3].Attributes, ATTR);
845         ok_int(buff[4].Char.UnicodeChar, L'A');
846         ok_int(buff[4].Attributes, ATTR);
847 
848         /* read attrs */
849         c.X = 0;
850         c.Y = 0;
851         ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
852         ok_int(ret, 1);
853         ok_long(len, 4);
854         ok_int(attrs[0], ATTR);
855         if (s_bIs8Plus)
856         {
857             ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
858             ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
859         }
860         else
861         {
862             ok_int(attrs[1], ATTR);
863             ok_int(attrs[2], ATTR);
864         }
865         ok_int(attrs[3], ATTR);
866     }
867 
868     /* COMMON_LVB_LEADING_BYTE and COMMON_LVB_TRAILING_BYTE for u9580 */
869     {
870         /* set cursor */
871         c.X = c.Y = 0;
872         SetConsoleCursorPosition(hConOut, c);
873         okCURSOR(hConOut, c);
874 
875         /* fill by 'A' */
876         ret = FillConsoleOutputCharacterW(hConOut, L'A', csbi.dwSize.X * 2, c, &len);
877         ok_int(ret, 1);
878         ok_long(len, csbi.dwSize.X * 2);
879 
880         /* reset buff */
881         buffSize.X = ARRAYSIZE(buff);
882         buffSize.Y = 1;
883         memset(buff, 0x7F, sizeof(buff));
884 
885         /* read output */
886         c.X = c.Y = 0;
887         ZeroMemory(&sr, sizeof(sr));
888         sr.Right = buffSize.X - 1;
889         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
890         ok_int(ret, 1);
891         ok_int(sr.Left, 0);
892         ok_int(sr.Top, 0);
893         ok_int(sr.Right, buffSize.X - 1);
894         ok_int(sr.Bottom, 0);
895 
896         /* check buff */
897         ok_int(buff[0].Char.UnicodeChar, L'A');
898         ok_int(buff[0].Attributes, ATTR);
899 
900         /* read attr */
901         ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
902         ok_int(ret, 1);
903         ok_long(len, 1);
904         ok_int(attrs[0], ATTR);
905 
906         /* read char */
907         memset(str, 0x7F, sizeof(str));
908         ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
909         ok_int(ret, 1);
910         ok_long(len, 2);
911         ok_int(str[0], L'A');
912         ok_int(str[1], L'A');
913 
914         /* set cursor */
915         c.X = 0;
916         c.Y = 0;
917         SetConsoleCursorPosition(hConOut, c);
918         okCURSOR(hConOut, c);
919 
920         /* write u9580 */
921         ret = WriteConsoleW(hConOut, u9580, 1, &len, NULL);
922         ok_int(ret, 1);
923         ok_long(len, 1);
924 
925         /* reset buff */
926         buffSize.X = ARRAYSIZE(buff);
927         buffSize.Y = 1;
928         memset(buff, 0x7F, sizeof(buff));
929 
930         /* read output */
931         c.X = c.Y = 0;
932         ZeroMemory(&sr, sizeof(sr));
933         sr.Right = buffSize.X - 1;
934         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
935         ok_int(ret, 1);
936         ok_int(sr.Left, 0);
937         ok_int(sr.Top, 0);
938         ok_int(sr.Right, buffSize.X - 1);
939         ok_int(sr.Bottom, 0);
940 
941         /* check buff */
942         if (s_bIs8Plus)
943         {
944             ok_int(buff[0].Char.UnicodeChar, u9580[0]);
945             ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
946             ok_int(buff[1].Char.UnicodeChar, u9580[0]);
947             ok_int(buff[1].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
948         }
949         else
950         {
951             ok_int(buff[0].Char.UnicodeChar, u9580[0]);
952             ok_int(buff[0].Attributes, ATTR);
953             ok_int(buff[1].Char.UnicodeChar, L'A');
954             ok_int(buff[1].Attributes, ATTR);
955         }
956         ok_int(buff[2].Char.UnicodeChar, L'A');
957         ok_int(buff[2].Attributes, ATTR);
958         ok_int(buff[3].Char.UnicodeChar, L'A');
959         ok_int(buff[3].Attributes, ATTR);
960 
961         /* read attr */
962         ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
963         ok_int(ret, 1);
964         ok_long(len, ARRAYSIZE(attrs));
965 
966         ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
967         ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
968         ok_int(attrs[2], ATTR);
969         ok_int(attrs[3], ATTR);
970 
971         /* read char */
972         c.X = c.Y = 0;
973         memset(str, 0x7F, sizeof(str));
974         ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
975         ok_int(ret, 1);
976         ok_long(len, 3);
977         ok_int(str[0], u9580[0]);
978         ok_int(str[1], L'A');
979         ok_int(str[2], L'A');
980         if (s_bIs8Plus)
981             ok_int(str[3], 0);
982         else
983             ok_int(str[3], 0x7F7F);
984 
985         /* set cursor */
986         c.X = 1;
987         c.Y = 0;
988         SetConsoleCursorPosition(hConOut, c);
989         okCURSOR(hConOut, c);
990 
991         /* write u9580 */
992         ret = WriteConsoleW(hConOut, u9580, 1, &len, NULL);
993         ok_int(ret, 1);
994         ok_long(len, 1);
995 
996         /* read output */
997         c.X = c.Y = 0;
998         ZeroMemory(&sr, sizeof(sr));
999         sr.Right = buffSize.X - 1;
1000         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1001         ok_int(ret, 1);
1002         ok_int(sr.Left, 0);
1003         ok_int(sr.Top, 0);
1004         ok_int(sr.Right, buffSize.X - 1);
1005         ok_int(sr.Bottom, 0);
1006 
1007         /* check buff */
1008         if (s_bIs8Plus)
1009         {
1010             ok_int(buff[0].Char.UnicodeChar, u9580[0]);
1011             ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
1012             ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1013             ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
1014             ok_int(buff[2].Char.UnicodeChar, u9580[0]);
1015             ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
1016         }
1017         else
1018         {
1019             ok_int(buff[0].Char.UnicodeChar, L' ');
1020             ok_int(buff[0].Attributes, ATTR);
1021             ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1022             ok_int(buff[1].Attributes, ATTR);
1023             ok_int(buff[2].Char.UnicodeChar, L'A');
1024             ok_int(buff[2].Attributes, ATTR);
1025         }
1026         ok_int(buff[3].Char.UnicodeChar, L'A');
1027         ok_int(buff[3].Attributes, ATTR);
1028 
1029         /* read attr */
1030         c.X = c.Y = 0;
1031         ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
1032         ok_int(ret, 1);
1033         ok_long(len, ARRAYSIZE(attrs));
1034 
1035         if (s_bIs8Plus)
1036         {
1037             ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
1038         }
1039         else
1040         {
1041             ok_int(attrs[0], ATTR);
1042         }
1043         ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1044         ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
1045         ok_int(attrs[3], ATTR);
1046 
1047         /* set cursor */
1048         c.X = csbi.dwSize.X - 1;
1049         c.Y = 0;
1050         SetConsoleCursorPosition(hConOut, c);
1051         okCURSOR(hConOut, c);
1052 
1053         /* write u9580 */
1054         WriteConsoleW(hConOut, u9580, 1, &len, NULL);
1055         ok_int(ret, 1);
1056         ok_long(len, 1);
1057 
1058         /* reset buff */
1059         buffSize.X = ARRAYSIZE(buff);
1060         buffSize.Y = 1;
1061         memset(buff, 0x7F, sizeof(buff));
1062 
1063         /* read output */
1064         c.X = c.Y = 0;
1065         sr.Left = csbi.dwSize.X - 2;
1066         sr.Top = 0;
1067         sr.Right = csbi.dwSize.X - 1;
1068         sr.Bottom = 0;
1069         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1070         ok_int(ret, 1);
1071         ok_int(sr.Left, csbi.dwSize.X - 2);
1072         ok_int(sr.Top, 0);
1073         ok_int(sr.Right, csbi.dwSize.X - 1);
1074         ok_int(sr.Bottom, 0);
1075 
1076         /* check buff */
1077         ok_int(buff[0].Char.UnicodeChar, L'A');
1078         ok_int(buff[0].Attributes, ATTR);
1079         ok_int(buff[1].Char.UnicodeChar, L'A');
1080         ok_int(buff[1].Attributes, ATTR);
1081 
1082         /* read attr */
1083         c.X = csbi.dwSize.X - 2;
1084         c.Y = 0;
1085         ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
1086         ok_int(ret, 1);
1087         ok_long(len, ARRAYSIZE(attrs));
1088         ok_int(attrs[0], ATTR);
1089         ok_int(attrs[1], ATTR);
1090 
1091         /* read char */
1092         memset(str, 0x7F, sizeof(str));
1093         ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
1094         ok_int(ret, 1);
1095         ok_long(len, 2);
1096         ok_int(str[0], L'A');
1097         ok_int(str[1], L'A');
1098 
1099         /* fill by 'A' */
1100         c.X = c.Y = 0;
1101         ret = FillConsoleOutputCharacterW(hConOut, L'A', 10, c, &len);
1102         ok_int(ret, 1);
1103         ok_long(len, 10);
1104 
1105         /* fill by u9580 */
1106         c.X = 1;
1107         c.Y = 0;
1108         ret = FillConsoleOutputCharacterW(hConOut, u9580[0], 1, c, &len);
1109         c.X = c.Y = 0;
1110         ok_int(ret, 1);
1111         ok_long(len, 1);
1112 
1113         /* reset buff */
1114         buffSize.X = ARRAYSIZE(buff);
1115         buffSize.Y = 1;
1116         memset(buff, 0x7F, sizeof(buff));
1117 
1118         /* read output */
1119         c.X = c.Y = 0;
1120         sr.Left = 0;
1121         sr.Top = 0;
1122         sr.Right = 4;
1123         sr.Bottom = 0;
1124         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1125         ok_int(ret, 1);
1126         ok_int(sr.Left, 0);
1127         ok_int(sr.Top, 0);
1128         ok_int(sr.Right, 4);
1129         ok_int(sr.Bottom, 0);
1130 
1131         /* check buff */
1132         ok_int(buff[0].Char.UnicodeChar, L'A');
1133         ok_int(buff[0].Attributes, ATTR);
1134         if (s_bIs8Plus)
1135         {
1136             ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1137             ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
1138             ok_int(buff[2].Char.UnicodeChar, u9580[0]);
1139             ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
1140         }
1141         else
1142         {
1143             ok_int(buff[1].Char.UnicodeChar, L' ');
1144             ok_int(buff[1].Attributes, ATTR);
1145             ok_int(buff[2].Char.UnicodeChar, L'A');
1146             ok_int(buff[2].Attributes, ATTR);
1147         }
1148         ok_int(buff[3].Char.UnicodeChar, L'A');
1149         ok_int(buff[3].Attributes, ATTR);
1150         ok_int(buff[4].Char.UnicodeChar, L'A');
1151         ok_int(buff[4].Attributes, ATTR);
1152 
1153         /* read attrs */
1154         c.X = 0;
1155         c.Y = 0;
1156         ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
1157         ok_int(ret, 1);
1158         ok_long(len, 4);
1159         ok_int(attrs[0], ATTR);
1160         if (s_bIs8Plus)
1161         {
1162             ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1163             ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
1164         }
1165         else
1166         {
1167             ok_int(attrs[1], ATTR);
1168             ok_int(attrs[2], ATTR);
1169         }
1170         ok_int(attrs[3], ATTR);
1171     }
1172 
1173     /* FillConsoleOutputAttribute and WriteConsoleOutput */
1174     {
1175         c.X = c.Y = 0;
1176         SetConsoleCursorPosition(hConOut, c);
1177         okCURSOR(hConOut, c);
1178         for (n = 0; n < count; ++n)
1179         {
1180             ret = WriteConsoleW(hConOut, space, lstrlenW(space), &len, NULL);
1181             ok_int(ret, 1);
1182             ok_long(len, 1);
1183         }
1184 
1185         /* fill attrs */
1186         c.X = c.Y = 0;
1187         SetConsoleCursorPosition(hConOut, c);
1188         okCURSOR(hConOut, c);
1189         ret = FillConsoleOutputAttribute(hConOut, 0xFFFF, 2, c, &len);
1190         ok_int(ret, 1);
1191         ok_long(len, 2);
1192 
1193         /* read attrs */
1194         memset(attrs, 0x7F, sizeof(attrs));
1195         ret = ReadConsoleOutputAttribute(hConOut, attrs, 3, c, &len);
1196         ok_int(ret, 1);
1197         ok_long(len, 3);
1198         if (s_bIs8Plus)
1199         {
1200             ok_int(attrs[0], 0xDCFF);
1201             ok_int(attrs[1], 0xDCFF);
1202         }
1203         else
1204         {
1205             ok_int(attrs[0], 0xFCFF);
1206             ok_int(attrs[1], 0xFCFF);
1207         }
1208         ok_int(attrs[2], ATTR);
1209 
1210         /* fill attrs */
1211         c.X = c.Y = 0;
1212         SetConsoleCursorPosition(hConOut, c);
1213         okCURSOR(hConOut, c);
1214         ret = FillConsoleOutputAttribute(hConOut, ATTR, 4, c, &len);
1215         ok_int(ret, 1);
1216         ok_long(len, 4);
1217 
1218         /* write */
1219         c.X = c.Y = 0;
1220         sr.Left = 0;
1221         sr.Top = 0;
1222         sr.Right = 4;
1223         sr.Bottom = 0;
1224         // Check how Read/WriteConsoleOutput() handle inconsistent DBCS flags.
1225         buff[0].Char.UnicodeChar = u9580[0];
1226         buff[0].Attributes = ATTR | COMMON_LVB_LEADING_BYTE;
1227         buff[1].Char.UnicodeChar = u9580[0];
1228         buff[1].Attributes = ATTR | COMMON_LVB_LEADING_BYTE;
1229         buff[2].Char.UnicodeChar = u9580[0];
1230         buff[2].Attributes = ATTR | COMMON_LVB_TRAILING_BYTE;
1231         buff[3].Char.UnicodeChar = L'A';
1232         buff[3].Attributes = ATTR;
1233         buff[4].Char.UnicodeChar = L' ';
1234         buff[4].Attributes = 0xFFFF;
1235         buffSize.X = 4;
1236         buffSize.Y = 1;
1237         ret = WriteConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1238         ok_int(ret, 1);
1239         ok_int(sr.Left, 0);
1240         ok_int(sr.Top, 0);
1241         ok_int(sr.Right, 3);
1242         ok_int(sr.Bottom, 0);
1243 
1244         /* read output */
1245         sr.Left = 0;
1246         sr.Top = 0;
1247         sr.Right = 4;
1248         sr.Bottom = 0;
1249         memset(buff, 0x7F, sizeof(buff));
1250         ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
1251         ok_int(ret, 1);
1252         ok_int(sr.Left, 0);
1253         ok_int(sr.Top, 0);
1254         ok_int(sr.Right, 3);
1255         ok_int(sr.Bottom, 0);
1256 
1257         /* check buff */
1258         if (s_bIs8Plus)
1259         {
1260             ok_int(buff[0].Char.UnicodeChar, u9580[0]);
1261             ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
1262             ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1263             ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
1264             ok_int(buff[2].Char.UnicodeChar, u9580[0]);
1265             ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
1266             ok_int(buff[3].Char.UnicodeChar, L'A');
1267             ok_int(buff[3].Attributes, ATTR);
1268             ok_int(buff[4].Char.UnicodeChar, 0x7F7F);
1269             ok_int(buff[4].Attributes, 0x7F7F);
1270         }
1271         else
1272         {
1273             ok_int(buff[0].Char.UnicodeChar, u9580[0]);
1274             ok_int(buff[0].Attributes, ATTR);
1275             ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1276             ok_int(buff[1].Attributes, ATTR);
1277             ok_int(buff[2].Char.UnicodeChar, 0);
1278             ok_int(buff[2].Attributes, 0);
1279             ok_int(buff[3].Char.UnicodeChar, 0);
1280             ok_int(buff[3].Attributes, 0);
1281             ok_int(buff[4].Char.UnicodeChar, 0x7F7F);
1282             ok_int(buff[4].Attributes, 0x7F7F);
1283         }
1284 
1285         /* read attrs */
1286         c.X = c.Y = 0;
1287         memset(attrs, 0x7F, sizeof(attrs));
1288         ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
1289         ok_int(ret, 1);
1290         ok_long(len, 6);
1291         ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
1292         if (s_bIs8Plus)
1293         {
1294             ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1295             ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
1296             ok_int(attrs[3], ATTR);
1297         }
1298         else
1299         {
1300             ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
1301             ok_int(attrs[2], ATTR | COMMON_LVB_LEADING_BYTE);
1302             ok_int(attrs[3], ATTR | COMMON_LVB_TRAILING_BYTE);
1303         }
1304         ok_int(attrs[4], ATTR);
1305         ok_int(attrs[5], ATTR);
1306     }
1307 
1308     /* WriteConsoleOutputCharacterW and WriteConsoleOutputAttribute */
1309     {
1310         c.X = c.Y = 0;
1311         SetConsoleCursorPosition(hConOut, c);
1312         okCURSOR(hConOut, c);
1313         for (n = 0; n < count; ++n)
1314         {
1315             ret = WriteConsoleW(hConOut, space, lstrlenW(space), &len, NULL);
1316             ok_int(ret, 1);
1317             ok_long(len, 1);
1318         }
1319 
1320         /* write attrs */
1321         attrs[0] = ATTR;
1322         attrs[1] = 0xFFFF;
1323         attrs[2] = ATTR;
1324         attrs[3] = 0;
1325         ret = WriteConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
1326         ok_int(ret, 1);
1327         ok_long(len, 4);
1328 
1329         /* read attrs */
1330         memset(attrs, 0x7F, sizeof(attrs));
1331         ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
1332         ok_int(ret, 1);
1333         ok_long(len, 4);
1334         ok_int(attrs[0], ATTR);
1335         if (s_bIs8Plus)
1336             ok_int(attrs[1], 0xDCFF);
1337         else
1338             ok_int(attrs[1], 0xFCFF);
1339         ok_int(attrs[2], ATTR);
1340         ok_int(attrs[3], 0);
1341 
1342         /* fill attr */
1343         ret = FillConsoleOutputAttribute(hConOut, ATTR, 4, c, &len);
1344         ok_int(ret, 1);
1345         ok_long(len, 4);
1346 
1347         /* write char */
1348         ret = WriteConsoleOutputCharacterW(hConOut, s_str, 4, c, &len);
1349         ok_int(ret, 1);
1350         ok_long(len, 4);
1351 
1352         /* read attrs */
1353         memset(attrs, 0x7F, sizeof(attrs));
1354         ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
1355         ok_int(ret, 1);
1356         ok_long(len, 4);
1357         ok_int(attrs[0], ATTR);
1358         ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
1359         ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
1360         ok_int(attrs[3], ATTR);
1361     }
1362 
1363     /* Restore code page */
1364     SetConsoleOutputCP(oldcp);
1365 }
1366 
1367 START_TEST(ConsoleCP)
1368 {
1369     HANDLE hConIn, hConOut;
1370     OSVERSIONINFOA osver = { sizeof(osver) };
1371 
1372     // https://github.com/reactos/reactos/pull/2131#issuecomment-563189380
1373     GetVersionExA(&osver);
1374     s_bIs8Plus = (osver.dwMajorVersion > 6) ||
1375                  (osver.dwMajorVersion == 6 && osver.dwMinorVersion >= 2);
1376 
1377     FreeConsole();
1378     ok(AllocConsole(), "Couldn't alloc console\n");
1379 
1380     hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1381     hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
1382     ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
1383     ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
1384 
1385     if (IsValidLocale(lcidRussian, LCID_INSTALLED))
1386     {
1387         if (!IsCJKCodePage())
1388             test_cp855(hConOut);
1389         else
1390             skip("Russian testcase is skipped because of CJK\n");
1391     }
1392     else
1393     {
1394         skip("Russian locale is not installed\n");
1395     }
1396 
1397     if (IsValidLocale(lcidJapanese, LCID_INSTALLED))
1398     {
1399         if (IsCJKCodePage())
1400             test_cp932(hConOut);
1401         else
1402             skip("Japanese testcase is skipped because of not CJK\n");
1403     }
1404     else
1405     {
1406         skip("Japanese locale is not installed\n");
1407     }
1408 
1409     CloseHandle(hConIn);
1410     CloseHandle(hConOut);
1411     FreeConsole();
1412     ok(AllocConsole(), "Couldn't alloc console\n");
1413 }
1414