This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eryksun
Recipients Dustin.Oprea, eryksun, paul.moore, steve.dower, tim.golden, zach.ware
Date 2016-06-28.00:36:01
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1467074165.96.0.663656756524.issue27403@psf.upfronthosting.co.za>
In-reply-to
Content
Paths starting with "\\.\" (or  "//./") and "\\?\" are not UNC paths. I've provided some explanations and examples below, and I also encourage you to read "Naming Files, Paths, and Namespaces":

https://msdn.microsoft.com/en-us/library/aa365247

"\\.\" is the general way to access DOS devices, but with some path processing still enabled. For example:

    >>> files = os.listdir(r'//./C:/Windows/System32/..')
    >>> [x for x in files if x[:2] == 'py']
    ['py.exe', 'pyw.exe']

Notice that using slash and ".." is allowed. This form doesn't allow relative paths that depend on per-drive current directories. It's actually not recommended to use "\\.\" to access files on drive letters. Normally it's used with drive letters only when directly opening a volume. For example:

    >>> fd = os.open(r'\\.\C:', os.O_RDONLY | os.O_BINARY)
    >>> os.read(fd, 512)[:7]
    b'\xebR\x90NTFS'

The "\\?\" prefix allows the most access to the NT kernel namespace from within the Windows API (e.g. file paths can be up to 32K characters instead of the DOS limit of 260 characters). It does so by disabling all path processing, which means the onus is on the programmer to provide a fully-qualified, Unicode path that only uses backslash as the path separator.

So why does "\\.\" exist? Some DOS devices are made implicitly available in the Windows API, such as DOS drive letters and "CON". However, the Windows API greatly extends the number of 'DOS' devices (e.g. the "PhysicalDrive0" device for low-level access to the first disk). Accessing these devices unambiguously requires the "\\.\" prefix. A common example is using "\\.\pipe\[pipe name]" to open a NamedPipe. You can even list the NamedPipe filesystem in Python. For example:

    >>> p1, p2 = multiprocessing.Pipe()
    >>> [x for x in os.listdir(r'\\.\pipe') if x[:2] == 'py']
    ['pyc-719-1-hoirbkzb']

Global DOS device names are defined in the kernel's "\Global??" directory. Some DOS devices, such as mapped network drives, are usually defined local to a logon session in the kernel's "\Sessions\0\DosDevices\[Logon Session ID]" directory. In the examples I gave, you may have noticed that each native kernel path starts with "\??\". This is a virtual directory in the kernel (and only the kernel). It instructs the object manager to first search the local session DOS devices and then the global DOS devices.

A DOS device is almost always implemented as an object symbolic link to the real NT device name in the kernel's "\Device" directory. For example, "\Global??\PIPE" links to "\Device\NamedPipe" and the "C:" drive may be a link to "\Device\HarddiskVolume2". This device is what the kernel actually opened in the previous example that read from "\\.\C:". Note that this accesses the volume itself, not the root directory of the filesystem that resides on the volume. The latter is "\\.C:\". The trailing backslash makes all the difference. (Opening a directory such as the latter requires backup semantics, as described in the CreateFile docs.)

If a DOS drive letter is assigned to a volume, the assignment is stored in the registry by the volume's ID. (Dynamic volumes that span multiple disks also contain a drive letter hint.) For volume devices, the kernel also creates a GUID name that's always available and allows mounting a volume in a directory using an NTFS reparse point (e.g. see the output of mountvol.exe). You can also use GUID volume names in the Windows API. For example:

    >>> path = r'\\?\Volume{1693b540-0000-0000-0000-612e00000000}\Windows'
    >>> files = os.listdir(path)
    >>> [x for x in files if x[:2] == 'py']
    ['py.exe', 'pyw.exe']

But normally you'd just mount the volume, which can even be recursively mounted within itself. For example:

    >>> os.mkdir('C:\\SystemVolume')
    >>> subprocess.call(r'mountvol C:\SystemVolume \\?\Volume{1693b540-0000-0000-0000-612e00000000}')
    0
    >>> files = os.listdir(r'C:\SystemVolume\Windows')
    >>> [x for x in files if x[:2] == 'py']
    ['py.exe', 'pyw.exe']
History
Date User Action Args
2016-06-28 00:36:06eryksunsetrecipients: + eryksun, paul.moore, tim.golden, zach.ware, steve.dower, Dustin.Oprea
2016-06-28 00:36:05eryksunsetmessageid: <1467074165.96.0.663656756524.issue27403@psf.upfronthosting.co.za>
2016-06-28 00:36:05eryksunlinkissue27403 messages
2016-06-28 00:36:01eryksuncreate