This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eryksun
Recipients BreamoreBoy, Kain, eryksun, petrikas, python-dev, r.david.murray, steve.dower, tim.golden, zach.ware
Date 2015-05-14.23:05:32
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1431644733.4.0.584878723866.issue23995@psf.upfronthosting.co.za>
In-reply-to
Content
Testing getpass shouldn't be that difficult if you use ctypes to call WriteConsoleInput [1]. For example:

    from ctypes import *
    from ctypes.wintypes import *

    kernel32 = WinDLL('kernel32')

    IN, OUT, INOUT = 1, 2, 3
    KEY_EVENT = 0x0001
    STD_INPUT_HANDLE  = -10
    STD_OUTPUT_HANDLE = -11
    STD_ERROR_HANDLE  = -12
    INVALID_HANDLE_VALUE = HANDLE(-1).value

    class KEY_EVENT_RECORD(Structure):
        class UCHAR(Union):
            _fields_ = (('UnicodeChar', WCHAR),
                        ('AsciiChar',   CHAR))
        _fields_ = (('bKeyDown',          BOOL),
                    ('wRepeatCount',      WORD),
                    ('wVirtualKeyCode',   WORD),
                    ('wVirtualScanCode',  WORD),
                    ('uChar',             UCHAR),
                    ('dwControlKeyState', DWORD))

    class INPUT_RECORD(Structure):
        class EVENT(Union):
            _fields_ = (('KeyEvent', KEY_EVENT_RECORD),)
        _fields_ = (('EventType', WORD),
                    ('Event',     EVENT))

    PINPUT_RECORD = POINTER(INPUT_RECORD)

    class HANDLE_IHV(HANDLE):
        @classmethod
        def _check_retval_(cls, retval):
            if retval.value == INVALID_HANDLE_VALUE:
                raise WinError(get_last_error())
            return retval.value

    def errcheck_bool(result, func, args):
        if not result:
            raise WinError(get_last_error())
        return args

    def WINAPI(name, dll, restype, *argspec):
        if argspec:
            argtypes = tuple(p[0] for p in argspec)
            paramflags = tuple(p[1:] for p in argspec)
        else:
            argtypes = paramflags = ()
        prototype = WINFUNCTYPE(restype, *argtypes, use_last_error=True)
        func = prototype((name, dll), paramflags)
        if restype in (BOOL, HANDLE):
            func.errcheck = errcheck_bool
        setattr(dll, name, func)

    WINAPI('GetStdHandle', kernel32, HANDLE_IHV,
            (DWORD, IN, 'nStdHandle'))

    WINAPI('WriteConsoleInputW', kernel32, BOOL,
           (HANDLE,         IN,     'hConsoleInput'),
           (PINPUT_RECORD,  IN,     'lpBuffer'),
           (DWORD,          IN,     'nLength'),
           (LPDWORD,        OUT,    'lpNumberOfEventsWritten'))

    def write_console_input(s):
        hInput = kernel32.GetStdHandle(STD_INPUT_HANDLE)
        recs = (INPUT_RECORD * len(s))()
        for c, rec in zip(s, recs):
            rec.EventType = KEY_EVENT
            rec.Event.KeyEvent.bKeyDown = True
            rec.Event.KeyEvent.wRepeatCount = 1
            rec.Event.KeyEvent.uChar.UnicodeChar = c
        return kernel32.WriteConsoleInputW(hInput, recs, len(recs))

    if __name__ == '__main__':
        import getpass
        test_input = 'Console test input.\n'
        n = write_console_input(test_input)
        assert n == len(test_input)
        read_input = getpass.getpass()
        assert read_input == test_input.rstrip()

This requires that python.exe is run with an attached console (conhost.exe), i.e. the process can't be created as a DETACHED_PROCESS [2] nor can it be run using pythonw.exe without first calling AllocConsole.
    
[1]: https://msdn.microsoft.com/en-us/library/ms687403
[2]: https://msdn.microsoft.com/en-us/library/ms684863
History
Date User Action Args
2015-05-14 23:05:33eryksunsetrecipients: + eryksun, tim.golden, r.david.murray, BreamoreBoy, python-dev, zach.ware, steve.dower, petrikas, Kain
2015-05-14 23:05:33eryksunsetmessageid: <1431644733.4.0.584878723866.issue23995@psf.upfronthosting.co.za>
2015-05-14 23:05:33eryksunlinkissue23995 messages
2015-05-14 23:05:32eryksuncreate