2222
2323#define WIN32_LEAN_AND_MEAN
2424#include <windows.h>
25+ #include <fcntl.h>
2526
2627#include "_iomodule.h"
2728
@@ -68,27 +69,34 @@ char _PyIO_get_console_type(PyObject *path_or_fd) {
6869 return _get_console_type (handle );
6970 }
7071
71- PyObject * decoded = Py_None ;
72- Py_INCREF (decoded );
72+ PyObject * decoded , * decoded_upper ;
7373
7474 int d = PyUnicode_FSDecoder (path_or_fd , & decoded );
7575 if (!d ) {
7676 PyErr_Clear ();
77+ return '\0' ;
78+ }
79+ if (!PyUnicode_Check (decoded )) {
7780 Py_CLEAR (decoded );
7881 return '\0' ;
7982 }
83+ decoded_upper = PyObject_CallMethod (decoded , "upper" , "" );
84+ Py_CLEAR (decoded );
85+ if (!decoded_upper ) {
86+ PyErr_Clear ();
87+ return '\0' ;
88+ }
8089
8190 char m = '\0' ;
82- if (!PyUnicode_Check (decoded )) {
83- return '\0' ;
84- } else if (PyUnicode_CompareWithASCIIString (decoded , "CONIN$" ) == 0 ) {
91+ if (PyUnicode_CompareWithASCIIString (decoded_upper , "CONIN$" ) == 0 ) {
8592 m = 'r' ;
86- } else if (PyUnicode_CompareWithASCIIString (decoded , "CONOUT$" ) == 0 ||
87- PyUnicode_CompareWithASCIIString (decoded , "CON" ) == 0 ) {
93+ } else if (PyUnicode_CompareWithASCIIString (decoded_upper , "CONOUT$" ) == 0 ) {
8894 m = 'w' ;
95+ } else if (PyUnicode_CompareWithASCIIString (decoded_upper , "CON" ) == 0 ) {
96+ m = 'x' ;
8997 }
9098
91- Py_CLEAR (decoded );
99+ Py_CLEAR (decoded_upper );
92100 return m ;
93101}
94102
@@ -227,6 +235,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
227235{
228236 const char * s ;
229237 wchar_t * name = NULL ;
238+ char console_type = '\0' ;
230239 int ret = 0 ;
231240 int rwa = 0 ;
232241 int fd = -1 ;
@@ -270,6 +279,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
270279
271280 Py_ssize_t length ;
272281 name = PyUnicode_AsWideCharString (decodedname , & length );
282+ console_type = _PyIO_get_console_type (decodedname );
273283 Py_CLEAR (decodedname );
274284 if (name == NULL )
275285 return -1 ;
@@ -294,12 +304,16 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
294304 goto bad_mode ;
295305 rwa = 1 ;
296306 self -> readable = 1 ;
307+ if (console_type == 'x' )
308+ console_type = 'r' ;
297309 break ;
298310 case 'w' :
299311 if (rwa )
300312 goto bad_mode ;
301313 rwa = 1 ;
302314 self -> writable = 1 ;
315+ if (console_type == 'x' )
316+ console_type = 'w' ;
303317 break ;
304318 default :
305319 PyErr_Format (PyExc_ValueError ,
@@ -327,7 +341,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
327341 }
328342
329343 if (self -> writable )
330- access | = GENERIC_WRITE ;
344+ access = GENERIC_WRITE ;
331345
332346 Py_BEGIN_ALLOW_THREADS
333347 /* Attempt to open for read/write initially, then fall back
@@ -347,12 +361,15 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj,
347361 }
348362 }
349363
350- if (self -> writable && _get_console_type (self -> handle ) != 'w' ) {
364+ if (console_type == '\0' )
365+ console_type = _get_console_type (self -> handle );
366+
367+ if (self -> writable && console_type != 'w' ) {
351368 PyErr_SetString (PyExc_ValueError ,
352369 "Cannot open console input buffer for writing" );
353370 goto error ;
354371 }
355- if (self -> readable && _get_console_type ( self -> handle ) != 'r' ) {
372+ if (self -> readable && console_type != 'r' ) {
356373 PyErr_SetString (PyExc_ValueError ,
357374 "Cannot open console output buffer for reading" );
358375 goto error ;
@@ -440,9 +457,9 @@ _io__WindowsConsoleIO_fileno_impl(winconsoleio *self)
440457 if (self -> fd < 0 && self -> handle != INVALID_HANDLE_VALUE ) {
441458 _Py_BEGIN_SUPPRESS_IPH
442459 if (self -> writable )
443- self -> fd = _open_osfhandle ((intptr_t )self -> handle , 'wb' );
460+ self -> fd = _open_osfhandle ((intptr_t )self -> handle , _O_WRONLY | _O_BINARY );
444461 else
445- self -> fd = _open_osfhandle ((intptr_t )self -> handle , 'rb' );
462+ self -> fd = _open_osfhandle ((intptr_t )self -> handle , _O_RDONLY | _O_BINARY );
446463 _Py_END_SUPPRESS_IPH
447464 }
448465 if (self -> fd < 0 )
@@ -776,7 +793,7 @@ _io__WindowsConsoleIO_readall_impl(winconsoleio *self)
776793 len += n ;
777794 }
778795
779- if (len > 0 && buf [0 ] == '\x1a' && _buflen (self ) == 0 ) {
796+ if (len == 0 || buf [0 ] == '\x1a' && _buflen (self ) == 0 ) {
780797 /* when the result starts with ^Z we return an empty buffer */
781798 PyMem_Free (buf );
782799 return PyBytes_FromStringAndSize (NULL , 0 );
0 commit comments