Last active
April 15, 2019 00:08
-
-
Save Trucido/dcd6d49f6c9533c4832c84d7f92854b5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Get-LinkTarget.ps1 | |
# Note: Script should be symlinked as follows: | |
# Get-LinkTarget.ps1 -> Resolve-UNCPath.ps1 | |
# Get-LinkTarget.ps1 -> Resolve-JunctionPath.ps1 | |
# Get-LinkTarget.ps1 -> Resolve-HardlinkPath.ps1 | |
# Get-LinkTarget.ps1 -> Resolve-SymlinkPath.ps1 | |
# Get-LinkTarget.ps1 -> Resolve-ReparsePointPath.ps1 | |
function Global:Get_UNCPath($l_dir) | |
{ | |
if( ( ([System.Management.Automation.PSTypeName]'System.Win32').Type -eq $null) -or | |
([system.win32].getmethod('GetSymbolicLinkTarget') -eq $null ) ) | |
{ | |
Add-Type -MemberDefinition @" | |
private const int CREATION_DISPOSITION_OPEN_EXISTING = 3; | |
private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; | |
[DllImport("kernel32.dll", EntryPoint = "GetFinalPathNameByHandleW", CharSet = CharSet.Unicode, SetLastError = true)] | |
public static extern int GetFinalPathNameByHandle(IntPtr handle, [In, Out] StringBuilder path, int bufLen, int flags); | |
[DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true)] | |
public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, | |
IntPtr SecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); | |
public static string GetSymbolicLinkTarget(System.IO.DirectoryInfo symlink) | |
{ | |
SafeFileHandle directoryHandle = CreateFile(symlink.FullName, 0, 2, System.IntPtr.Zero, CREATION_DISPOSITION_OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, System.IntPtr.Zero); | |
if(directoryHandle.IsInvalid) | |
{ | |
throw new Win32Exception(Marshal.GetLastWin32Error()); | |
} | |
StringBuilder path = new StringBuilder(512); | |
int size = GetFinalPathNameByHandle(directoryHandle.DangerousGetHandle(), path, path.Capacity, 0); | |
if (size<0) | |
{ | |
throw new Win32Exception(Marshal.GetLastWin32Error()); | |
} | |
// The remarks section of GetFinalPathNameByHandle mentions the return being prefixed with "\\?\" | |
// More information about "\\?\" here -> http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx | |
string sPath = path.ToString(); | |
if( sPath.Length>8 && sPath.Substring(0,8) == @"\\?\UNC\" ) | |
{ | |
return @"\" + sPath.Substring(7); | |
} | |
else if( sPath.Length>4 && sPath.Substring(0,4) == @"\\?\" ) | |
{ | |
return sPath.Substring(4); | |
} | |
else | |
{ | |
return sPath; | |
} | |
} | |
"@ -Name Win32 -NameSpace System -UsingNamespace System.Text,Microsoft.Win32.SafeHandles,System.ComponentModel | |
} | |
[System.Win32]::GetSymbolicLinkTarget($l_dir) | |
} | |
function Global:Get_JunctionTarget([string]$p_path) | |
{ | |
$l_target = fsutil reparsepoint query $p_path | where-object { $_ -imatch 'Print Name\:' } | foreach-object { $_ -replace 'Print Name\:\s*','' } | |
if( $l_target -imatch "(^[A-Z])\:\\" ) | |
{ | |
$l_drive = $matches[1] | |
$l_uncPath = Get_UncPath $p_path | |
if( $l_uncPath -imatch "(^\\\\[^\\]*\\)" ) | |
{ | |
$l_machine = $matches[1] | |
$l_target = $l_target -replace "^$l_drive\:","$l_machine$l_drive$" | |
} | |
} | |
$l_target | |
} | |
function Global:Get_LinkTargetPath | |
{ | |
foreach($item in $args) | |
{ | |
$itemTarget = try { (Get-Item $item -Force).Target } catch {} | |
if( !$itemTarget ) | |
{ | |
continue | |
} | |
if( $itemTarget) | |
{ | |
$itemTarget # TODO: resolve target PSPath | |
} | |
} | |
} | |
if( !( $MyInvocation.InvocationName -eq '.' -or $MyInvocation.Line -eq '' ) ) | |
{ | |
if( $null -ne $MyInvocation.MyCommand.Name ) | |
{ | |
switch -Wildcard ( $MyInvocation.MyCommand.Name ) | |
{ | |
"*UNC*" { Get_UNCPath $args } | |
"*Junction*" { Get_JunctionPath $args } | |
"*Reparse*" { Get_JunctionPath $args } | |
"*Sym*" { Get_LinkTargetPath $args } | |
"*Hard*" { Get_LinkTargetPath $args } | |
} | |
} | |
} | |
else {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment