Click here to Skip to main content
Click here to Skip to main content

Windows 2000 Junction Points

By , 5 Jan 2000
 

If you're not interested in the way to the solution, simply skip to the section The Solution.

Background

Windows 2000 includes a new version of NTFS dubbed "Version 5".

This version of NTFS includes something called reparse points. Reparse points can, among other things, be used to implement a type of softlinks, seen in other operating systems for the last decades.

  • A reparse point that points to a Volume is called Volume mount point.
  • A reparse point that points to a Directory is called Junction Point.

Volume Mount Points

The first steps to try these out was by using diskmgmt.msc which is an MMC "Snap-in" replacement for the Disk Administrator in NT4.

I created a directory \mnt\s and tried to mount S: on this directory.

It worked! I now had access to my S: through \mnt\s.

OK, can I now remove the driveletter from this drive and still have it working? Yes! Finally, you don't need all those driveletters anymore (except for the boot- and system-drive). You can simply remove e.g. S: and mount the Volume under \mnt\s.

This might not seem like a big deal to some people, but it can remove a lot of clutter. It also helps a lot when moving programs from one place to another, since just about every program in the Windows world expects to never be moved from the directory it was installed in.

E.g. moving your "Program Files" directory to another drive, and linking the original "Program Files" directory to this new location.

A Volume mount point basically contains the Unicode string

"\??\Volume{ GUID }\"
and is a representation that Windows 2000 uses to identify individual Volumes.

You can list accessible Volume GUIDs by typing MountVol.

For a quick look at where these are used, start RegEdit and look in the key

HKLM\SYSTEMS\MountedDevices

Note that a Volume isn't the Media, but rather the logical "device", since a Volume can refer to a floppy drive with no media in it.

Directory Junction Points

Reading a bit more revealed that reparse points should also be able to point at another directory. Ahhh, finally, I thought.

While looking for a way to create Directory junction points, I found a reference to a tool called "linkd.exe" in the Windows help. Hunting high and low for this tool I ended up empty handed.

Perhaps the most important evolution of NTFS ever, and they didn't supply the documented tool to use it! (It's apparently supposed to appear in Windows 2000 Resource Kit)

What's even more bothering is that junction points API usage is undocumented.

The Search

Starting to work up some steam over this issue, I got going on writing a tool that could create and manipulate Directory junction points (i.e. softlinks).

Now, how do you write code with completely undocumented structures? As usual in this world, by disassembling, trial-and-error, and searching old documentation and SDKs.

The the Windows 2000 SDK documentation that mentions Reparse Points points you to the struct REPARSE_GUID_DATA_BUFFER.

typedef struct _REPARSE_GUID_DATA_BUFFER {
    DWORD  ReparseTag;
    WORD   ReparseDataLength;
    WORD   Reserved;
    GUID   ReparseGuid;
    struct {
        BYTE   DataBuffer[1];
    } GenericReparseBuffer;
} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;
This struct is nothing more than i bit-bucket for the real data that any particular reparse point contains. In the case of Volume mount points and Junction points, it's both close to useless and completely wrong. Trying to parse the deata from a Junction Points using the ReparseGuid data member would only result in jibberish.

No help here.

There are three FSCTLs defined in WinIoCtl.h to manipulate reparse points using DeviceIoControl:

  • FSCTL_SET_REPARSE_POINT
  • FSCTL_GET_REPARSE_POINT
  • FSCTL_DELETE_REPARSE_POINT

Looking at the definition of these, you find that all three of them has a comment // REPARSE_DATA_BUFFER. This comment is still present in the Windows 2000 SDK, but the structure definition is nowhere to be found.

At this time my cursing started to approach a level not suitable for printing, and I decided that it was a long night with a lot of coffe and disassemly ahead.

But, I had a vague memory of this structure in the VC6 header. A contents search in the include directory for REPARSE_DATA_BUFFER displayed that it indeed existed in WinNT.h from VC6.

Apparently this needed structure was removed from the Windows 2000 SDK. Go figure...

Since I've now mentioned REPARSE_DATA_BUFFER, I think it's fair to show you the definition of it.

// slightly edited for displaying purposes
struct REPARSE_DATA_BUFFER {
    DWORD  ReparseTag;
    WORD   ReparseDataLength;
    WORD   Reserved;
    struct {
        WORD   SubstituteNameOffset;
        WORD   SubstituteNameLength;
        WORD   PrintNameOffset;
        WORD   PrintNameLength;
        WCHAR  PathBuffer[1];
    } SymbolicLinkReparseBuffer;
};

Armed with this struct, and a little knowledge of how Volume mount point strings looked, I went of to write some code.

I had no success whatsoever in using the SET FSCTL. DeviceIoControl only returned an error.

Now, I could GET a Volume mount point, that are easily created with the Disk Administrator equivalent or MountVol.exe, but I couldn't SET it back!

Suddenly a thought struck me, what if the definition of the SET macro changed?!

Comparing the definitions of these macros from the new SDK with the VC6 version confirmed my suspicions. The VC6 version looks like

#define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, 
        METHOD_BUFFERED, FILE_WRITE_DATA) // REPARSE_DATA_BUFFER,
