diff --git a/WitcherScriptMerger/Extensions.cs b/WitcherScriptMerger/Extensions.cs index 8d3585d..0d84725 100644 --- a/WitcherScriptMerger/Extensions.cs +++ b/WitcherScriptMerger/Extensions.cs @@ -8,6 +8,8 @@ namespace WitcherScriptMerger { + using System.IO; + static class Extensions { #region Strings @@ -56,6 +58,13 @@ public static string GetPluralS(this int num) #endregion + #region FileInfo + public static string ResolveTargetFileFullName(this FileInfo fileInfo) + { + return fileInfo.Exists ? SimLink.GetSymbolicLinkTarget(fileInfo) : fileInfo.FullName; + } + #endregion + #region Tree & Context Menu public static IEnumerable GetAvailableItems(this ContextMenuStrip menu) diff --git a/WitcherScriptMerger/SimLink.cs b/WitcherScriptMerger/SimLink.cs new file mode 100644 index 0000000..6672f9b --- /dev/null +++ b/WitcherScriptMerger/SimLink.cs @@ -0,0 +1,61 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.Win32.SafeHandles; + +namespace WitcherScriptMerger +{ + /// + /// Provides access to NTFS junction points in .Net. + /// + public static class SimLink + { + private const int CREATION_DISPOSITION_OPEN_EXISTING = 3; + + private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; + + // http://msdn.microsoft.com/en-us/library/aa364962%28VS.85%29.aspx + [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); + + // http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx + [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(FileInfo symlink) + { + var fileHandle = CreateFile(symlink.FullName, 0, 2, IntPtr.Zero, CREATION_DISPOSITION_OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero); + if (fileHandle.IsInvalid) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + + var path = new StringBuilder(512); + var size = GetFinalPathNameByHandle(fileHandle.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 + if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\') + { + return path.ToString().Substring(4); + } + return path.ToString(); + } + } +} \ No newline at end of file diff --git a/WitcherScriptMerger/Tools/KDiff3.cs b/WitcherScriptMerger/Tools/KDiff3.cs index 35fbfcf..090fe67 100644 --- a/WitcherScriptMerger/Tools/KDiff3.cs +++ b/WitcherScriptMerger/Tools/KDiff3.cs @@ -32,8 +32,12 @@ public static int Run( ? "\"" + vanillaFile.FullName + "\" " : ""); + // resolve any simlinked files + var source1FullName = source1.TextFile.ResolveTargetFileFullName(); + var source2FullName = source2.TextFile.ResolveTargetFileFullName(); + args += - $"\"{source1.TextFile.FullName}\" \"{source2.TextFile.FullName}\" " + + $"\"{source1FullName}\" \"{source2FullName}\" " + $"-o \"{outputPath}\" " + "--cs \"WhiteSpace3FileMergeDefault=2\" " + "--cs \"CreateBakFiles=0\" " + @@ -51,7 +55,7 @@ public static int Run( if (!Program.Settings.Get("ReviewEachMerge") && hasVanillaVersion) { - if (source1.TextFile.FullName.EqualsIgnoreCase(outputPath) + if (source1FullName.EqualsIgnoreCase(outputPath) && source2.Hash != null && source2.Hash.IsOutdated) { Program.MainForm.ShowMessage( diff --git a/WitcherScriptMerger/WitcherScriptMerger.csproj b/WitcherScriptMerger/WitcherScriptMerger.csproj index d124350..62d5ed1 100644 --- a/WitcherScriptMerger/WitcherScriptMerger.csproj +++ b/WitcherScriptMerger/WitcherScriptMerger.csproj @@ -69,6 +69,7 @@ OptionsForm.cs +