The following works in my test setup, which use GetFinalPathNameByHandle
.
var
LinkHandle: THandle;
TargetName: array [0..512] of Char;
begin
LinkHandle := CreateFile('[path to sym link]', 0, FILE_SHARE_READ, nil,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
Win32Check(LinkHandle <> INVALID_HANDLE_VALUE);
try
if GetFinalPathNameByHandle(LinkHandle, TargetName, 512,
FILE_NAME_NORMALIZED) > 0 then
ShowMessage(TargetName)
else
RaiseLastOSError;
finally
CloseHandle(LinkHandle);
end;
end;
The target path is displayed as \\?\UNC\Server\Share\Folder\SubFolder\
. You can test the left-most side agains \\?\UNC
and replace it with \
if you like.
You can also substitute VOLUME_NAME_NONE
in place of FILE_NAME_NORMALIZED
to have the target path as \Server\Share\Folder\SubFolder\
.
The RTL use the same function in one of its tries with VOLUME_NAME_NT
as result type which returns a path like Device\Mup\..
, and then tries to match the starting part of the string with one of the local logical volumes (GetLogicalDriveStrings
). When there's no match, since the path points to a network drive, it returns an empty string as you have noted.
Do note the comment in the RTL sources regarding symbolic links across machine boundary though:
The access rights of symlinks are unpredictable over network drives. It is therefore not recommended to create symlinks over a network drive. To enable remote access of symlinks under Windows Vista and Windows 7 use the command: "fsutil behavior set SymlinkEvaluation R2R:1 R2L:1"