#define FSCTL_GET_REPARSE_POINT     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, 
        METHOD_BUFFERED, FILE_ANY_ACCESS) // , REPARSE_DATA_BUFFER
#define FSCTL_DELETE_REPARSE_POINT  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, 
        METHOD_BUFFERED, FILE_WRITE_DATA) // REPARSE_DATA_BUFFER,
but in the Windows 2000 SDK, it had been changed to
// Windows 2000 SDK
#define FSCTL_SET_REPARSE_POINT     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, 
        METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER,
#define FSCTL_GET_REPARSE_POINT     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, 
        METHOD_BUFFERED, FILE_ANY_ACCESS) // REPARSE_DATA_BUFFER
#define FSCTL_DELETE_REPARSE_POINT  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, 
        METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER,

The new FILE_SPECIAL_ACCESS is defined as:

#define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS)
Aha, they changed the access protection for SET and DELETE! That might explain why nothing worked.

Actually, the change in access protection makes some sense. A SET or DELETE operation on a reparse point doesn't need write access to the Directory it's used on. It only needs access to the NTFS Attributes for that directory.

As a sidenote I might add the following snippet from WinIoCtl.h from the windows 2000 SDK.

// FILE_SPECIAL_ACCESS is checked
// by the NT I/O system the same as FILE_ANY_ACCESS.
// The file systems, however, may add additional access checks
// for I/O and FS controls
// that use this value.
Interesting: It mentions that
"The file systems, however, may add additional access checks...".

I wonder how they are supposed to do that, since both ANY and SPECIAL access are defined to be zero.

Getting Closer

Finally I could both GET and SET a Volume mount point using DeviceIoControl, and thereby get some info of how this struct should be filled in.
The Volume mount points PathBuffer in REPARSE_DATA_BUFFER is a Unicode string that looks like

"\??\Volume{9424a4a2-bbb6-11d3-a640-806d6172696f}\"

The SubstituteNameLength tells how many bytes the PathBuffer contains. By disassembling SetVolumeMountPoint from kernel32.dll, I found out that it only accepts 96 or 98 bytes as buffer length.

Strange, was my first thought. But still I tried to use the Volume GUID with an appended directory name through DeviceIoControl, in the hope that it wouldn't have the same restrictions and only get resolved during access. Right?

Wrong. Why make it orthogonal when you can make it "cumbersome"?

After many hours of trial-and-error, and even more cursing, I was about ready to give in, and admit defeat, when I got an idea. What if you instead of using a Volume GUID, look back on the CreateFile documentation?

The Solution

According to CreateFile documentation, you can enter a non-parsed path by prepending "\??\" to it. What if we used this approach and put in a "normal" full path like

"\??\C:\Program Files"

Type some code, build and test...Finally! It worked!

So, finally, to create a directory junction point, you must do the following:

  1. Create a directory, or use an existing empty directory.
  2. Open this directory with CreateFile, using the flags    FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT
  3. Create a filled-in REPARSE_DATA_BUFFER.
  4. Call
    DeviceIoControl(hDir,			// HANDLE to the directory
    		FSCTL_SET_REPARSE_POINT,
    		(LPVOID)&rdb,		// REPARSE_DATA_BUFFER
    		dwBytesToSet,
    		NULL,
    		0,
    		&dwBytes,
    		0);
    
  5. Done.

Well, almost. It's still that little matter of filling in this struct.

Filling in the REPARSE_DATA_BUFFER example

// quick 'n' dirty solution
wchar_t wszDestDir[] = "\\??\\C:\\Program Files\";
const int nDestBytes = lstrlenW(wszDestDir) * sizeof(wchar_t);

char szBuff[1024] = { 0 };
REPARSE_DATA_BUFFER& rdb = *(REPARSE_DATA_BUFFER*)szBuff;

rdb.ReparseTag        = IO_REPARSE_TAG_MOUNT_POINT;
rdb.ReparseDataLength = nDestBytes + 12;
rdb.SymbolicLinkReparseBuffer.SubstituteNameLength = nDestBytes;
rdb.SymbolicLinkReparseBuffer.PrintNameOffset      = nDestBytes + 2;

lstrcpyW(rdb.SymbolicLinkReparseBuffer.PathBuffer, wszDestDir);

const DWORD dwBytesToSet = // input buffer size to give to DeviceIoControl
	rdb.ReparseDataLength + REPARSE_DATA_BUFFER_HEADER_SIZE;

