mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	 5e437fb872
			
		
	
	
		5e437fb872
		
			
		
	
	
	
	
		
			
			This works by not caching the handle and instead getting the handle from the file descriptor each time, so that if the actual handle changes by fd redirection closing/opening the console handle beneath our feet, we will keep working correctly.
		
			
				
	
	
		
			133 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| /* Testing module for multi-phase initialization of extension modules (PEP 489)
 | |
|  */
 | |
| 
 | |
| #include "Python.h"
 | |
| 
 | |
| #ifdef MS_WINDOWS
 | |
| 
 | |
| #include "..\modules\_io\_iomodule.h"
 | |
| 
 | |
| #define WIN32_LEAN_AND_MEAN
 | |
| #include <windows.h>
 | |
| #include <fcntl.h>
 | |
| 
 | |
|  /* The full definition is in iomodule. We reproduce
 | |
|  enough here to get the fd, which is all we want. */
 | |
| typedef struct {
 | |
|     PyObject_HEAD
 | |
|     int fd;
 | |
| } winconsoleio;
 | |
| 
 | |
| 
 | |
| static int execfunc(PyObject *m)
 | |
| {
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| PyModuleDef_Slot testconsole_slots[] = {
 | |
|     {Py_mod_exec, execfunc},
 | |
|     {0, NULL},
 | |
| };
 | |
| 
 | |
| /*[clinic input]
 | |
| module _testconsole
 | |
| 
 | |
| _testconsole.write_input
 | |
|     file: object
 | |
|     s: PyBytesObject
 | |
| 
 | |
| Writes UTF-16-LE encoded bytes to the console as if typed by a user.
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testconsole_write_input_impl(PyObject *module, PyObject *file,
 | |
|                               PyBytesObject *s)
 | |
| /*[clinic end generated code: output=48f9563db34aedb3 input=4c774f2d05770bc6]*/
 | |
| {
 | |
|     INPUT_RECORD *rec = NULL;
 | |
| 
 | |
|     if (!PyWindowsConsoleIO_Check(file)) {
 | |
|         PyErr_SetString(PyExc_TypeError, "expected raw console object");
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     const wchar_t *p = (const wchar_t *)PyBytes_AS_STRING(s);
 | |
|     DWORD size = (DWORD)PyBytes_GET_SIZE(s) / sizeof(wchar_t);
 | |
| 
 | |
|     rec = (INPUT_RECORD*)PyMem_Calloc(size, sizeof(INPUT_RECORD));
 | |
|     if (!rec)
 | |
|         goto error;
 | |
| 
 | |
|     INPUT_RECORD *prec = rec;
 | |
|     for (DWORD i = 0; i < size; ++i, ++p, ++prec) {
 | |
|         prec->EventType = KEY_EVENT;
 | |
|         prec->Event.KeyEvent.bKeyDown = TRUE;
 | |
|         prec->Event.KeyEvent.wRepeatCount = 1;
 | |
|         prec->Event.KeyEvent.uChar.UnicodeChar = *p;
 | |
|     }
 | |
| 
 | |
|     HANDLE hInput = _Py_get_osfhandle(((winconsoleio*)file)->fd);
 | |
|     if (hInput == INVALID_HANDLE_VALUE)
 | |
|         goto error;
 | |
| 
 | |
|     DWORD total = 0;
 | |
|     while (total < size) {
 | |
|         DWORD wrote;
 | |
|         if (!WriteConsoleInputW(hInput, &rec[total], (size - total), &wrote)) {
 | |
|             PyErr_SetFromWindowsErr(0);
 | |
|             goto error;
 | |
|         }
 | |
|         total += wrote;
 | |
|     }
 | |
| 
 | |
|     PyMem_Free((void*)rec);
 | |
| 
 | |
|     Py_RETURN_NONE;
 | |
| error:
 | |
|     if (rec)
 | |
|         PyMem_Free((void*)rec);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testconsole.read_output
 | |
|     file: object
 | |
| 
 | |
| Reads a str from the console as written to stdout.
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testconsole_read_output_impl(PyObject *module, PyObject *file)
 | |
| /*[clinic end generated code: output=876310d81a73e6d2 input=b3521f64b1b558e3]*/
 | |
| {
 | |
|     Py_RETURN_NONE;
 | |
| }
 | |
| 
 | |
| #include "clinic\_testconsole.c.h"
 | |
| 
 | |
| PyMethodDef testconsole_methods[] = {
 | |
|     _TESTCONSOLE_WRITE_INPUT_METHODDEF
 | |
|     _TESTCONSOLE_READ_OUTPUT_METHODDEF
 | |
|     {NULL, NULL}
 | |
| };
 | |
| 
 | |
| static PyModuleDef testconsole_def = {
 | |
|     PyModuleDef_HEAD_INIT,                      /* m_base */
 | |
|     "_testconsole",                             /* m_name */
 | |
|     PyDoc_STR("Test module for the Windows console"), /* m_doc */
 | |
|     0,                                          /* m_size */
 | |
|     testconsole_methods,                        /* m_methods */
 | |
|     testconsole_slots,                          /* m_slots */
 | |
|     NULL,                                       /* m_traverse */
 | |
|     NULL,                                       /* m_clear */
 | |
|     NULL,                                       /* m_free */
 | |
| };
 | |
| 
 | |
| PyMODINIT_FUNC
 | |
| PyInit__testconsole(PyObject *spec)
 | |
| {
 | |
|     return PyModuleDef_Init(&testconsole_def);
 | |
| }
 | |
| 
 | |
| #endif /* MS_WINDOWS */
 |