This post originated from an RSS feed registered with Ruby Buzz
by Daniel Berger.
Original Post: Symlinks for Windows
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
This weekend I finally got around to working on the C version of the Win32 junction code. Timothy Byrd originally submitted a pure Ruby version using the Win32API module but I decided, for various reasons, that I wanted it in C. So, I recreated it as a C extension.
Junctions in Windows are a pain. The first problem is that they aren't well documented. There is no CreateJunction() method, or anything so simple. Second, the definition of the REPARSE_DATA_BUFFER structure was actually removed from the SDK after VC++ 6.0. I have no idea why, nor does anyone else, it seems. Third, the definition of FSCTL_SET_REPARSE_POINT is different in different versions of the SDK. Lastly, there are some Unicode issues that I haven't yet figured out how to resolve.
Fortunately, this is all well documented in Mike Nordell's Windows 2000 Junction Points article, from which both Timothy Byrd and Autrijus Tang clearly (and smartly) borrow.
I looked at both Timothy's version, and Autrijus' Win32::Symlink Perl module, took ideas from both, and added some Unicode support on my own, mostly by using tchar.h functions wherever possible. Timothy smartly uses GetFullPathName() so that folks can use relative paths if they want to, while Autrijus provides a custom CTL_CODE instead of using FSCTL_SET_REPARSE_POINT, since the latter is unreliable in its definition between versions of the SDK.
I also decided, with support from folks on the mailing list, to make this Dir.create_junction, instead of trying to define File.symlink for Windows. The problem with the latter is that symlinks only work for directories on Windows, not regular files, so I didn't want there to be any confusion. It would be easy enough to create a facade, however, if folks really want it.