Ugly or what? I especially dislike the unnamed (i.e. it doesn't have a typename) struct SymbolicLinkReparseBuffer. Both that it's unnamed, and the length of its name makes the code quite unreadable.

I copied the definition of REPARSE_DATA_BUFFER from the VC6 header file to be able to use this even with the Windows 2000 SDK. I renamed it and removed the unnamed struct. In the process, it got some member functions to make its usage a lot easier.

Summary

As I said earlier in this article, possibly one of the most sought for features (and by that, looong overdue) in NTFS is "softlinks", and they didn't have the decency to neither document it, nor to provide any API whatsoever to use it.

I mean, get real; DeviceIoControl() to create a softlink?!

To make this a bit more usable, I wrote a little library that you can use in your own creations. The included program MakeLink.exe uses this library, and it's used to create, list and delete junction points. Just start MakeLink without arguments to see its usage.

The functions that IMO were missing from Microsofts API, and got implemented by this library (though in its own C++ namespace) are:

BOOL CreateJunctionPoint(LPCTSTR szMountDir, LPCTSTR szDestDir);
BOOL DeleteJunctionPoint(LPCTSTR szMountDir);
DWORD GetJunctionPointDestination(LPCTSTR szMountDir, LPTSTR szDestBuff, 
                                  DWORD dwBuffSize /* in TCHARs */);

These should be self explaining, but in the interest of completeness, here's some documentation.

CreateJunctionPoint

This function allows you to create or overwrite an existing junction point.

  • szMountDir must point to an empty directory.
  • szDestDir can either contain a path in the form "C:\Program Files" or "\??\C:\Program Files".
The first form will check if the directory exists before creating/overwriting the junction point. The second form allows you to enter just about any string as the destination.

Note that using the second form, you could create a Directory junction point that points to nowhere usable (e.g. "\??\foo:bar/baz").

If the function fails, the return value is FALSE. To get extended error information, call GetLastError.

Note: Strictly speaking, you can use this function as a replacement for the MountVol.exe command using the "\??\" form, but I think that Disk Admin is better suited for that purpose.

DeleteJunctionPoint

This function allows you to remove any Volume Mount Points or Directory Junction Points from the specified directory.

If the function fails, the return value is FALSE. To get extended error information, call GetLastError.

GetJunctionPointDestination

This function allows you to query any directory for its reparse point destination. Note that it will only work for reparse points of the type IO_REPARSE_TAG_MOUNT_POINT, but since this includes both Volume mount points and Directory junction points, it's fit for this library.

If the GetJunctionPointDestination succeeds, the return value is the the length, in TCHARs, of the string copied to szDestDir, not including the terminating null character.

If the szDestDir buffer is too small, the return value is the size of the buffer, in TCHARs, required to hold the path.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Final notes

The code is compilable as both ANSI and Unicode. It does not use MFC, standard C++ library, or any CRT memory management functions.

Writing this library and I had a few criterias in mind:

  • Make an easy API for people to use. I always use CreateFile as a comparison.
  • Create as few dependencies on other libraries as possible.
  • Don't use MFC. Not everybody uses MFC, and to use it for a utility (library) like this is IMO like using a sledgehammer to type on your keyboard.
  • Don't depend on the standard C++ library. Not everybody uses it, and though a correct implementation is good, PJP's Microsoft implementation is not correct, since their compilers can't handle a conforming implementation. Besides that:
  • Make it small.

The application MakeLink.exe is 5 632 bytes. It does however depend on MSVCRT.dll (Microsoft C Runtime Library), but I think the size criteria was met. :-)

BTW:
While browsing the new documentation, in the documentation for SetVolumeMountPoint I found the following text

... "\\?\C:\myworld\private" is seen as "C:\myworld\private".
This initially led me to believe that I've done all this work for nothing!

Trying out this API (which according to its name is to mount Volumes only), I found out that they've only mentioned it, they don't implement this behaviour in SetVolumeMountPoint. Another point of interest is that the creator of this API apparently was completely unaware of the already documented approach of creating a non-parsed file system name "\??\", and charged ahead to invent "\\?\".

Happy Filesystem linking.

Mike Nordell - Nordell Consulting

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Mike Nordell
Architect
Sweden Sweden
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalsome wrong on 2t disk simulatormembernhchmg15 Dec '10 - 22:55 
I test on 2T Disk,a tool, 2T Disk Simulator,it simulate a 2TB disk,1024,2048,4096 bytes/secotr,this app can not work.I found this tool on http://www.2tdisk.com
GeneralMy vote of 5memberdemonkoryu13 Oct '10 - 23:58 
Thanks man! You're describing my adventures last night, but I didn't have a VC6 SDK handy anymore! Probs! (Also, belated congrats on 10th anniversary of this article)
GeneralJunction Link Magic: Include Option to Select Folder Level Deepgroupjames.rapula22 Jul '10 - 13:43 
This worked wonders for our organisation when we had to restructure the share data scaling the folders into different logical drives.Few months later, I revisited the site and learnt that Version 2 had been released which further improves the functionality which provides the option to select the drives to scan!!! I’m a very happy user of the utility and will be visiting this site often to see if there are any new or updates to the utilities.
 
Just a small addition:
 
I have just one little suggestion: would it be possible to make changes to JLM in that when it scans, it only does up to 4th or 5th folder level depth? Will be much better it the depth level can be optional before the scan kicks off just after the drive selection.
 
Thanks
James
QuestionIs Link to Network Drive Possible?memberJonny Hart5 Jun '08 - 22:26 
Hello,
 
First of all, I use makelink a lot now to resolve building projects against different revisions of common code libraries. Without it the build file management task would be horrendous - thank you!
 
I have the following situation:
 
