Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Another handy dos command, originating back to DOS is SUBST.

Came in pretty handy when I wanted to share a folder with Remote Desktop, but it would only let me select whole drives.

Made a SUBST drive letter for that folder, worked like a charm!



SUBST makes use of NT Object Namespace Symbolic Links to register the drive letter. After running SUBST, you get an object named "M:" (or whatever your drive letter is") sitting in the "\??\" directory, its full path will be "\??\M:". It will be a symbolic link that points to something like "\??\C:\target_path".

You can either see this by using "NtQuerySymbolicLinkObject" on "\??\M:", or calling "QueryDosDeviceW" on "M:". On Windows NT, you will see the result as an NT-native path "\??\C:\target_path" rather than a Win32-style path "C:\target_path".

"\??\" is not some kind of special notation for paths or anything, it is a real NT object that exists. It holds your drive letters and other things.

On Windows 9x, you won't see an NT-native path from QueryDosDevice, you'll instead see a Win32-style path "C:\target_path".

Weirdly enough, Sysinternals Winobj is unable to find the symbolic link object at all, despite that it exists when you query it using NT API calls.

Fun fact about NT native paths, you can use them in Win32 if you prefix them with "\\?\GLOBALROOT". So "\??\C:\" becomes "\\?\GLOBALROOT\??\C:\". You can use it in any Win32 program that doesn't actively block that kind of path (such as the file explorer/open dialog)


NT wasn't even a twinkle in Dave Cutler's eye when DOS APPEND came into being


IIRC originally SUBST was designed for that - early programs didn't understand directories but did understand drives, and so you could make a directory appear to be a drive and they'd be happy - otherwise they'd dump everything in the root of C:\ (or A:\).


I still use SUBST with my team so we all have our source code on P:\ which can be mapped to wherever they want it to be. This helps keep Visual Studio object files and project includes pointing to the same place, especially when mistakes are made (they should be relative paths but things happen).

It is run from a registry key upon bootup.


We do the same, except you don't need to do it at bootup, you can set it once using the following:

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices]
    "P:"="\\??\\C:\\Dev\\Source"
Change source path accordingly, save as .reg file, import once and it'll stay.

Nice thing about this vs using SUBST is that the SUBST is for your user only, so if you have a separate admin account it won't see it. However the above registry entry is for the machine, so all users on the machine will see it.

Obviously makes it less useful for terminal servers and other shared machines.


I think SUBST can break when you run as administrator (elevating your own privileges).


It still works, but the elevated context maintains a separate list of drive letter mappings, so you need to issue the SUBST command again while elevated.

The same applies to network drive letter mappings.

Under the hood, both are implemented as NT Object Manager symbolic links, which you can see using, e.g.,

https://learn.microsoft.com/en-us/sysinternals/downloads/win...


SUBST is all fine, up until the point some tool explodes when it sees that normalizePath("P:\\whatever") == "C:\\code\\whatever", and it ends up with two paths to one file, or no way to build a relative path. I’ve seen that happen with some node tooling, for example.


I've seen programs blow up because they think they need to "canonicalize" the path, when all they actually want is a full path (a rooted path rather than a relative path).

Canonicalizing the path resolves all drive letters and symbolic links. The Rust function that canonicalizes a path can fail on some mounted filesystems if the drive letter wasn't registered using the Windows Mount Manager.


I think some of the WSL stuff refuses to deal with SUBST'd drives. And if you use voidtools's Everything, it's worth spending 2 minutes setting up some excluded paths so that you don't get doubled up entries. But it seems it does generally work pretty well. I've recently done work for a former employer, who it seems are still using SUBST'd drive Z:, just as they'd always done when I worked there nearly 20 years ago. (Main reason: we'd found it worked well at the place we'd all worked at previously...)

The idea of everybody having the same paths for things never sat right with me, because it's an easy way for absolute paths to sneak in, which can be (and occasionally was) a problem when trying to support multiple branches later in the project lifecycle. But if you've got a CI system, which people typically do in 2024, that's much less of an issue (because you can arrange for the CI system to build from a random path each time). And it is pretty handy when you can paste universally-usable paths into the chat.


> you can arrange for the CI system to build from a random path each time

Or you can end up having to use the magic path for all builds.

At work, we have a subst’d drive. The way we set it up means that some <evil crap> requires it (by the virtue of hardcoding, or by common configuration). But I do most of my development from a fully separate, leaner copy of the repo, and consider the subst drive to be a garbage pile.


The idea is that you set up the CI system to build from a different path as often as possible. Per build, per build machine, per build machine rebuild - whatever works for you. Just ensure it's a different path from the standard one that the developers use. Ideally, also make sure that the path the developers use is completely inaccessible on the CI machines.

Now the chance of introducing dependencies on the standard path is much lower. You can do it, and it will work for you, and it will work for everybody else too when they get your change. But at some point, the CI system will get it, and it will fail, and you'll know that you have something to fix.


SUBST to this day is how you solve long file name problems. One drive for business can make a very long path if it uses your full business name. Windows has the api to let some apps apps save long sob folders, but not to let Explorer or powershell delete those folders.

You go on folder up and use subst to make a drive letter from which you can delete content.


Explorer (known in MS jargon as "the shell", but I'm avoiding the term because it confuses Unix users) is limited by MAX_PATH characters when it stores absolute paths.

Win32 allows you to use paths above MAX_PATH in length when you 1. Use the utf-16 filename apis and 2. prefix your path with \\?\.

But the shell doesn't do the latter. It may also use fixed size buffers for paths, that is a common reason for such limitations.


poor man's chroot.


Ahh yes, subst was very handy many times back in the day and it worked like magic to me!




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: