On Tue, 23 Aug 2011, Eric Pouech wrote:
Le 03/08/2011 18:07, Francois Gouget a écrit :
WriteFile() checks if the handle corresponds to the console and if it does invokes WriteConsoleA(). This barely escaped an infinite loop but messed up the string encoding as CP_UNIXCP is usually different from CP_ACP.
I noticed this issue while testing the net.exe tool. After making it use WineConsole() I was getting the following outputs:
$ wine net stop Spécifie le service à arrêter. $ ./wine net stop | cat Sp├®cifie le service ├á arr├¬ter.
It turns out that it's because we only get through the WineConsoleW() -> WriteFile() -> WriteConsoleA() loop in the second case.
could you elaborate a bit more. in case of wine ... | cat, the standard output should be a pipe not a console
* net.c is calling GetStdHandle(STD_OUTPUT_HANDLE). * It then passes that to WriteConsoleW() and get_console_bare_fd() does return an fd for it (no idea if that's right or wrong). * So we end up in the WriteFile case and give it wine_server_ptr_handle(console_handle_unmap(hConsoleOutput)). Frankly I don't know what that's supposed to do but when WriteFile() calls is_console_handle() on it it gets TRUE.
so writeconsoleW is supposed to fail
Yes. It does fail when output is a pipe on Windows.
so it would make more sense to simply let WriteConsoleW fail when is_console_handle(hConsoleOutput) is FALSE ? (similar functions as WriteConsoleA, ReadConsoleA/W should be protected the same way)
Currently only three APIs in console.c check is_console_handle(): VerifyConsoleIoHandle(), DuplicateConsoleHandle() and CloseConsoleHandle(). That could certainly be extended to others and things even seems to work if I add a simple 'if (!is_console_handle(hConsoleOutput)) return FALSE;' at the start of WriteConsoleW().
One could then rip out the code in the WriteFile() branch but I'm not sure what the consequences of all this would be or why the WriteFile() case was added in the first place. The author of that code would probably know better than me<g>.