A PC with a legacy app deposits files on it's C drive in a place that can't be changed (we dont have the source / compiler etc). I want these files to be placed on a shared drive on a remote networked machine. I have done the following:
 
1) Mapped a drive on legacy PC (runs NT4) to remote machine as Z:
2) makelink c:\localfilerepository\ z:\remotefilerepository
 
makelink fails. both folders are empty BTW.
 
Am I simply asking to much of makelink?
 
Regargs
 
Jon
GeneralCab and restore a folder which is a Junction/Link in other drivememberkulkarniquiet7 Mar '07 - 22:32 
I have a query about Junction/link to a folder.
How to identify junction in MFC in code?
Is there ant specific method?
If I make write some code to cab a folder which is a link(Junction) in other drive.
So when I restored it back,will the link/junction be also restored at the destination?
Kindly reply.
Awaiting for the same.
 


 
Best Regards,
Abhijit
Questiontrailing backslash--bug?memberlarham28 Nov '06 - 8:59 
A trailing backslash seems to confound MakeLink on the command line. A junction is created, but files cannot be copied. I was seeing this as part of a script, so I tested using a script--not sure if that matters.
 
larry
------------------
 
C:\TEMP>mkdir c:\foo
 
C:\TEMP>type test.bat
C:\temp\MakeLink.exe c:\foo "d:\bar"
 
C:\TEMP>test.bat
 
C:\TEMP>C:\temp\MakeLink.exe c:\foo "d:\bar"
Created link "c:\foo" -> "d:\bar"
 
C:\TEMP>copy MakeLink.exe c:\foo
1 file(s) copied.
 
C:\TEMP>rmdir c:\foo
 
C:\TEMP>mkdir c:\foo
 
C:\TEMP>
C:\TEMP>type test.bat
C:\temp\MakeLink.exe c:\foo d:\bar\
 
C:\TEMP>test.bat
 
C:\TEMP>C:\temp\MakeLink.exe c:\foo d:\bar\
Created link "c:\foo" -> "d:\bar\"
 
C:\TEMP>copy MakeLink.exe c:\foo
The filename, directory name, or volume label syntax is incorrect.
0 file(s) copied.
 
C:\TEMP>
GeneralVolume Mount Points To Device PNPmembersmclain23 Jun '06 - 19:07 
I enjoyed the article. I have been looking for a way to go from a VolumeMountPoint to the PNP id of the associate storage device. I have not found an interface or set of steps for doing this. Do you have any suggestions.
 
Thanks
JokeLonghorn provides API for symlinks LOLmembercurlyhands25 Mar '06 - 20:53 
here
uses the same technology of reparse points.
GeneralShell Extension for junctionsmemberryltsov10 Feb '06 - 9:52 
There is a nice shell extension for junctions at http://alax.info/blog/ntfslinks
GeneralDirectory junction points now available directly from linkd.exesussMatthias Fripp29 Sep '05 - 12:39 
This article was very useful but is somewhat out of date.
 
Windows XP has the same built-in support as Windows 2000 for grafting a whole volume into the directory structure of another volume. As the author notes, this can be done via mountvol.exe, or via diskmgmt.msc, which can be accessed through the GUI in Windows XP at Control Panel -> Administrative Tools -> Computer Management -> Storage -> Disk Management -> (right click on the drive) -> Change Drive Letter and Paths...
 
However, linkd.exe is also available now, if you want to graft a _directory_ from one volume into another (instead of the whole volume). Linkd.exe pretty much replaces the command line utility described here for making directory junction points. You can download linkd.exe as part of the Windows 2003 Server Resource Kit at http://www.microsoft.com/downloads/details.aspx?FamilyID=9d467a69-57ff-4ae7-96ee-b18c4790cffd&displaylang=en
 
System Internals is also reported to have a freeware utility for doing all of this.
 
More information can be found here:
 
http://www.windowsnetworking.com/kbase/WindowsTips/Windows2000/AdminTips/Miscellaneous/Windows2000breaksthe26driveletterlimitation.html
 
http://support.microsoft.com/kb/q205524/
GeneralRe: Directory junction points now available directly from linkd.exememberScott Pascoe19 Nov '05 - 8:05 
This article is actually quite relevant, as the information in it allows languages that implement symlink as an internal function to now implement the function on the Windows platform.
 
postgressql uses this feature, and it could easily be added to PHP. All because of the wonderful work done here
 
Thank you!!
QuestionWith p/Invokesussjonscheiding12 Sep '05 - 6:06 
I'm attempting to write a .NET library that can accomplish this through p/Invoke. So far things are going well, I have been able to get junction point info into a REPARSE_DATA_BUFFER struct which is formulated like this:
 
[StructLayout (LayoutKind.Explicit)]
struct REPARSE_DATA_BUFFER 
{
  [FieldOffset (0)]  uint ReparseTag;
  [FieldOffset (4)]  ushort ReparseDataLength;
  [FieldOffset (8)]  ushort SubstituteNameOffset;
  [FieldOffset (10)] ushort SubstituteNameLength;
  [FieldOffset (12)] ushort PrintNameOffset;
  [FieldOffset (14)] ushort PrintNameLength;
  [MarshalAs ( UnmanagedType.ByValArray, SizeConst=480 )]
  [FieldOffset (16)] byte [] PathBuffer;
}
Notice that the SizeConst on PathBuffer is 480, this means that if by some chance DeviceIoControl wants to put more than 480 bytes into the buffer (this can definitely happen), it will get truncated. However, if I set the SizeConst to any greater value, DeviceIoControl fails. GetLastError returns an error code of 6, which FormatMessage translates as "Invalid access to memory location".
 
