ReactOS  0.4.15-dev-1392-g3014417
ConsoleCP.c
Go to the documentation of this file.
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};
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;
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;
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);
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);
535  ok_int(str[1], u9580[0]);
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);
627  ok_int(buff[1].Char.UnicodeChar, 0x0414);
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);
692  ok_int(buff[1].Char.UnicodeChar, 0x0414);
694  ok_int(buff[2].Char.UnicodeChar, 0x0414);
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);
833  ok_int(buff[2].Char.UnicodeChar, 0x0414);
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]);
946  ok_int(buff[1].Char.UnicodeChar, u9580[0]);
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]);
1012  ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1014  ok_int(buff[2].Char.UnicodeChar, u9580[0]);
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]);
1138  ok_int(buff[2].Char.UnicodeChar, u9580[0]);
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]);
1262  ok_int(buff[1].Char.UnicodeChar, u9580[0]);
1264  ok_int(buff[2].Char.UnicodeChar, u9580[0]);
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 
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 
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 }
static const WCHAR u0414[]
Definition: ConsoleCP.c:22
static BOOL IsCJKCodePage(void)
Definition: ConsoleCP.c:31
#define ATTR
Definition: ConsoleCP.c:20
#define MAKELCID(lgid, srtid)
BOOL WINAPI SetConsoleOutputCP(IN UINT wCodepage)
Definition: console.c:692
BOOL WINAPI AllocConsole(VOID)
Definition: console.c:74
ULONG dwMajorVersion
Definition: rtltypes.h:238
#define CloseHandle
Definition: compat.h:598
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 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput, IN WORD wAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten)
Definition: console.c:522
#define TRUE
Definition: types.h:120
BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleW(IN HANDLE hConsoleOutput, IN CONST VOID *lpBuffer, IN DWORD nNumberOfCharsToWrite, OUT LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
Definition: readwrite.c:1447
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define SUBLANG_DEFAULT
Definition: nls.h:168
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
GLdouble n
Definition: glext.h:7729
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
#define ZeroMemory
Definition: winbase.h:1648
DWORD LCID
Definition: nls.h:13
#define ok_long(expression, result)
Definition: atltest.h:133
#define lstrlenW
Definition: compat.h:609
#define LCID_INSTALLED
Definition: winnls.h:198
BOOL WINAPI WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, IN LPCWSTR lpCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten)
Definition: console.c:448
static void test_cp855(HANDLE hConOut)
Definition: ConsoleCP.c:47
#define LANG_JAPANESE
Definition: nls.h:76
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
short SHORT
Definition: pedump.c:59
#define GENERIC_WRITE
Definition: nt_native.h:90
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2453
const WCHAR * str
#define ok_int(expression, result)
Definition: atltest.h:134
BOOL WINAPI SetConsoleCursorPosition(IN HANDLE hConsoleOutput, IN COORD dwCursorPosition)
Definition: console.c:638
static BOOL s_bIs8Plus
Definition: ConsoleCP.c:29
BOOL WINAPI GetVersionExA(IN LPOSVERSIONINFOA lpVersionInformation)
Definition: version.c:69
#define OPEN_EXISTING
Definition: compat.h:634
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:592
SHORT Left
Definition: blue.h:32
ULONG X
Definition: bl.h:1340
BOOL WINAPI FreeConsole(VOID)
Definition: console.c:153
#define trace
Definition: atltest.h:70
SHORT Bottom
Definition: blue.h:35
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define SORT_DEFAULT
BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput, OUT LPWORD lpAttribute, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfAttrsRead)
Definition: readwrite.c:1422
const GLubyte * c
Definition: glext.h:8905
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:611
#define LANG_RUSSIAN
Definition: nls.h:113
SHORT Top
Definition: blue.h:33
static const WCHAR ideograph_space
Definition: ConsoleCP.c:25
BOOL WINAPI IsValidLocale(LCID lcid, DWORD flags)
Definition: lang.c:1548
int ret
static const WCHAR L[]
Definition: oid.c:1250
static const WCHAR s_str[]
Definition: ConsoleCP.c:26
GLenum GLsizei len
Definition: glext.h:6722
ULONG dwMinorVersion
Definition: rtltypes.h:239
#define GENERIC_READ
Definition: compat.h:135
Definition: bl.h:1338
START_TEST(ConsoleCP)
Definition: ConsoleCP.c:1367
BOOL WINAPI IsValidCodePage(UINT CodePage)
Definition: nls.c:1479
static LCID lcidRussian
Definition: ConsoleCP.c:28
#define ok(value,...)
Definition: atltest.h:57
static void test_cp932(HANDLE hConOut)
Definition: ConsoleCP.c:269
#define NULL
Definition: types.h:112
BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput, OUT LPWSTR lpCharacter, IN DWORD nLength, IN COORD dwReadCoord, OUT LPDWORD lpNumberOfCharsRead)
Definition: readwrite.c:1380
static const WCHAR u9580[]
Definition: ConsoleCP.c:23
#define skip(...)
Definition: atltest.h:64
#define okCURSOR(hCon, c)
Definition: ConsoleCP.c:11
#define COMMON_LVB_LEADING_BYTE
Definition: wincon.h:48
#define c
Definition: ke_i.h:80
#define MAKELANGID(p, s)
Definition: nls.h:15
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
#define COMMON_LVB_TRAILING_BYTE
Definition: wincon.h:49
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:599
SHORT Right
Definition: blue.h:34
ULONG Y
Definition: bl.h:1341
#define memset(x, y, z)
Definition: compat.h:39
static unsigned char buff[32768]
Definition: fatten.c:17
static LCID lcidJapanese
Definition: ConsoleCP.c:27
BOOL WINAPI DECLSPEC_HOTPATCH FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput, IN WCHAR cCharacter, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfCharsWritten)
Definition: readwrite.c:1674
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
UINT WINAPI GetOEMCP(VOID)
Definition: nls.c:2195