You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.3 KiB

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