Fix xcopy so output is either unicode (console) or oem (file)

Kirill K. Smirnov lich at math.spbu.ru
Sat Apr 21 04:14:11 CDT 2007


No, from this point of view the patch is correct.
>> +/* 
>=========================================================================
>> + * Output a formatted unicode string. Ideally this will go to the console
>> + *  and hence required WriteConsoleW to output it, however if file i/o is
>> + *  redirected, it needs to be WriteFile'd using OEM (not ANSI) format
>> + * 
>>========================================================================= 
*/
>The described above behaviour should be implemented either inside of wprintf
>implementation in msvcrt,
Just little test:

#include <windows.h>
#include <stdio.h>

int main(void)
{
    WCHAR str_uni[]={0x044d, 0x0442, 0x043e,
                     0x0020, 0x0442, 0x0435,
                     0x0441, 0x0442, 0x0000};
    char str_oem[]="~]Б╝ ЮЦАА╙╗╘ Б╔╙АБ in OEM";

    wprintf(str_uni);
    printf(str_oem);
    return 0;
}

It will write both strings in wine and only second in windows. wprintf should 
not write unicode strings to console.

>or inside of the console driver of WriteConsoleW 
>depending on the test results IMO.
And not here too. Application must check this itself.
http://msdn2.microsoft.com/en-us/library/ms687401.aspx contains tips:
[quote]
Both WriteConsole and WriteFile can be used for console I/O. While 
WriteConsole supports writing Unicode characters to a console screen buffer, 
WriteFile does not. However, WriteConsole fails if it is used with a standard 
handle that is redirected to a file. If an application handles multilingual 
output that can be redirected, determine whether the output handle is a 
console handle (one method is to call the GetConsoleMode function and check 
whether it succeeds). If the handle is a console handle, call WriteConsole; 
otherwise, the output is redirected and you should call WideCharToMultiByte 
to convert the text to the current code page and WriteFile to perform the 
I/O.
[/quote]

There are some my tests at:
http://www.winehq.com/pipermail/wine-devel/2007-April/056102.html
I could miss something, it would be great if you check it!



I've just found another bug in the patch:

>+      /* Convert to OEM, then output */
>+      convertedChars = WideCharToMultiByte(GetConsoleOutputCP(), 0, 
>output_bufW,
>+                          len, output_bufA, MAX_WRITECONSOLE_SIZE,
>+                          "?", &usedDefaultChar);

The comment is correct, but code is wrong. Here should be CP_OEMCP instead of 
GetConsoleOutputCP().

I did not noticed it before, because there two bugs: one is here, and another 
is in WriteConsoleA (the same bug - should be CP_OEMCP not 
GetConsoleOutputCP()). And they are mutually annihilated ;-)

Test demostrating that WriteConsoleA is wrong:
#include <windows.h>
#include <stdio.h>

int main(void)
{
    DWORD tmp;
    WCHAR str_uni[]={0x044d, 0x0442, 0x043e,
                     0x0020, 0x0442, 0x0435,
                     0x0441, 0x0442, 0x0000};
    char str_oem[]="~]Б╝ ЮЦАА╙╗╘ Б╔╙АБ in OEM\n";

    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str_uni, wcslen(str_uni),
                  &tmp, NULL);
    WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), str_oem, strlen(str_oem),
                  &tmp, NULL);
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str_uni, wcslen(str_uni),
                  &tmp, NULL);
    WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), str_oem, strlen(str_oem),
                  &tmp, NULL);
    SetConsoleCP(866);
    SetConsoleOutputCP(866);
    return 0;
}

=^_^=
--
Kirill



More information about the wine-devel mailing list