Does anyone know why this is? Also, does anyone happen to know what a more ideal SizeConst value would be? What is the maximum length of paths in NTFS 5?
 
Thanks for your time!
AnswerRe: With p/InvokememberMike Nordell14 Sep '06 - 7:20 
I want it to be known I know exactly nothing about .NET and it's runtime.
 
That said, I (strongly) suspect this is a function of how the virtual machine functions. You probably need to actually touch (in Win32/NT parlance that'd be to commit it) all the physical memory SizeConst says follows. If not all memory is committed, a kernel-mode check that you've provided a large enough buffer of committed memory will fail. As such a kernel-mode code can't commit the memory for you, it returns an error.
 
++luck;
GeneralTo get Information of localization of a resource in windowsmemberAjay Movalia6 Nov '03 - 1:05 
hello sir,
I am almost areading all the articles of you. So I am very eager to know that the resources used by the window. bcz i am from gujarat India so i want to develop the localized resource in gujarati for windows. I know that I has to write the dll and replaced it with the existing dll. But i want to know wat function it contains. and wat are the resources used by the windows.
 
Please help me regarding this if possible...
 
Ajay Movalia
QuestionIsReparseTagValid macro?memberJerker Bäck30 Sep '03 - 10:25 
Definition of "IsReparseTagValid" is missing in my system:
Vc7, PSDK oct 2002, WinDDK XPsp1
 
Maybe it's replaced by "IsReparseTagMicrosoft"?
 
Jerker Bäck
AnswerRe: IsReparseTagValid macro?memberMike Nordell30 Sep '03 - 11:35 
No, the two are different. They both used to be defined in winnt.h (VC6), but have since apparently been removed.
 
You might try the following:
 
#define IsReparseTagMicrosoft(_tag) ((_tag) & 0x80000000
#define IO_REPARSE_TAG_VALID_VALUES (0xE000FFFF)
#define IsReparseTagValid(_tag) ( \
!((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) && \
((_tag) > 1) \
)
 
++luck;

GeneralRe: IsReparseTagValid macro?memberJerker Bäck1 Oct '03 - 12:33 
OK, interesting...
if you show 0xE000FFFF in binary format and compare it with the info in winnt.h:
0xE000FFFF => 11100000000000001111111111111111
 
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+-+-+-+-------------------------+-------------------------------+
|M|L|N|   Reserved bits         |       Reparse Tag Value       |
+-+-+-+-------------------------+-------------------------------+
 
tag > IO_REPARSE_TAG_RESERVED_RANGE (>1)
this macro says that the reserved bits must be zero for the tag to be valid. The "IsReparseTagMicrosoft" macro just test the M-bit. But if it's not a Microsoft tag - what is it then? The IO_REPARSE_TAG_MOUNT_POINT tag could be tested for the N-bit (the only "known" tag who set this bit).
 
What about mounting a shell namespace? If one clear the M-bit, set the N-bit and make up some value for the Reparse Tag Value. How to do next?
The psdk says:
"To ensure uniqueness of tags, Microsoft provides a mechanism to distribute new tags. For more information, see the Windows 2000 IFS Kit."

 
Jerker Bäck
GeneralRe: IsReparseTagValid macro?memberJerker Bäck7 Nov '04 - 12:30 
OK, I looked in to this again. The following is the correct macros from ntifs.h in Windows 2003 DDK IFS-kit.
 
// Macro to determine whether a reparse point tag corresponds to a tag
// owned by Microsoft.
#define IsReparseTagMicrosoft(_tag) (((_tag) & 0x80000000))
 
// Macro to determine whether a reparse point tag is a name surrogate
#define IsReparseTagNameSurrogate(_tag) (((_tag) & 0x20000000))
 
// The following constant represents the bits that are valid to use in
// reparse tags.
#define IO_REPARSE_TAG_VALID_VALUES     (0xF000FFFF)
 
// Macro to determine whether a reparse tag is a valid tag.
#define IsReparseTagValid(_tag) (                               \
                  !((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) &&   \
                  ((_tag) > IO_REPARSE_TAG_RESERVED_RANGE))
 
The "IsReparseTagMicrosoft" macro is defined in winnt.h and Mike's code will compile if "IsReparseTagValid" is substituted with this.
 
Jerker
GeneralAnother REPARSE_DATA_BUFFERmemberJerker Bäck30 Sep '03 - 7:52 
The REPARSE_DATA_BUFFER has probably been moved to the Microsoft IFS kit (not for everyone!)
You can find a free version of the MS IFS kit's "ntifs.h" at "Bo Brantén [ntifs.zip]"
Bo has listed an another version of the structure. If this works with making junctions remains to be seen.
 
There is also a similar utility to "MakeLink" called "junction" made by Mark Russinovich at SysInternals [jnctnsrc.zip], source code included.
 
Annars: tack Micke för koden! Wink | ;)
 
