Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programmatically access the target path of a windows symbolic link?

Windows 6 (Vista and Server 2008) support proper symbolic links, which can be created via the CreateSymbolicLink function. But there doesn't appear to be a corresponding function for interrogating a symbolic link to obtain the path of the link's target.

I have found out that symbolic links are an implementation of reparse points, and so the reparse point functions can be used to obtain the target path. But the header files that I need to use reparse points appear to come with the Windows Driver Kit. Setting up this kit with VS2008 appears to be a non trivial task.

Is there a nice simple function that I've missed for obtaining a link's target, or do I really have to set up a windows driver development environment just to write code to access this information?

EDIT: Adam Mitz came up with the suggestion of GetFinalPathNameByHandle. This function works just great for local symlinks, but doesn't appear to work for resolving remote links (via a UNC path).

EDIT 2: At Adam's request, here are more details of what I've tried:

I initially went down the FSCTL_GET_REPARSE_POINT/ DeviceIoControl route, but that yields a REPARSE_DATA_BUFFER structure. The headers that define this structure seem to exist solely within the Windows Driver Kit.

GetFinalPathNameByHandle() works fine when the link exists on a local disk (C:\...\link etc). Curiously, I found that I could obtain the handle to the link - and thus get the target - using CreateFileW() whether the FILE_FLAG_OPEN_REPARSE_POINT flag was specified or not, regardless of whether the target file exists.

When CreateFileW() and GetFinalPathNameByHandle() are used to interrogate a remote link though (\\?\UNC\....), things start to unravel. If FILE_FLAG_OPEN_REPARSE_POINT is specified, GetFinalPathNameByHandle() always returns the link path, not the target path. If FILE_FLAG_OPEN_REPARSE_POINT is not specified, then the target path is returned, but only if the target exists and is on the same machine as the link. If the link points to another machine, I get a network permissions error. If the link points to a local - non-existent - file, I get a file not found error.

like image 240
David Arno Avatar asked Oct 21 '08 10:10

David Arno


1 Answers

GetFinalPathNameByHandle

A final path is the path that is returned when a path is fully resolved. For example, for a symbolic link named "C:\tmp\mydir" that points to "D:\yourdir", the final filesystem path would be "D:\yourdir".

like image 80
Adam Mitz Avatar answered Oct 13 '22 15:10

Adam Mitz