You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

235 lines
13 KiB

  1. /* Copyright (C) 2008-2016 Peter Palotas, Jeffrey Jangli, Alexandr Normuradov
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. * THE SOFTWARE.
  20. */
  21. using Alphaleonis.Win32.Network;
  22. using System;
  23. using System.Globalization;
  24. using System.IO;
  25. using System.Net.NetworkInformation;
  26. using System.Security;
  27. namespace Alphaleonis.Win32.Filesystem
  28. {
  29. public static partial class Path
  30. {
  31. #region GetMappedConnectionName
  32. /// <summary>[AlphaFS] Gets the connection name of the locally mapped drive.</summary>
  33. /// <returns>The server and share as: \\servername\sharename.</returns>
  34. /// <exception cref="ArgumentException"/>
  35. /// <exception cref="ArgumentNullException"/>
  36. /// <exception cref="PathTooLongException"/>
  37. /// <exception cref="NetworkInformationException"/>
  38. /// <param name="path">The local path with drive name.</param>
  39. [SecurityCritical]
  40. public static string GetMappedConnectionName(string path)
  41. {
  42. return Host.GetRemoteNameInfoCore(path, true).lpConnectionName;
  43. }
  44. #endregion // GetMappedConnectionName
  45. #region GetMappedUncName
  46. /// <summary>[AlphaFS] Gets the network share name from the locally mapped path.</summary>
  47. /// <returns>The network share connection name of <paramref name="path"/>.</returns>
  48. /// <exception cref="ArgumentException"/>
  49. /// <exception cref="ArgumentNullException"/>
  50. /// <exception cref="PathTooLongException"/>
  51. /// <exception cref="NetworkInformationException"/>
  52. /// <param name="path">The local path with drive name.</param>
  53. [SecurityCritical]
  54. public static string GetMappedUncName(string path)
  55. {
  56. return Host.GetRemoteNameInfoCore(path, true).lpUniversalName;
  57. }
  58. #endregion // GetMappedUncName
  59. #region IsUncPath
  60. /// <summary>[AlphaFS] Determines if a path string is a valid Universal Naming Convention (UNC) path.</summary>
  61. /// <returns><see langword="true"/> if the specified path is a Universal Naming Convention (UNC) path, <see langword="false"/> otherwise.</returns>
  62. /// <param name="path">The path to check.</param>
  63. [SecurityCritical]
  64. public static bool IsUncPath(string path)
  65. {
  66. return IsUncPathCore(path, false, true);
  67. }
  68. /// <summary>[AlphaFS] Determines if a path string is a valid Universal Naming Convention (UNC) path, optionally skip invalid path character check.</summary>
  69. /// <returns><see langword="true"/> if the specified path is a Universal Naming Convention (UNC) path, <see langword="false"/> otherwise.</returns>
  70. /// <param name="path">The path to check.</param>
  71. /// <param name="checkInvalidPathChars"><see langword="true"/> will check <paramref name="path"/> for invalid path characters.</param>
  72. [SecurityCritical]
  73. public static bool IsUncPath(string path, bool checkInvalidPathChars)
  74. {
  75. return IsUncPathCore(path, false, checkInvalidPathChars);
  76. }
  77. #endregion // IsUncPath
  78. #region LocalToUnc
  79. /// <summary>[AlphaFS] Converts a local path to a network share path.
  80. /// <para>A Local path, e.g.: "C:\Windows" will be returned as: "\\MachineName\C$\Windows".</para>
  81. /// <para>If a logical drive points to a network share path, the share path will be returned instead.</para>
  82. /// </summary>
  83. /// <returns>On successful conversion a UNC path is returned.
  84. /// <para>If the conversion fails, <paramref name="localPath"/> is returned.</para>
  85. /// <para>If <paramref name="localPath"/> is an empty string or <see langword="null"/>, <see langword="null"/> is returned.</para>
  86. /// </returns>
  87. /// <exception cref="ArgumentException"/>
  88. /// <exception cref="PathTooLongException"/>
  89. /// <exception cref="NetworkInformationException"/>
  90. /// <param name="localPath">A local path, e.g.: "C:\Windows".</param>
  91. [SecurityCritical]
  92. public static string LocalToUnc(string localPath)
  93. {
  94. return LocalToUncCore(localPath, false, false, false);
  95. }
  96. /// <summary>[AlphaFS] Converts a local path to a network share path, optionally returning it in a long path format.
  97. /// <para>A Local path, e.g.: "C:\Windows" will be returned as: "\\MachineName\C$\Windows".</para>
  98. /// <para>If a logical drive points to a network share path, the share path will be returned instead.</para>
  99. /// </summary>
  100. /// <returns>On successful conversion a UNC path is returned.
  101. /// <para>If the conversion fails, <paramref name="localPath"/> is returned.</para>
  102. /// <para>If <paramref name="localPath"/> is an empty string or <see langword="null"/>, <see langword="null"/> is returned.</para>
  103. /// </returns>
  104. /// <exception cref="ArgumentException"/>
  105. /// <exception cref="PathTooLongException"/>
  106. /// <exception cref="NetworkInformationException"/>
  107. /// <param name="localPath">A local path, e.g.: "C:\Windows".</param>
  108. /// <param name="asLongPath"><see langword="true"/> returns the path in long path (Unicode) format, when <see langword="false"/> returns the path as a regular path.</param>
  109. [SecurityCritical]
  110. public static string LocalToUnc(string localPath, bool asLongPath)
  111. {
  112. return LocalToUncCore(localPath, asLongPath, false, false);
  113. }
  114. /// <summary>[AlphaFS] Converts a local path to a network share path, optionally returning it in a long path format and the ability to add or remove a trailing backslash.
  115. /// <para>A Local path, e.g.: "C:\Windows" will be returned as: "\\MachineName\C$\Windows".</para>
  116. /// <para>If a logical drive points to a network share path, the share path will be returned instead.</para>
  117. /// </summary>
  118. /// <returns>On successful conversion a UNC path is returned.
  119. /// <para>If the conversion fails, <paramref name="localPath"/> is returned.</para>
  120. /// <para>If <paramref name="localPath"/> is an empty string or <see langword="null"/>, <see langword="null"/> is returned.</para>
  121. /// </returns>
  122. /// <exception cref="ArgumentException"/>
  123. /// <exception cref="PathTooLongException"/>
  124. /// <exception cref="NetworkInformationException"/>
  125. /// <param name="localPath">A local path, e.g.: "C:\Windows".</param>
  126. /// <param name="asLongPath"><see langword="true"/> returns the path in long path (Unicode) format, when <see langword="false"/> returns the path as a regular path.</param>
  127. /// <param name="addTrailingDirectorySeparator"><see langword="true"/> adds a trailing <see cref="DirectorySeparatorChar"/> character to <paramref name="localPath"/>, when absent.</param>
  128. /// <param name="removeTrailingDirectorySeparator"><see langword="true"/> removes the trailing <see cref="DirectorySeparatorChar"/> character from <paramref name="localPath"/>, when present.</param>
  129. [SecurityCritical]
  130. public static string LocalToUnc(string localPath, bool asLongPath, bool addTrailingDirectorySeparator, bool removeTrailingDirectorySeparator)
  131. {
  132. return LocalToUncCore(localPath, asLongPath, addTrailingDirectorySeparator, removeTrailingDirectorySeparator);
  133. }
  134. #endregion // LocalToUnc
  135. #region Internal Methods
  136. /// <summary>[AlphaFS] Determines if a path string is a valid Universal Naming Convention (UNC) path, optionally skip invalid path character check.</summary>
  137. /// <returns><see langword="true"/> if the specified path is a Universal Naming Convention (UNC) path, <see langword="false"/> otherwise.</returns>
  138. /// <param name="path">The path to check.</param>
  139. /// <param name="isRegularPath">When <see langword="true"/> indicates that <paramref name="path"/> is already in regular path format.</param>
  140. /// <param name="checkInvalidPathChars"><see langword="true"/> will check <paramref name="path"/> for invalid path characters.</param>
  141. [SecurityCritical]
  142. internal static bool IsUncPathCore(string path, bool isRegularPath, bool checkInvalidPathChars)
  143. {
  144. if (!isRegularPath)
  145. path = GetRegularPathCore(path, checkInvalidPathChars ? GetFullPathOptions.CheckInvalidPathChars : 0, false);
  146. else if (checkInvalidPathChars)
  147. CheckInvalidPathChars(path, false, false);
  148. Uri uri;
  149. return Uri.TryCreate(path, UriKind.Absolute, out uri) && uri.IsUnc;
  150. }
  151. /// <summary>Converts a local path to a network share path.
  152. /// <para>A Local path, e.g.: "C:\Windows" will be returned as: "\\MachineName\C$\Windows".</para>
  153. /// <para>If a logical drive points to a network share path, the share path will be returned instead.</para>
  154. /// </summary>
  155. /// <returns>On successful conversion a UNC path is returned.
  156. /// <para>If the conversion fails, <paramref name="localPath"/> is returned.</para>
  157. /// <para>If <paramref name="localPath"/> is an empty string or <see langword="null"/>, <see langword="null"/> is returned.</para>
  158. /// </returns>
  159. /// <exception cref="ArgumentException"/>
  160. /// <exception cref="PathTooLongException"/>
  161. /// <exception cref="NetworkInformationException"/>
  162. /// <param name="localPath">A local path, e.g.: "C:\Windows".</param>
  163. /// <param name="asLongPath"><see langword="true"/> returns the path in long path (Unicode) format, when <see langword="false"/> returns the path as a regular path.</param>
  164. /// <param name="addTrailingDirectorySeparator"><see langword="true"/> adds a trailing <see cref="DirectorySeparatorChar"/> character to <paramref name="localPath"/>, when absent.</param>
  165. /// <param name="removeTrailingDirectorySeparator"><see langword="true"/> removes the trailing <see cref="DirectorySeparatorChar"/> character from <paramref name="localPath"/>, when present.</param>
  166. [SecurityCritical]
  167. internal static string LocalToUncCore(string localPath, bool asLongPath, bool addTrailingDirectorySeparator, bool removeTrailingDirectorySeparator)
  168. {
  169. if (Utils.IsNullOrWhiteSpace(localPath))
  170. return null;
  171. localPath = GetRegularPathCore(localPath, GetFullPathOptions.CheckInvalidPathChars, false);
  172. if (!IsUncPathCore(localPath, true, false))
  173. {
  174. if (localPath[0] == CurrentDirectoryPrefixChar || !IsPathRooted(localPath, false))
  175. localPath = GetFullPathCore(null, localPath, GetFullPathOptions.None);
  176. string drive = GetPathRoot(localPath, false);
  177. if (Utils.IsNullOrWhiteSpace(drive))
  178. return localPath;
  179. Network.NativeMethods.REMOTE_NAME_INFO unc = Host.GetRemoteNameInfoCore(drive, true);
  180. if (!Utils.IsNullOrWhiteSpace(unc.lpConnectionName))
  181. // Only leave trailing backslash if "localPath" also ends with backslash.
  182. return localPath.EndsWith(DirectorySeparator, StringComparison.OrdinalIgnoreCase)
  183. ? AddTrailingDirectorySeparator(unc.lpConnectionName, false)
  184. : RemoveTrailingDirectorySeparator(unc.lpConnectionName, false);
  185. // Split: localDrive[0] = "C", localDrive[1] = "\Windows"
  186. string[] localDrive = localPath.Split(VolumeSeparatorChar);
  187. // Return: "\\MachineName\C$\Windows"
  188. localPath = string.Format(CultureInfo.CurrentCulture, "{0}{1}{2}${3}", Host.GetUncName(), DirectorySeparatorChar, localDrive[0], localDrive[1]);
  189. }
  190. // Only leave trailing backslash if "localPath" also ends with backslash.
  191. addTrailingDirectorySeparator = addTrailingDirectorySeparator ||
  192. (localPath.EndsWith(DirectorySeparator, StringComparison.OrdinalIgnoreCase) && !removeTrailingDirectorySeparator);
  193. var options = (addTrailingDirectorySeparator ? GetFullPathOptions.AddTrailingDirectorySeparator : 0) |
  194. (removeTrailingDirectorySeparator ? GetFullPathOptions.RemoveTrailingDirectorySeparator : 0);
  195. return asLongPath ? GetLongPathCore(localPath, options) : localPath;
  196. }
  197. #endregion // Internal Methods
  198. }
  199. }