Jerker Bäck
QuestionMulti target ?sussMadium3 Jul '03 - 9:59 
Is there any way to have multi-targeting working ?
I explain: we have 3 folders: A, B & C
A & B has their contents. C has the content of A & B together.
 
I'm searching a global solution: if anyone know a solution that work, even without the use of junction it's ok.
I also accept, if it's more easy that C should only be acceeded by network, (or is a network share).
 
Thanks for any help
AnswerRe: Multi target ?memberrumburaky31 Jul '03 - 3:52 
If the contents are only files and A,B,C are folders on the same volume, a solution could be Hard Links (see CreateHardLink in MSDN). However there are some inconvenient if you remove or add files to A and B folders, the change will not be visible in the C folder. If you only change content of the files it will all be ok.
GeneralJunction Pts for C:\Program Files and C:\Documents and SettingsmemberWarrenW8 Jun '03 - 21:06 
I'm trying to link:
 
"C:\Documents and Settings" to "D:\Documents and Settings"
"C:\Program Files" to "D:\Program Files"
 
Since source directories have to be empty to create junction points, a user has to move all subdirectories first. However, once booted into a machine, even in safe mode as "administrator", one cannot move the contents of "Program Files" and "Documents and Settings", because files are open and being written to, etc.
 
I attempted to boot from the Win2K CD in console/rescue mode, move the directories, and then run "junction" (the Sysinternals utility) to make the links. Unfortunately, there is a limited set of commands that can be run from console (pretty much only the DOS command set), so this won't work either.
 
So, is there any way to accomplish this? I'd appreciate any pointers.
 
TIA
 
-- .W
GeneralRe: Junction Pts for C:\Program Files and C:\Documents and SettingsmemberMike Nordell9 Jun '03 - 1:00 
WarrenW wrote:
So, is there any way to accomplish this?
 
The way I do it is to always have another Window installation ready to boot at another volume.
GeneralRe: Junction Pts for C:\Program Files and C:\Documents and SettingsmemberWarrenW9 Jun '03 - 13:53 
I thought about doing this, however I'm also researching creating a bootable Win2K CD.
 
Not easy, however.   I believe such a CD could be created via PE Builder, but that is difficult to get unless you are a developer.
 
I'm also wondering if it's possible by booting from an ERD Commander CD.
 
...developing...
 
-- .W
GeneralRe: Junction Pts for C:\Program Files and C:\Documents and SettingsmemberJohn M. Dlugosz22 Feb '05 - 10:01 
I set up "BartPE" specifically for this purpose. It is a clone of the unobtainable PE mentioned in another reply. You can put on it any programs you want, including this one.
 
