Junctions, Hard Links, Symbolic Links on the Windows File System

On windows, the command line tool mklink is used to create symbolic links, junctions, and hard links. But what are those? I’ll first mention a couple of scenarios where they may be helpful. Let’s say that you have a content-driven system. You have multiple versions of your content sets on the file system. Each complete set is in its own folder. The software itself uses the content in a folder named current. When your content syncing applicate gets done downloading a new content set, there are several ways to make it available to the software that is using it. The method I want to focus on is having a virtual folder named current that is actually a pointer to the real folder. A variation of this need is having different versions of an SDK installed. To change from one SDK to another, there could be multiple environment variables that must be updated to point from one SDK version to another. This can be simplified by having a folder that is actually a pointer to the directory that must be used.

Switching from abstract to actual for a moment, I’ve got a couple of versions of the Java Card SDK installed. I just installed the latest version, but I want to keep the previous version around for a while. I’ve got a javacard folder as the root folder of all of the other software used for Java Card development. In it, there are junctions named tools and simulator to point to the Java Card folders for the command line tools and the Java Card simulator. If I need to switch between versions, I only need to delete the old junctions and create new ones.

Arguments for mklink

The arguments to the command are as follows.

mklink[[/j] | [/d] | [/h]] <link> <target>

  • /j – Create a directory junction
  • /d – Create a directory symbolic link
  • /h – Create a hard link (for files only)

Understanding of hard links and junctions requires understanding of the underlying file system. hard links refer to files while junctions refer to directories. Beyond that, they do the same thing. For a hard link or junction, two entries on the file allocation table point to the same inode entries. Symlinks are more like pointers that hold information on the original file system entry. Hard links and junctions can only refer to files on the same file system, while can symlinks refer to a file on a different file system. If no arguments are passed to mklink it will assume that you are making a file symlink.

Command Line Examples

What follows scenarios and the associated commands for those scenarios.

Create a new junction named tools that points to c:\bin\tools_v3.5

mklink/j tools c:\bin\tools_v3.5

Delete a junction named tools.

rd tools

Create a hard link named readme.txt to a file named c:\data\readme_23.txt

mklink /h readme.txt c:\data\readme_23.txt

Delete the hard link for readme.txt.

del readme.txt

What if I Want to Do This with an API Function?

The Win32 API also makes this functionality available to you through the function CreateSymbolicLink and DeviceIoControl.

CreateSymbolicLink

The arguments for the function reflect the arguments used by the command line tool.

BOOLEAN CreateSymbolicLinkW(
  [in] LPCWSTR lpSymlinkFileName,
  [in] LPCWSTR lpTargetFileName,
  [in] DWORD   dwFlags
);

The flag here can be one of three values.

ValueMeaning
0The target is a file
SYMBOLIC_LINK_FLAG_DIRECTORY (0x01)The target is a directory
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE(0x02)Non-Elevated Create

DeviceIoControl

DeviceIoControl is used for a lot of different functionality. The details of using it in this specific use case may be worthy of its own post. For the sake of brevity, I won’t cover it here. But I’ll mention a few things about using it. When using it to make a junction, the following struct would be used. Note that this struct is a union. The union members that you would use for making a junction to a directory are in the MountPointReparseBuffer.

typedef struct _REPARSE_DATA_BUFFER {
  ULONG  ReparseTag;
  USHORT ReparseDataLength;
  USHORT Reserved;
  union {
    struct {
      USHORT SubstituteNameOffset;
      USHORT SubstituteNameLength;
      USHORT PrintNameOffset;
      USHORT PrintNameLength;
      ULONG  Flags;
      WCHAR  PathBuffer[1];
    } SymbolicLinkReparseBuffer;
    struct {
      USHORT SubstituteNameOffset;
      USHORT SubstituteNameLength;
      USHORT PrintNameOffset;
      USHORT PrintNameLength;
      WCHAR  PathBuffer[1];
    } MountPointReparseBuffer;
    struct {
      UCHAR DataBuffer[1];
    } GenericReparseBuffer;
  } DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;

Administrative Level Needed for Non-Developers

This functionality usually requires administrative level privileges to execute. However, if a machine has developer mode enabled, the function can be invoked without administrative level privileges. The mklint command line tool appears to follow the same rule. Running this on my own systems (which have developer mode enabled) I can create links without administrative privileges. If you are creating links with a Win32 API call, remember to set the flag SYMBOLIC_LINK_ALLOW_UNPRIVILEGED_CREATE.


Posts may contain products with affiliate links. When you make purchases using these links, we receive a small commission at no extra cost to you. Thank you for your support.

Mastodon: @j2inet@masto.ai
Instagram: @j2inet
Facebook: @j2inet
YouTube: @j2inet
Telegram: j2inet
Bluesky: @j2i.net

Sushi Bricks

A gift I received some time ago was a Sushi themed not-LEGO set (It’s not from the LEGO corporation, but people would still colloquially call them LEGOS). This set was a recreation of a sushi dish. I like assembling models and LEGO sets, I love sushi, and I enjoyed putting this set together. I think the end result speaks for itself.

This was easy to put together. While it took me 31 minutes to do so, it was because I was recording the process and talking to someone else. The video of the assembly (minutes the audio from my conversation and minus some redundant points) is on YouTube on my alternative channel for collectables, toys, and other items (@j2inet2). It is also embedded below. If you are interested in getting this set, you can find it on Amazon (affiliate link)