Symbolic Link/INODE pointer function

Discussion in 'Scripting' started by GodHand, Jan 30, 2018.

  1. GodHand

    GodHand MDL Senior Member

    Jul 15, 2016
    317
    282
    10
    I wrote this function to locate pointers across files and directories to verify where its source information gets gathered from. It uses a C# method and a PowerShell wrapper, and may be useful for those who need to quickly locate a symbolic link to a file or directory so I figured I'd toss it on here for anyone who wants to use it.

    Code:
    #region C# Code Method
    Add-Type @"
    using System;
    using System.Text;
    using System.Runtime.InteropServices;
    using Microsoft.Win32.SafeHandles;
    using System.ComponentModel;
    
    namespace LINK_INTEROP
    {
        public sealed class GetSymbolicLink
        {
            private const int FILE_SHARE_READ = 1;
            private const int FILE_SHARE_WRITE = 2;
            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(string SymbolicLinkPath)
            {
                SafeFileHandle directoryHandle = CreateFile
                    (
                    SymbolicLinkPath,
                    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()
                        );
                if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\')
                    return path.ToString().Substring(4);
                else
                    return path.ToString();
            }
        }
    }
    "@
    #endregion C# Code Method
    
    Function Get-SymbolicLink
    {
       <#
       .SYNOPSIS
           Gets symbolic links from a regular resolvable path.
       
       .DESCRIPTION
           Gets the link of an INODE/file that points to another INODE/file. This allows for verification of true information INODE\link locations.
       
       .PARAMETER Path
           The resolvable path of any file or directory to check for Symbolic Links.
       
       .EXAMPLE
           PS C:\> Get-SymbolicLink -Path "C:\Documents and Settings"
       
       .NOTES
           Symbolic Links are how data is stored on drives.  Being able to "track" them allows a user to locate pointers (paths) an INODE/file may use to access information.
       #>
       [CmdletBinding()]
       Param
       (
           [Parameter(Mandatory = $true,
                      ValueFromPipeline = $true)][ValidateNotNullOrEmpty()][string]$Path
       )
       
       Process
       {
           Return [LINK_INTEROP.GetSymbolicLink]::GetSymbolicLinkTarget($Path)
       }
    }
    
     
  2. GodHand

    GodHand MDL Senior Member

    Jul 15, 2016
    317
    282
    10
    I should have also made it clear that this particular function does no changes to either the symbolic link or anything that would harm a system. It simply shows you where a specific file/INODE points to allowing you to verify information pointers and sources. This can be very useful if trying to track down resolvable paths for any item that uses a symbolic link, which most do. If you're unfamiliar with Symbolic Links, think of them as advanced Junction Points, where an alias is used for data access and not the actual hard-link where the information is truly located.