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