On Mon, Aug 22, 2016 at 5:24 PM, Chris Angelico <ros...@gmail.com> wrote: > On Tue, Aug 23, 2016 at 3:13 AM, eryk sun <eryk...@gmail.com> wrote: >> On Mon, Aug 22, 2016 at 4:18 PM, Chris Angelico <ros...@gmail.com> wrote: >>> >>>> The CON device should work if the process is attached to a console >>>> (i.e. a conhost.exe instance). >>> >>> No, I used Pike (to avoid any specifically-Python issues or >>> protections) running in a console. Attempting to write to "Logs/con" >>> wrote to the console, so I know the console device is active. >>> Attempting to write to "Logs/con.txt" failed as described. >> >> What version of Windows is this? If it's Windows 7 I'll have to check >> that later. If "Logs" is an existing directory, then both "Logs/con" >> and "Logs/con.txt" should refer to the console. If "Logs" doesn't >> exist, then both should fail. Virtual DOS devices only exist in >> existing directories. > > Yes, it was Windows 7 (running in a VM under Debian Jessie, though I > doubt that makes any difference). The Logs directory did exist (that's > why I used that otherwise-odd choice of name).
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. If there's a match, then a CreateFile call gets routed to OpenConsoleW, which uses the process ConsoleHandle to send the request to the attached instance of conhost.exe, which replies with a console pseudohandle. Note that the handle value is flagged by setting the lower 2 bits, i.e. 3, 7, 11, which allows routing to special console functions, such as WriteFile => WriteConsoleA. In Windows 8+ console handles are regular File handles (e.g. 24, 28, 32). When debugging this I observed that there's a performance hack in BaseIsThisAConsoleName. It only calls RtlIsDosDeviceName_U, which does a full check for "CON" in the path, if the name starts with '\\' , 'c', or 'C', or if it ends with 'n', 'N', ':', or '$'. This means r"C:\whatever\con.txt" works (the base path doesn't even have to exist), but not r"D:\whatever\con.txt". In your case the name starts with 'L', so BaseIsThisAConsoleName returns false and the code falls through to calling DosPathNameToRelativeNtPathName_U_WithStatus. This returns r"\??\con", which NtCreateFile fails to open. r"\??" is a virtual directory starting in Windows XP. For this directory the object manager first checks the logon session's DOS devices in r"\Sessions\0\DosDevices\[Logon Id]" and then the global DOS devices in r"\GLOBAL??". This is an improvement over the less flexible way that Windows 2000 managed DOS devices for terminal services and logon sessions. A DOS 'device' is an object symbolic link to the real NT device in the r"\Device" directory. In Windows 8+, r"\GLOBAL??\CON" is a link to r"\Device\ConDrv\Console", which is why opening "Logs/con.txt" worked 'correctly' for me in Windows 10. -- https://mail.python.org/mailman/listinfo/python-list