1/* Testing module for multi-phase initialization of extension modules (PEP 489) 2 */ 3 4#ifndef Py_BUILD_CORE_BUILTIN 5# define Py_BUILD_CORE_MODULE 1 6#endif 7 8#include "Python.h" 9 10#ifdef MS_WINDOWS 11 12#include "pycore_fileutils.h" // _Py_get_osfhandle() 13#include "..\modules\_io\_iomodule.h" 14 15#define WIN32_LEAN_AND_MEAN 16#include <windows.h> 17#include <fcntl.h> 18 19 /* The full definition is in iomodule. We reproduce 20 enough here to get the fd, which is all we want. */ 21typedef struct { 22 PyObject_HEAD 23 int fd; 24} winconsoleio; 25 26 27static int execfunc(PyObject *m) 28{ 29 return 0; 30} 31 32PyModuleDef_Slot testconsole_slots[] = { 33 {Py_mod_exec, execfunc}, 34 {0, NULL}, 35}; 36 37/*[clinic input] 38module _testconsole 39 40_testconsole.write_input 41 file: object 42 s: PyBytesObject 43 44Writes UTF-16-LE encoded bytes to the console as if typed by a user. 45[clinic start generated code]*/ 46 47static PyObject * 48_testconsole_write_input_impl(PyObject *module, PyObject *file, 49 PyBytesObject *s) 50/*[clinic end generated code: output=48f9563db34aedb3 input=4c774f2d05770bc6]*/ 51{ 52 INPUT_RECORD *rec = NULL; 53 54 if (!PyWindowsConsoleIO_Check(file)) { 55 PyErr_SetString(PyExc_TypeError, "expected raw console object"); 56 return NULL; 57 } 58 59 const wchar_t *p = (const wchar_t *)PyBytes_AS_STRING(s); 60 DWORD size = (DWORD)PyBytes_GET_SIZE(s) / sizeof(wchar_t); 61 62 rec = (INPUT_RECORD*)PyMem_Calloc(size, sizeof(INPUT_RECORD)); 63 if (!rec) 64 goto error; 65 66 INPUT_RECORD *prec = rec; 67 for (DWORD i = 0; i < size; ++i, ++p, ++prec) { 68 prec->EventType = KEY_EVENT; 69 prec->Event.KeyEvent.bKeyDown = TRUE; 70 prec->Event.KeyEvent.wRepeatCount = 1; 71 prec->Event.KeyEvent.uChar.UnicodeChar = *p; 72 } 73 74 HANDLE hInput = _Py_get_osfhandle(((winconsoleio*)file)->fd); 75 if (hInput == INVALID_HANDLE_VALUE) 76 goto error; 77 78 DWORD total = 0; 79 while (total < size) { 80 DWORD wrote; 81 if (!WriteConsoleInputW(hInput, &rec[total], (size - total), &wrote)) { 82 PyErr_SetFromWindowsErr(0); 83 goto error; 84 } 85 total += wrote; 86 } 87 88 PyMem_Free((void*)rec); 89 90 Py_RETURN_NONE; 91error: 92 if (rec) 93 PyMem_Free((void*)rec); 94 return NULL; 95} 96 97/*[clinic input] 98_testconsole.read_output 99 file: object 100 101Reads a str from the console as written to stdout. 102[clinic start generated code]*/ 103 104static PyObject * 105_testconsole_read_output_impl(PyObject *module, PyObject *file) 106/*[clinic end generated code: output=876310d81a73e6d2 input=b3521f64b1b558e3]*/ 107{ 108 Py_RETURN_NONE; 109} 110 111#include "clinic\_testconsole.c.h" 112 113PyMethodDef testconsole_methods[] = { 114 _TESTCONSOLE_WRITE_INPUT_METHODDEF 115 _TESTCONSOLE_READ_OUTPUT_METHODDEF 116 {NULL, NULL} 117}; 118 119static PyModuleDef testconsole_def = { 120 PyModuleDef_HEAD_INIT, /* m_base */ 121 "_testconsole", /* m_name */ 122 PyDoc_STR("Test module for the Windows console"), /* m_doc */ 123 0, /* m_size */ 124 testconsole_methods, /* m_methods */ 125 testconsole_slots, /* m_slots */ 126 NULL, /* m_traverse */ 127 NULL, /* m_clear */ 128 NULL, /* m_free */ 129}; 130 131PyMODINIT_FUNC 132PyInit__testconsole(PyObject *spec) 133{ 134 return PyModuleDef_Init(&testconsole_def); 135} 136 137#endif /* MS_WINDOWS */ 138