http://bugs.winehq.org/show_bug.cgi?id=5541
--- Comment #14 from Anastasius Focht focht@gmx.net 2008-01-26 19:40:29 --- Created an attachment (id=10462) --> (http://bugs.winehq.org/attachment.cgi?id=10462) patch which fixes cscript WriteConsoleA/W stdout problem
Hello again,
some re-thoughts ... After digging in MSDN, I find this cscript behaviour similar to the "remarks" section of WriteConsoleW() MSDN documention (http://msdn2.microsoft.com/en-us/library/ms687401.aspx).
--- quote --- .. 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 ---
The problem is that cscript.exe doesn't call "GetConsoleMode" as suggested by remarks section to determine output target. As outlined earlier, it's using:
--- snip --- if( GetFileType( GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR) { /* console mode */ } else { /* redirected */ } --- snip ---
If not redirected, wine GetFileType( GetStdHandle( std_handle )) will return FILE_TYPE_CHAR for all 3 std handles because the underlying NtQueryVolumeInformationFile -> get_device_info() -> FILE_DEVICE_UNKNOWN is mapped to FILE_TYPE_CHAR. Cscript thinks it's in true console mode, calling WriteConsoleW() for output. In all other cases (redirect/pipe), WriteFile() is used.
Because the std handles are not real wine-style console handles (registered consoles in wine server), cscript WriteConsoleW calls will subsequently fail:
--- snip --- BOOL WINAPI WriteConsoleW( .. ) { if (!GetConsoleMode(hConsoleOutput, &mode) || !GetConsoleScreenBufferInfo(hConsoleOutput, &csbi)) return FALSE; --- snip ---
Cscript and the scripting engine inproc server don't use any other console API functions. That WriteConsoleW() is only used for line based output.
For the time being I made a small not-very-intrusive patch. There might be better (general) solutions to attack this problem like msvcrt-style process stdio handles (requires some work/rethoughts) but for now it's sufficient.
It fixes the problem by using a WriteFile fallback in WriteConsoleA/W(). If WriteConsoleA/W() is used on redirected handles it fails on purpose (matches MSDN). Although MSDN says WriteFile() shouldn't use UNICODE on console/std handles this seems not a problem in wine. In fact it works nicely (omitting double conversion for ansi case).
Regards