Skip to content

Commit

Permalink
fixes #3
Browse files Browse the repository at this point in the history
  • Loading branch information
activescott committed Sep 8, 2016
1 parent ec80146 commit c88e8a4
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 39 deletions.
12 changes: 6 additions & 6 deletions src/LessIO.Tests/PathTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,24 +185,24 @@ public void UNCLongFormPathsShouldBeRooted()
[Fact]
public void UNCLongFormPathsGetPathRoot()
{
TestGetPathRoot(@"\\ComputerName\SharedFolder", Win32LongPathPrefixUNC + @"\ComputerName\SharedFolder\subfolder");
TestGetPathRoot(@"\\ComputerName\SharedFolder", Win32LongPathPrefixUNC + @"\ComputerName\SharedFolder\subfolder\");
TestGetPathRoot(@"\\ComputerName\SharedFolder", Win32LongPathPrefixUNC + @"\ComputerName\SharedFolder\subfolder\another");
TestGetPathRoot(@"\\ComputerName\SharedFolder", Win32LongPathPrefixUNC + @"\ComputerName\SharedFolder");
TestGetPathRoot(@"\\ComputerName\SharedFolder", Win32LongPathPrefixUNC + @"ComputerName\SharedFolder\subfolder");
TestGetPathRoot(@"\\ComputerName\SharedFolder", Win32LongPathPrefixUNC + @"ComputerName\SharedFolder\subfolder\");
TestGetPathRoot(@"\\ComputerName\SharedFolder", Win32LongPathPrefixUNC + @"ComputerName\SharedFolder\subfolder\another");
TestGetPathRoot(@"\\ComputerName\SharedFolder", Win32LongPathPrefixUNC + @"ComputerName\SharedFolder");
}

[Fact]
public void WithPrefixShouldIncludeUNCPrefix()
{
var p = new LessIO.Path(@"\\ComputerName\SharedFolder");
Assert.Equal(Win32LongPathPrefixUNC + @"\ComputerName\SharedFolder", p.WithWin32LongPathPrefix());
Assert.Equal(Win32LongPathPrefixUNC + @"ComputerName\SharedFolder", p.WithWin32LongPathPrefix());
}

[Fact]
public void WithPrefixShouldIncludeStandardPrefix()
{
var p = new Path(@"c:\dir\\file.ext");
Assert.Equal(Win32LongPathPrefixUNC + Win32LongPathPrefix + @"c:\dir\\file.ext", p.WithWin32LongPathPrefix());
Assert.Equal(Win32LongPathPrefix + @"c:\dir\file.ext", p.WithWin32LongPathPrefix());
}
}
}
63 changes: 30 additions & 33 deletions src/LessIO/Path.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ public struct Path : IEquatable<Path>
private static readonly string _pathEmpty = string.Empty;
public static readonly Path Empty = new Path();

/// <summary>
/// This is the special prefix to prepend to paths to support up to 32,767 character paths.
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
/// </summary>
private static readonly string Win32LongPathPrefix = @"\\?\";
/// <summary>
/// This is the special prefix to prepend to paths to support long paths for UNC paths.
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
/// </summary>
private static readonly string Win32LongPathPrefixUNC = @"\\?\UNC\";

private static readonly string UNCPrefix = @"\\";

// TODO: Add validation using a strategy? Or just use it as a strongly typed path to force caller to be explicit?

public Path(string path)
Expand Down Expand Up @@ -53,11 +66,13 @@ private static string StripDirectorySeperatorPostfix(string path)

private static string StripWin32PathPrefix(string pathString)
{
//TODO: UNC
if (pathString.StartsWith(Path.Win32LongPathPrefixDontUse))
return pathString.Substring(Path.Win32LongPathPrefixDontUse.Length);
else
return pathString;
if (pathString.StartsWith(Win32LongPathPrefixUNC))
return UNCPrefix + pathString.Substring(Win32LongPathPrefixUNC.Length);

if (pathString.StartsWith(Win32LongPathPrefix))
return pathString.Substring(Win32LongPathPrefix.Length);

return pathString;
}

/// <summary>
Expand Down Expand Up @@ -192,45 +207,27 @@ internal static bool Equals(Path a, Path b)
return PathEquals(a.PathString, b.PathString);
}


/// <summary>
/// This is the special prefix to prepend to paths to support up to 32,767 character paths.
/// </summary>
private static readonly string Win32LongPathPrefixDontUse = @"\\?\";
/*
/// <summary>
/// Returns the specified path with the <see cref="LongPathPrefix"/> prepended if necessary.
/// </summary>
public static string EnsureWin32LongPathPrefix(string path)
{
//TODO: Needs to look for/support UNC path prefix too!
if (!path.StartsWith(Win32LongPathPrefixDontUse)) // More consistent to deal with if we just add it to all of them: if (!path.StartsWith(LongPathPrefix) && path.Length >= MAX_PATH)
return Win32LongPathPrefixDontUse + path;
else
return path;
}
public static Path EnsureWin32LongPathPrefix(Path path)
{
return new Path(EnsureWin32LongPathPrefix(path.ToString()));
}
*/

/// <summary>
/// Long-form filenames are not supported by the .NET system libraries, so we do win32 calls.
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#maxpath
/// </summary>
/// <remarks>
/// The <see cref="Path"/> object will never store the Win32 long path prefix. Instead use this method to trim it off when necessary.
/// The <see cref="Path"/> object will never store the Win32 long path prefix. Instead use this method to add it back when necessary (i.e. when making direct calls into Win32 APIs).
/// </remarks>
public string WithWin32LongPathPrefix()
{
const string Win32LongPathPrefix = @"\\?\";
//TODO: Needs to look for/support UNC path prefix too!
if (!PathString.StartsWith(Win32LongPathPrefix)) // More consistent to deal with if we just add it to all of them: if (!path.StartsWith(LongPathPrefix) && path.Length >= MAX_PATH)
return Win32LongPathPrefix + this.PathString;
{
if (PathString.StartsWith(UNCPrefix))
return Win32LongPathPrefixUNC + this.PathString.Substring(UNCPrefix.Length);
else
return Win32LongPathPrefix + this.PathString;
}
else
{
//NOTE that Win32LongPathPrefixUNC is a superset of Win32LongPathPrefix we just assume the right pathprefix is already there.
return this.PathString;
}
}

public override int GetHashCode()
Expand Down
7 changes: 7 additions & 0 deletions src/LessIO/Strategies/Win32/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@ internal class NativeMethods
internal const int MAX_PATH = 260;
/// <summary>
/// This is the special prefix to prepend to paths to support up to 32,767 character paths.
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
/// </summary>
internal static readonly string LongPathPrefix = @"\\?\";

/// <summary>
/// This is the special prefix to prepend to UNC paths to support up to 32,767 character paths.
/// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
/// </summary>
internal static readonly string LongPathPrefixUNC = @"\\?\UNC\";

internal static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

[StructLayout(LayoutKind.Sequential)]
Expand Down

0 comments on commit c88e8a4

Please sign in to comment.