But, experimenting with it I found that the drive letter used by the junction needs to match that of the normal boot-time! It uses a drive letter rather than a unique volume name. (I'm going to experiment to see if it will work with the latter).
 
Before that, I accomplished moving Program Files by killing off any processes that still hold files open, or forcing the handles closed. Find out who using the SysInternals tools.
 
In the past, I've done it by renaming the directory as a "pending move", and after rebooting, when nothing works right but I run a command shell, then create a new empty directory and create a junction. However, this last time I found that something was creating files rather than just dieing.
 
--John

GeneralCall me stupid, but....memberhector santos1 Mar '03 - 0:23 
Can someone me an example why this reparse point is useful?
 
I get the idea it is something similar to the SUBST.EXE command which I use alot to assign a virtual drive letter to a specific path. Is this basically the same thing?
 

 

GeneralRe: Call me stupid, but....memberChristopher Lord15 Mar '03 - 12:09 
Its the other way around. It lets you bind drives and folders to a path on any old file system.
 
Say you have a drive for projects, a drive for swap, a drive for programs, and your boot drive.
 
without this API, you are stuck with C:, D:, E:, F:, G:, etc. for labels. Sure you can label the drive, but this doesnt work at the command prompt, nor at other keyboard-only input areas like the run box.
 
With junction points, you can have these drives bound to a path instead. so you can have c:\swap, c:\projects, c:\mp3s, etc, and they function perfectly transparently. The only point where it is not transparent is when drive space vs. recursive size search is performed.
 
How is this useful?
 
Well, besides the increase in organization, it lets you have MULTIPLE junctions. I use it to include a bunch of files in both my PDA sync folder, my laptop sync folder, and my normal working folder. Now changes in my sync folders are automatically mirrored to my working folder, since in reality (bits on disk) they are now the same files with three different paths pointing at them, so that two different applications can work with the files easily, and I dont have to constantly do point-to-point backups.
 
There are other uses, I am sure.
GeneralRe: Call me stupid, but....memberJerry Jeremiah16 Oct '06 - 15:25 
There used to be two commands in DOS:
SUBST.EXE Associates a path with a drive letter.
JOIN.EXE Joins a disk drive to a directory on another disk drive.
 
This article explains an NT equivalent of JOIN.EXE except it also allows you to link a driver letter to a directory or a directory to another directory. So now the same directory can appear in multiple places on your hard drive without actually duplicaing the data.

GeneralJunctions pointing at remote shares/volumessussAnonymous3 Dec '02 - 2:26 
As Dan Piponi writes (in sep. 2000), there isn't really a method to link to a remote shared drive, directory or volume.
 
However, this could be a real cool and wanted feature, at least from my point of view.
Am trying to create a "Virtual File System" in Windows as it is possible in UNIX with NFS mounts and symbolic links.
 
Does anobody know if it is at all possible, to do this??
 
Dan Piponi thinks so, but has anyone "researched" in that direction since?
 
I've not been able to find any information anywhere.
 
Thanks
 
/sune

GeneralRe: Junctions pointing at remote shares/volumesmemberMike Nordell3 Dec '02 - 16:23 
Anonymous wrote:
As Dan Piponi writes (in sep. 2000), there isn't really a method to link to a remote shared drive, directory or volume.
 
Actually, there is! You must however first "login" to that machine since junction points don't provide credentials.
 
If you first by some means gains access to e.g. \\server1\share1, you can actually do
 
md foo
makelink \??\server1\share1 foo
dir foo
 
to get the directory contents of the mentioned share.
 
What you however can not do, is use this on XP. In Windows 2000 this works porfectly. In the shiny-plastic-toyish XP the malicious Macrosoft removed this possibility. You can't even create a junction point formed like this, since it seems NTFS5.1 (or some other part of that toy) nowadays tries to "help" you by making sure the target path is local, valid and accessible.

GeneralRe: Junctions pointing at remote shares/volumesmemberSunemaster4 Dec '02 - 0:38 
Mike Nordell wrote:
Actually, there is!
 
Erhm...
This really doesn't work for me.
 
First of all, doesn't the makelink.exe take the parameters the other way around??
I mean like "makelink c:\foo \??\server\share"
 
Anyways, both methods doesn't seem to work here, even if i already have a connection open to the share.
 
Trying to make the link on a win2k pro (sp3), up against a win2k server (sp3).
 
But perhaps i misunderstood the meaning of "gain access".
Is it enough to have the share already mapped?
Or does it need to be some other form of connection?
 
If i use the format "makelink c:\foo \\??\server\share" (double backslashes) the command hesitates, as if it was actually trying to do it, but errors out after a few secs.
 
Thanks dude...
Nice app.
 
/sune

GeneralRe: Junctions pointing at remote shares/volumesmemberMike Nordell11 Dec '02 - 12:40 
I have tried it with W2k sp2 and I got it to work. W2k sp3 I'm forbidden to install due to the horrible license change. If that [sp3] screws things up I can't say.
 
You could probably solve this by mapping a drive letter to a dir on a non-Micros~1 OS using SAMBA, and from some point in that tree use an NFS mount to... Well, you get the point. You'd need devilish fast net to make it work as-local though...

GeneralRe: Junctions pointing at remote shares/volumesmemberSunemaster12 Dec '02 - 0:20 
Mike,
 
Actually the solution i use today, is a unix server with the remote servers mounted over nfs, and then use symbolic links to the data stored on both the local and remote fileserver (remote office).
 
The data folders and the folder containing all the symlinks is then nfs exported to unix clients, and shared to windows clients.
 
This way all data can be accessed from both unix and windows, only with slow access to the remote data (acceptable).
 
When i saw these junctions in Win2k i was hoping to be able to move the data to a Win2k server.
 
Ah well...
I'll just have to keep looking for another solution.
 
Thanks for your input.
 
/sune

GeneralRe: Junctions pointing at remote shares/volumesmemberrtroncy8 Jan '03 - 22:44 
Hello,
 
I have tried this on both W2k sp1 and W2k sp2 as follows:
 
md temp
makelink temp \??\otherserver\myshare
or
makelink temp \??\n:\
 
(where N: is mapped to \\otherserver\myshare)
 
and I get the following error:
Couldn't create link "temp" -> "\??\otherserver\myshare"
 
Any idea of what I may be missing?
 
Also, is this possible to make a junction point on a volume that is not mounted (with mounvol)? (I'd like to mount separately the folders that reside in the root of a 2nd volume, without the root showing-up in the system)
 
Many thanks
Rem
GeneralRe: Junctions pointing at remote shares/volumesmemberMike Nordell9 Jan '03 - 13:49 
rtroncy wrote:
makelink temp \??\n:\
 
Try
  makelink temp \??\N:
without the trailing backslash. IIRC that's how I had to do it to get it to work.
 
Please note that I don't know how this affects the MS-DOS (which is what we're basically using here) feature that you have different Current Directories for each drive-letter. I.e. would "N:", "CD foo" make the link point to "N:\foo"? Personally I don't even use SMB anymore why I can't test it, but I'm sure you can have "fun" trying it out yourself.
 
Since this is the FAQ, maybe you should tell Micros~1 you want to be able to use SMB this way, much like *nices have been able to mount NFS shares for the last decades? With lots of luck it might actually be included in less than a decade.
 
I'd like to mount separately the folders that reside in the root of a 2nd volume, without the root showing-up in the system
 
When a volume is not mounted, no filesystem driver knows about it and you have no filesystem-ish way to access its contents. Therefore, AFAIK, you need to mount the volume to get access to its contents, which is needed to be able to point a junction point to (anywhere to) it. It won't have to be mounted as a drive-letter, but it still needs to be mounted.
GeneralRe: Junctions pointing at remote shares/volumesmemberSpam Basket10 Feb '03 - 6:55 
Gee, how about using DFS?
GeneralRe: Junctions pointing at remote shares/volumesmemberMike Nordell10 Feb '03 - 7:30 
Spam Basket wrote:
Gee, how about using DFS?
 
I haven't got a clue, but forced to guess I'd answer "No way - that could be useful".
 
Feel free to experiment with the code and report back though.
GeneralRe: Junctions pointing at remote shares/volumesmemberphoton07 Apr '05 - 5:36 
My guess is they want to do the same thing as I.
Create a tree like structure with more than 2 servers. Something like this:
A server connected with the network on one side and connected to 2 other workstations on the other side (probably crossover cables).
For my part i'm trying to share multiple diskspace so Ghost clients (DOS) can access them as one drive with directories.
The problem with DFS is it don't work under DOS.
GeneralRe: Junctions pointing at remote shares/volumesmemberalwaysZeroHour26 Apr '07 - 6:01 
Hi
I am looking into this also. Firstly it IS possible.
To prove this get a open a shared folder in Explorer, say "\\server\theshare\thefolder\"
Now right click on start (XP) and click "open"
You should see the start menu for your user.
Now switch windows back to the Explorer with the share in it, DO NOT CLOSE EITHER EXPLORER WINDOWS!!
Now, click and drag the folder you want to link to the start menu explorer WHILE holding ALT. This should show the shortcut icon moniker on your mouse.
Drop the folder and a softlink is created. This only seems to work to items dragged onto the start menu and not anywhere else I have found. This does though mean Microsoft made it work, they just did not think they could trust us to do it anywhere else (prob incase the share is dead or security authentication issues with the "SYSTEM" account accessing a share).
Anyway hope this inspires someone into figuring the problem out.
 
Remember this was created in the 2000 NT 5 FS, back when MS had support for legacy dos apps. Vista which now allows full symbolic links does not *officially*
I think that MS blocked the creation to stop anyone using them for DOS apps as we all know DOS does not support UNC's unless mapped. If you CMD browse into the folder you will see the target.lnk and the desktop.ini files that help create this virtual folder. The folder itself gets tagged as a system type folder fyi.
GeneralRe: Junctions pointing at remote shares/volumesmemberArgon019 Sep '08 - 2:56 
That's not really a softlink, just a shortcut, a softlink you'd be able to get to from dos...
GeneralHKEY_LOCAL_USERmemberHugo Hallman20 Oct '02 - 23:47 
Is there a way to make a junction point that is local to the user?
(I have no domain or such. not even a network, just a multiuser computer.)
GeneralRe: HKEY_LOCAL_USERmemberMike Nordell21 Oct '02 - 3:16 
Not that I'm aware of, though you could probably emulate it by setting the access control to allow that user only to access the "directory".
GeneralANN: GUI version of MakeLinkmemberJos Branders31 Mar '02 - 5:17 
Junction Link Magic is a GUI version for creating junction links, based on Mike Nordell's code. Take a look here:
 
http://www.rekenwonder.com/linkmagic.htm Smile | :)
GeneralRe: ANN: GUI version of MakeLinkmemberhector santos1 Mar '03 - 0:29 
Question, when is NTFS 5.0 available?
GeneralRe: ANN: GUI version of MakeLinksussJos Branders1 Mar '03 - 21:04 
NT4 with SP4 or Windows 2000/XP.
 
Junction Link Magic only works on Windows 2000/XP though.
 
Jos Branders
GeneralRe: ANN: GUI version of MakeLinkmemberhector santos1 Mar '03 - 0:33 
By the way, I am currently running your utility and it is still scanning the system.
 
Tip: I use many virtual drives. You might want to add some smarts to skip the redundancy scans by checking for equivalent drives. Its been nearly 5 minutes now scanning Smile | :)
GeneralGreat!memberKurt1 Sep '01 - 1:44 
I've been missing this feature for ages! Thanks!

GeneralCool util! Found a good use for it.memberGossamer18 Jun '01 - 13:11 
Cool | :cool: Amazing article! I've been searching high and low for the linkd.exe utility but now I finally found your article, and it worked! I'm really impressed how you found out how it all works without having anything to go on.
 
I have my machine loaded with multiple logons for different networks (domains, etc), and now I can just make a junction for my user directory and not have to set everything up all over again for each user.
GeneralThank'smemberAnonymous27 Apr '01 - 11:10 
it worked fine...
Smile | :)
 
juerg jenzer
GeneralSystinernals junctionmemberAnonymousx16 Apr '01 - 7:42 
How's this different from the junction tool provided by sysinternals?
 
No sig

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 6 Jan 2000
Article Copyright 2000 by Mike Nordell
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid