On Fri, Aug 26, 2016 at 11:28 AM, Jon Ribbens <jon+use...@unequivocal.eu> wrote: > On 2016-08-24, Chris Angelico <ros...@gmail.com> wrote: >> On Thu, Aug 25, 2016 at 7:00 AM, eryk sun <eryk...@gmail.com> wrote: >>> I discovered why "Logs/con.txt" isn't working right in Windows 7, >>> while "Logs/nul.txt" does get redirected correctly to r"\\.\nul". >>> Prior to Windows 8 the console doesn't use an NT device, so the base >>> API has a function named BaseIsThisAConsoleName that looks for names >>> such as r"\\.CON", r"\\.CONIN$", "CON", or r"C:\Temp\con.txt" and >>> returns either "CONIN$" or "CONOUT$" if there's a match. A match for >>> just "CON" maps to one or the other of the latter depending on whether >>> read or write access is desired. >> >> See? This is why *even after I tested it* I wasn't sure I was right! >> The rules are... complicated. > > Hence my doubts about this function - it has almost no chance of not > being broken, potentially leading to whatever code was using it having > security holes. Perhaps it should be deprecated or at least attract a > large caveat in the documentation.
I agree that the docs need a warning that the behavior of paths containing legacy DOS device names is inconsistent between versions of Windows and that the rules that Windows uses aren't explicitly documented. There's another inconsistency if Python is run under ReactOS (and probably Wine, too). The ReactOS equivalent to BaseIsThisAConsoleName is IntCheckForConsoleFileName, which doesn't have the (buggy) speed hack that Windows uses to gate the more expensive call to RtlIsDosDeviceName_U: http://preview.tinyurl.com/reactos-console-c-71210 Also note the comment on line 354 that "C:\some_path\CONIN$" should open the console. This highlights yet another problem with the current pathlib check: it doesn't reserve the names "CONIN$" and "CONOUT$". Actually, the comment is technically wrong for versions prior to Windows 8. The old implementation of RtlIsDosDeviceName_U only checks for "CON", not "CONIN$" or "CONOUT$". The latter two devices aren't inherited from DOS. They were added to the Windows API to allow opening console handles with both read and write access, e.g. to be able to call WriteConsoleInput and ReadConsoleOutput. "CON" doesn't allow this. However, the base API does allow opening plain "CONIN$" and "CONOUT$" without the "\\.\" device namespace prefix, so those names are at least reserved for the current directory. The problem is more encompassing for Windows 8+, which has a real console device. It no longer calls BaseIsThisAConsoleName to redirect CreateFile to OpenConsoleW. Instead it passes the regular NT paths r"\??\CON", r"\??\CONIN$", or r"\??\CONOUT$" to the NtCreateFile system call, which resolves the object manager symbolic links respectively to r"\Device\ConDrv\Console", r"\Device\ConDrv\CurrentIn", and r"\Device\ConDrv\CurrentOut". As part of the redesign, the base API moved the check for "CONIN$" and "CONOUT$" into the NT runtime library function RtlpIsDosDeviceName_Ustr. Now "CON", "CONIN$", and "CONOUT$" are reserved in every directory, just like how it's always worked for NUL, AUX, PRN, COM1-9, and LPT1-9. For example: Windows 10 >>> print(os.path.abspath('C:/Temp/conout$ : spam . eggs')) \\.\conout$ Windows 7 >>> print(os.path.abspath('C:/Temp/conout$ : spam . eggs')) C:\Temp\conout$ : spam . eggs -- https://mail.python.org/mailman/listinfo/python-list