Search code examples
windowsjunction

How can I make a junction point or symlink point to a different place for different users?


Example scenario: I want c:\temp to point to each user's temp directory, even if multiple users are logged in simultaneously.

I can run code during user logon, e.g., using a logon script, the Run key, etc., but it must work for non-administrative users.


Solution

  • This is a job for the local DOS devices namespace!

    During user logon, create a device name pointing to the temporary folder:

    DefineDosDevice(DDD_RAW_TARGET_PATH, L"TempFolder", L"\??\C:\<path>");
    

    You can then log on as an administrative user and create the junction point or symlink. For example:

    mklink /J c:\temp \\?\TempFolder
    

    A few notes:

    • You cannot create a junction point to a device name that does not both exist in the current logon session and point to a local drive. So make sure you create the device name before attempting to create the junction point. (This does not apply to symlinks.)

    • If UAC is enabled, administrators will have two logon sessions, one elevated and one restricted. If you want the link to work in both sessions you must create the device name in both sessions.

    • The device name path should not include a trailing backslash.

    • You cannot prevent the user from redefining where the folder points to in their own logon session. So this cannot be part of a security mechanism.

    • If the file system is being backed up, you should test whether the presence of such a junction point / symlink breaks the backup software. Most backup software does not attempt to follow junction points or symlinks, so it should usually be OK. (However, a restore operation for the junction point or symlink may fail if the device name does not exist.)

    • As near as I can tell, the only reason I need to use the \\?\ format (rather than \??\) when creating the junction point is that the mklink command misinterprets the latter as a relative path. If you are creating the junction point in code, you can probably use either. For more context, see also "Path prefixes \??\ and \?\".

    • The local DOS device namespace appears to be per-remote-desktop-session as well as per-logon-session. Under normal circumstances this won't matter, but I'm not sure what will happen if you're doing weird stuff like explicitly changing a token's remote desktop session.