Ask Learn
Preview
Ask Learn is an AI assistant that can answer questions, clarify concepts, and define terms using trusted Microsoft documentation.
Please sign in to use Ask Learn.
Sign inThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Most of us are familiar with DOS style paths to files such as C:\bar\foo.txt. Most aren't familiar with the DOS Device format of said path: \\.\C:\bar\foo.txt. Even less know about the lowest level version of this path- the "real" NT path to the file object that Windows uses internally: \Device\HarddiskVolume4\bar\foo.txt.
Knowing how paths resolve through the system will help you understand how to access all resources (such as volumes that don't have a drive letter) and write any path handling code correctly. My prior post on Path Normalization is one part of this. This post will follow the path's resolution to help you understand why all of the following (and many other variants) are equivalent:
The "real" path would be the path Windows uses internally- or the "NT path". An NT path is a path to a resource as maintained by the Windows Object Manager. The Object Manager handles creation, destruction, and access rights for objects. Resources include files, registry keys, threads, processes, devices, mutexes and others.
An NT path for a file is a path to a device in the Object Manager namespace followed by the local path for the given device. C:\bar\foo.txt on my machine is the NT path \Device\HarddiskVolume4\bar\foo.txt. \Device\HarddiskVolume4 on my machine is the device object that is exposed to Win32 by the symbolic link for my drive (C:). The device object is where the Object Manager's parsing of the path is handed off. The rest of the path \bar\foo.txt is handed off to the I/O Manager and the relevant driver(s) for further parsing and object creation.
To further illustrate the process, lets follow a path as it goes through the system.
C:\bar>echo foo > foo.txt
A file object needs to be opened and a handle to it returned in order to get the data out of the file (via CreateFile). "foo.txt" is passed to CreateFile and this is roughly what happens:
The Sysinternals tool "WinObj" will let you browse the Windows object manager. If we look for the device path in the example above, we'll find the following:
[caption id="attachment_435" align="alignnone" width="806"] A device path in the object manager.[/caption]
Following the symbolic link will take us to the Device leaf node.
[caption id="attachment_445" align="alignnone" width="806"] The Device object the C: symbolic link points to.[/caption]
(Note that you need to run the tool as Administrator to see some of the objects, but not the ones we care about here.)
The \??\C:\foo.txt form is how the path is passed to the Object Manager (and how you would represent a path when writing a kernel mode driver). Some Win32 APIs recognize this form of the path, but not all of them. Use it for giggles, but not production code as the APIs that don't recognize it will fall through to normalization- call GetFullPathName() on this particular path to see what will happen or try and reason it out yourself using the information in my last post.
Other related topics that I intend to go over are common mistakes made with paths and utilizing the various sets of APIs related to these recent posts on paths. Feel free to chime in with suggestions about what you want to see me cover.
Ask Learn is an AI assistant that can answer questions, clarify concepts, and define terms using trusted Microsoft documentation.
Please sign in to use Ask Learn.
Sign in