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

Dmitry Timoshkov dmitry at codeweavers.com
Mon Apr 23 02:49:14 CDT 2007


"Kirill K. Smirnov" <lich at math.spbu.ru> wrote:

> 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.

wprintf does write unicode strings to a console, the problem in your test
is that it doesn't change the locale from the default "C" to russian, and
the conversion from unicode to code page simply fails.

I'm attaching a modified version of your test, with some results/conclusions:

WriteConsole uses current console output code page to translate strings.

WriteConsole does produce an output when not redirecting output to a file.

WriteConsole does not produce an output when redirecting output to a file,
returns FALSE and sets last error to 6 (ERROR_INVALID_HANDLE).

wprintf translates unicode strings to current CRT multibyte locale before
printing them either to a console or to a file.

printf doesn't care about locale at all, it simply prints what it has.

So, the patch sent by Jason is OK, except using wchar_t instead of WCHAR.

-- 
Dmitry. 
-------------- next part --------------
#include <windows.h>
#include <stdio.h>
#include <locale.h>

int main(void)
{
    DWORD dummy;
    BOOL ret;
    WCHAR str_uni[]={0x044d, 0x0442, 0x043e,
                     0x0020, 0x0442, 0x0435,
                     0x0441, 0x0442, '\r', '\n', 0x0000};
    char str_cp866[]="â® àãá᪨© ⥪áâ in cp866\n\0\0";
    char str_cp1251[]="Ýòî ðóññêèé òåêñò in cp1251\n\0\0";
    char *loc_str;

    loc_str = setlocale(LC_ALL, NULL);
    printf("current locale %s\n", loc_str);

    loc_str = setlocale(LC_ALL, "Russian");
    printf("current locale %s\n", loc_str);

    SetConsoleOutputCP(866);

    printf("WriteConsoleW: ");
    SetLastError(-1);
    ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str_uni, lstrlenW(str_uni), &dummy, NULL);
    if (!ret) printf("error %d\n", GetLastError());
    printf("WriteConsoleA: ");
    SetLastError(-1);
    ret = WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), str_cp866, lstrlenA(str_cp866), &dummy, NULL);
    if (!ret) printf("error %d\n", GetLastError());
    printf("wprintf(%%ws): ");
    wprintf(L"%ws", L"unicode string ðóññêèé\n");
    printf("printf: ");
    printf("%s", str_cp866);
    printf("printf: ");
    printf("%s", str_cp1251);

    SetConsoleOutputCP(1251);

    printf("WriteConsoleW: ");
    SetLastError(-1);
    ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str_uni, lstrlenW(str_uni), &dummy, NULL);
    if (!ret) printf("error %d\n", GetLastError());
    printf("WriteConsoleA: ");
    SetLastError(-1);
    ret = WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), str_cp1251, lstrlenA(str_cp1251), &dummy, NULL);
    if (!ret) printf("error %d\n", GetLastError());
    printf("wprintf(%%ws): ");
    wprintf(L"%ws", L"unicode string ðóññêèé\n");
    printf("printf: ");
    printf("%s", str_cp866);
    printf("printf: ");
    printf("%s", str_cp1251);

    return 0;
}


More information about the wine-devel mailing list