[issue25386] msvcrt_putch/msvcrt_putwch don't check the return value of _putch/_putwch

eryksun report at bugs.python.org
Tue Oct 13 17:31:50 EDT 2015


eryksun added the comment:

> It would be interesting to know under what circumstances these 
> functions can fail.

The CRT _put[w]ch and _get[w]ch[e] functions will fail when called in a process that doesn't have a console. (Except get[w]ch may succeed if it follows unget[w]ch.) This is the case when running under pythonw.exe if the process hasn't first attached to a console via AllocConsole() or AttachConsole(). It also applies to python.exe when run as a detached process (i.e. the creation flag DETACHED_PROCESS) or after having detached the console via FreeConsole(). 

Note that even though the docs for get[w]ch [1] and get[w]che [2] state that "[t]here is no error return", these functions actually do return an error value of [W]EOF. This has been the case since at least back to Windows NT. Maybe Steve Dower can shed light on why this is undocumented.

Here's an example, tested on 64-bit Windows 10 in Python 3.5. This example calls the console I/O functions using both msvcrt and ctypes. Since there's no attached console, an error is expected, except when calling ungetwch followed by getwch.

    import os
    import sys
    import subprocess

    cmds_msvcrt = [
        "import msvcrt; msvcrt.ungetwch('a'); msvcrt.getwch()",
        "import msvcrt; msvcrt.ungetwch('a'); msvcrt.ungetwch('a')",
        "import msvcrt; msvcrt.getwch()",
        "import msvcrt; msvcrt.putwch('a')",
    ]

    csetup = "import sys,ctypes; ucrt = ctypes.cdll.ucrtbase; "

    cmds_ctypes = [
        csetup + "ucrt._ungetwch(ord('a')); sys.exit(ucrt._getwch())",
        csetup + "ucrt._ungetwch(ord('a')); sys.exit(ucrt._ungetwch(ord('a')))",
        csetup + "sys.exit(ucrt._getwch())",
        csetup + "sys.exit(ucrt._putwch(ord('a')))",
    ]

    def test(cmds):
        pythonw = os.path.join(sys.prefix, 'pythonw.exe')
        return [subprocess.call([pythonw, '-c', cmd]) for cmd in cmds]
    
    
    >>> test(cmds_msvcrt)
    [0, 1, 0, 0]

    >>> test(cmds_ctypes)
    [97, 65535, 65535, 65535]

65535 is WEOF. 

[1]: https://msdn.microsoft.com/en-us/library/078sfkak
[2]: https://msdn.microsoft.com/en-us/library/kswce429

----------
nosy: +eryksun

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue25386>
_______________________________________


More information about the Python-bugs-list mailing list