Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 

396 rindas
22 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.Filesystem;
  22. using System;
  23. using System.Collections.Generic;
  24. using System.Diagnostics.CodeAnalysis;
  25. using System.Globalization;
  26. using System.Linq;
  27. using System.Net.NetworkInformation;
  28. using System.Security;
  29. namespace Alphaleonis.Win32.Network
  30. {
  31. partial class Host
  32. {
  33. #region EnumerateOpenConnections
  34. /// <summary>Enumerates open connections from the local host.</summary>
  35. /// <returns><see cref="OpenConnectionInfo"/> connection information from the local host.</returns>
  36. /// <exception cref="ArgumentNullException"/>
  37. /// <exception cref="NetworkInformationException"/>
  38. [SecurityCritical]
  39. public static IEnumerable<OpenConnectionInfo> EnumerateOpenConnections()
  40. {
  41. return EnumerateOpenConnectionsCore(null, null, false);
  42. }
  43. /// <summary>Enumerates open connections from the specified host.</summary>
  44. /// <returns><see cref="OpenConnectionInfo"/> connection information from the specified <paramref name="host"/>.</returns>
  45. /// <exception cref="ArgumentNullException"/>
  46. /// <exception cref="NetworkInformationException"/>
  47. /// <param name="host">The DNS or NetBIOS name of the remote server. <see langword="null"/> refers to the local host.</param>
  48. /// <param name="share">The name of the Server Message Block (SMB) share.</param>
  49. /// <param name="continueOnException">
  50. /// <para><see langword="true"/> suppress any Exception that might be thrown as a result from a failure,</para>
  51. /// <para>such as unavailable resources.</para>
  52. /// </param>
  53. [SecurityCritical]
  54. public static IEnumerable<OpenConnectionInfo> EnumerateOpenConnections(string host, string share, bool continueOnException)
  55. {
  56. return EnumerateOpenConnectionsCore(host, share, continueOnException);
  57. }
  58. #endregion // EnumerateOpenConnections
  59. #region EnumerateShares
  60. /// <summary>Enumerates Server Message Block (SMB) shares from the local host.</summary>
  61. /// <returns><see cref="IEnumerable{ShareInfo}"/> shares from the specified host.</returns>
  62. /// <remarks>This method also enumerates hidden shares.</remarks>
  63. [SecurityCritical]
  64. public static IEnumerable<ShareInfo> EnumerateShares()
  65. {
  66. return EnumerateSharesCore(null, ShareType.All, false);
  67. }
  68. /// <summary>Enumerates Server Message Block (SMB) shares from the local host.</summary>
  69. /// <returns><see cref="IEnumerable{ShareInfo}"/> shares from the specified host.</returns>
  70. /// <remarks>This method also enumerates hidden shares.</remarks>
  71. /// <param name="continueOnException"><see langword="true"/> suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  72. [SecurityCritical]
  73. public static IEnumerable<ShareInfo> EnumerateShares(bool continueOnException)
  74. {
  75. return EnumerateSharesCore(null, ShareType.All, continueOnException);
  76. }
  77. /// <summary>Enumerates Server Message Block (SMB) shares from the local host.</summary>
  78. /// <returns><see cref="IEnumerable{ShareInfo}"/> shares from the specified host.</returns>
  79. /// <remarks>This method also enumerates hidden shares.</remarks>
  80. /// <param name="shareType">The type of the shared resource to retrieve.</param>
  81. /// <param name="continueOnException"><see langword="true"/> suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  82. [SecurityCritical]
  83. public static IEnumerable<ShareInfo> EnumerateShares(ShareType shareType, bool continueOnException)
  84. {
  85. return EnumerateSharesCore(null, shareType, continueOnException);
  86. }
  87. /// <summary>Enumerates Server Message Block (SMB) shares from the specified <paramref name="host"/>.</summary>
  88. /// <returns><see cref="IEnumerable{ShareInfo}"/> shares from the specified host.</returns>
  89. /// <remarks>This method also enumerates hidden shares.</remarks>
  90. /// <param name="host">The DNS or NetBIOS name of the specified host.</param>
  91. [SecurityCritical]
  92. public static IEnumerable<ShareInfo> EnumerateShares(string host)
  93. {
  94. return EnumerateSharesCore(host, ShareType.All, false);
  95. }
  96. /// <summary>Enumerates Server Message Block (SMB) shares from the specified <paramref name="host"/>.</summary>
  97. /// <returns><see cref="IEnumerable{ShareInfo}"/> shares from the specified host.</returns>
  98. /// <remarks>This method also enumerates hidden shares.</remarks>
  99. /// <param name="host">The DNS or NetBIOS name of the specified host.</param>
  100. /// <param name="continueOnException"><see langword="true"/> suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  101. [SecurityCritical]
  102. public static IEnumerable<ShareInfo> EnumerateShares(string host, bool continueOnException)
  103. {
  104. return EnumerateSharesCore(host, ShareType.All, continueOnException);
  105. }
  106. /// <summary>Enumerates Server Message Block (SMB) shares from the specified <paramref name="host"/>.</summary>
  107. /// <returns><see cref="IEnumerable{ShareInfo}"/> shares from the specified host.</returns>
  108. /// <remarks>This method also enumerates hidden shares.</remarks>
  109. /// <param name="host">The DNS or NetBIOS name of the specified host.</param>
  110. /// <param name="shareType">The type of the shared resource to retrieve.</param>
  111. /// <param name="continueOnException"><see langword="true"/> suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  112. [SecurityCritical]
  113. public static IEnumerable<ShareInfo> EnumerateShares(string host, ShareType shareType, bool continueOnException)
  114. {
  115. return EnumerateSharesCore(host, shareType, continueOnException);
  116. }
  117. #endregion // EnumerateShares
  118. #region GetHostShareFromPath
  119. /// <summary>Gets the host and share path name for the given <paramref name="uncPath"/>.</summary>
  120. /// <param name="uncPath">The share in the format: \\host\share.</param>
  121. /// <returns>The host and share path. For example, if <paramref name="uncPath"/> is: "\\SERVER001\C$\WINDOWS\System32",
  122. /// its is returned as string[0] = "SERVER001" and string[1] = "\C$\WINDOWS\System32".
  123. /// <para>If the conversion from local path to UNC path fails, <see langword="null"/> is returned.</para>
  124. /// </returns>
  125. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Utils.IsNullOrWhiteSpace validates arguments.")]
  126. [SecurityCritical]
  127. public static string[] GetHostShareFromPath(string uncPath)
  128. {
  129. if (Utils.IsNullOrWhiteSpace(uncPath))
  130. return null;
  131. Uri uri;
  132. if (Uri.TryCreate(Path.GetRegularPathCore(uncPath, GetFullPathOptions.None, false), UriKind.Absolute, out uri) && uri.IsUnc)
  133. {
  134. return new[]
  135. {
  136. uri.Host,
  137. uri.AbsolutePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar)
  138. };
  139. }
  140. return null;
  141. }
  142. #endregion // GetHostShareFromPath
  143. #region GetShareInfo
  144. /// <summary>Retrieves information about the Server Message Block (SMB) share as defined on the specified host.</summary>
  145. /// <returns>A <see cref="ShareInfo"/> class, or <see langword="null"/> on failure or when not available, and <paramref name="continueOnException"/> is <see langword="true"/>.</returns>
  146. /// <param name="uncPath">The share in the format: \\host\share.</param>
  147. /// <param name="continueOnException"><see langword="true"/> to suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  148. [SecurityCritical]
  149. public static ShareInfo GetShareInfo(string uncPath, bool continueOnException)
  150. {
  151. string[] unc = GetHostShareFromPath(uncPath);
  152. return GetShareInfoCore(ShareInfoLevel.Info503, unc[0], unc[1], continueOnException);
  153. }
  154. /// <summary>Retrieves information about the Server Message Block (SMB) share as defined on the specified host.</summary>
  155. /// <returns>A <see cref="ShareInfo"/> class, or <see langword="null"/> on failure or when not available, and <paramref name="continueOnException"/> is <see langword="true"/>.</returns>
  156. /// <param name="shareLevel">One of the <see cref="ShareInfoLevel"/> options.</param>
  157. /// <param name="uncPath">The share in the format: \\host\share.</param>
  158. /// <param name="continueOnException"><see langword="true"/> to suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  159. [SecurityCritical]
  160. public static ShareInfo GetShareInfo(ShareInfoLevel shareLevel, string uncPath, bool continueOnException)
  161. {
  162. string[] unc = GetHostShareFromPath(uncPath);
  163. return GetShareInfoCore(shareLevel, unc[0], unc[1], continueOnException);
  164. }
  165. /// <summary>Retrieves information about the Server Message Block (SMB) share as defined on the specified host.</summary>
  166. /// <returns>A <see cref="ShareInfo"/> class, or <see langword="null"/> on failure or when not available, and <paramref name="continueOnException"/> is <see langword="true"/>.</returns>
  167. /// <param name="host">The DNS or NetBIOS name of the specified host.</param>
  168. /// <param name="share">The name of the Server Message Block (SMB) share.</param>
  169. /// <param name="continueOnException"><see langword="true"/> to suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  170. [SecurityCritical]
  171. public static ShareInfo GetShareInfo(string host, string share, bool continueOnException)
  172. {
  173. return GetShareInfoCore(ShareInfoLevel.Info503, host, share, continueOnException);
  174. }
  175. /// <summary>Retrieves information about the Server Message Block (SMB) share as defined on the specified host.</summary>
  176. /// <returns>A <see cref="ShareInfo"/> class, or <see langword="null"/> on failure or when not available, and <paramref name="continueOnException"/> is <see langword="true"/>.</returns>
  177. /// <param name="shareLevel">One of the <see cref="ShareInfoLevel"/> options.</param>
  178. /// <param name="host">A string that specifies the DNS or NetBIOS name of the specified <paramref name="host"/>.</param>
  179. /// <param name="share">A string that specifies the name of the Server Message Block (SMB) share.</param>
  180. /// <param name="continueOnException"><see langword="true"/> to suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  181. [SecurityCritical]
  182. public static ShareInfo GetShareInfo(ShareInfoLevel shareLevel, string host, string share, bool continueOnException)
  183. {
  184. return GetShareInfoCore(shareLevel, host, share, continueOnException);
  185. }
  186. #endregion // GetShareInfo
  187. #region Internal Methods
  188. #region EnumerateOpenConnectionsCore
  189. /// <summary>Enumerates open connections from the specified host.</summary>
  190. /// <returns><see cref="OpenConnectionInfo"/> connection information from the specified <paramref name="host"/>.</returns>
  191. /// <exception cref="ArgumentNullException"/>
  192. /// <exception cref="NetworkInformationException"/>
  193. /// <param name="host">The DNS or NetBIOS name of the remote server. <see langword="null"/> refers to the local host.</param>
  194. /// <param name="share">The name of the Server Message Block (SMB) share.</param>
  195. /// <param name="continueOnException"><see langword="true"/> suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  196. [SecurityCritical]
  197. private static IEnumerable<OpenConnectionInfo> EnumerateOpenConnectionsCore(string host, string share, bool continueOnException)
  198. {
  199. if (Utils.IsNullOrWhiteSpace(share))
  200. throw new ArgumentNullException("share");
  201. return EnumerateNetworkObjectCore(new FunctionData { ExtraData1 = share }, (NativeMethods.CONNECTION_INFO_1 structure, SafeGlobalMemoryBufferHandle buffer) =>
  202. new OpenConnectionInfo(host, structure),
  203. (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle) =>
  204. {
  205. // When host == null, the local computer is used.
  206. // However, the resulting OpenResourceInfo.Host property will be empty.
  207. // So, explicitly state Environment.MachineName to prevent this.
  208. // Furthermore, the UNC prefix: \\ is not required and always removed.
  209. string stripUnc = Utils.IsNullOrWhiteSpace(host) ? Environment.MachineName : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty);
  210. return NativeMethods.NetConnectionEnum(stripUnc, functionData.ExtraData1, 1, out buffer, NativeMethods.MaxPreferredLength, out entriesRead, out totalEntries, out resumeHandle);
  211. },
  212. continueOnException);
  213. }
  214. #endregion // EnumerateOpenConnectionsCore
  215. #region EnumerateSharesCore
  216. /// <summary>Enumerates Server Message Block (SMB) shares from a local or remote host.</summary>
  217. /// <returns><see cref="IEnumerable{ShareInfo}"/> shares from the specified host.</returns>
  218. /// <remarks>This method also enumerates hidden shares.</remarks>
  219. /// <exception cref="ArgumentNullException"/>
  220. /// <exception cref="NetworkInformationException"/>
  221. /// <param name="host">The DNS or NetBIOS name of the specified host.</param>
  222. /// <param name="shareType">The type of the shared resource to retrieve.</param>
  223. /// <param name="continueOnException"><see langword="true"/> suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  224. [SecurityCritical]
  225. internal static IEnumerable<ShareInfo> EnumerateSharesCore(string host, ShareType shareType, bool continueOnException)
  226. {
  227. // When host == null, the local computer is used.
  228. // However, the resulting OpenResourceInfo.Host property will be empty.
  229. // So, explicitly state Environment.MachineName to prevent this.
  230. // Furthermore, the UNC prefix: \\ is not required and always removed.
  231. string stripUnc = Utils.IsNullOrWhiteSpace(host)
  232. ? Environment.MachineName
  233. : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty);
  234. var fd = new FunctionData();
  235. bool hasItems = false;
  236. bool yieldAll = shareType == ShareType.All;
  237. // Try SHARE_INFO_503 structure.
  238. foreach (var si in EnumerateNetworkObjectCore(fd, (NativeMethods.SHARE_INFO_503 structure, SafeGlobalMemoryBufferHandle buffer) =>
  239. new ShareInfo(stripUnc, ShareInfoLevel.Info503, structure),
  240. (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle) =>
  241. NativeMethods.NetShareEnum(stripUnc, 503, out buffer, NativeMethods.MaxPreferredLength, out entriesRead, out totalEntries, out resumeHandle), continueOnException).Where(si => yieldAll || si.ShareType == shareType))
  242. {
  243. yield return si;
  244. hasItems = true;
  245. }
  246. // SHARE_INFO_503 is requested, but not supported/possible.
  247. // Try again with SHARE_INFO_2 structure.
  248. if (!hasItems)
  249. foreach (var si in EnumerateNetworkObjectCore(fd, (NativeMethods.SHARE_INFO_2 structure, SafeGlobalMemoryBufferHandle buffer) =>
  250. new ShareInfo(stripUnc, ShareInfoLevel.Info2, structure),
  251. (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle) =>
  252. NativeMethods.NetShareEnum(stripUnc, 2, out buffer, NativeMethods.MaxPreferredLength, out entriesRead, out totalEntries, out resumeHandle), continueOnException).Where(si => yieldAll || si.ShareType == shareType))
  253. {
  254. yield return si;
  255. hasItems = true;
  256. }
  257. // SHARE_INFO_2 is requested, but not supported/possible.
  258. // Try again with SHARE_INFO_1 structure.
  259. if (!hasItems)
  260. foreach (var si in EnumerateNetworkObjectCore(fd, (NativeMethods.SHARE_INFO_1 structure, SafeGlobalMemoryBufferHandle buffer) =>
  261. new ShareInfo(stripUnc, ShareInfoLevel.Info1, structure),
  262. (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle) =>
  263. NativeMethods.NetShareEnum(stripUnc, 1, out buffer, NativeMethods.MaxPreferredLength, out entriesRead, out totalEntries, out resumeHandle), continueOnException).Where(si => yieldAll || si.ShareType == shareType))
  264. {
  265. yield return si;
  266. }
  267. }
  268. #endregion // EnumerateSharesCore
  269. #region GetShareInfoCore
  270. /// <summary>Gets the <see cref="ShareInfo"/> structure of a Server Message Block (SMB) share.</summary>
  271. /// <returns>A <see cref="ShareInfo"/> class, or <see langword="null"/> on failure or when not available, and <paramref name="continueOnException"/> is <see langword="true"/>.</returns>
  272. /// <exception cref="NetworkInformationException"/>
  273. /// <param name="shareLevel">One of the <see cref="ShareInfoLevel"/> options.</param>
  274. /// <param name="host">A string that specifies the DNS or NetBIOS name of the specified <paramref name="host"/>.</param>
  275. /// <param name="share">A string that specifies the name of the Server Message Block (SMB) share.</param>
  276. /// <param name="continueOnException"><see langword="true"/> to suppress any Exception that might be thrown as a result from a failure, such as unavailable resources.</param>
  277. [SecurityCritical]
  278. internal static ShareInfo GetShareInfoCore(ShareInfoLevel shareLevel, string host, string share, bool continueOnException)
  279. {
  280. if (Utils.IsNullOrWhiteSpace(share))
  281. return null;
  282. // When host == null, the local computer is used.
  283. // However, the resulting OpenResourceInfo.Host property will be empty.
  284. // So, explicitly state Environment.MachineName to prevent this.
  285. // Furthermore, the UNC prefix: \\ is not required and always removed.
  286. string stripUnc = Utils.IsNullOrWhiteSpace(host)
  287. ? Environment.MachineName
  288. : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty);
  289. bool fallback = false;
  290. startNetShareGetInfo:
  291. SafeGlobalMemoryBufferHandle safeBuffer;
  292. uint structureLevel = Convert.ToUInt16(shareLevel, CultureInfo.InvariantCulture);
  293. uint lastError = NativeMethods.NetShareGetInfo(stripUnc, share, structureLevel, out safeBuffer);
  294. using (safeBuffer)
  295. {
  296. switch (lastError)
  297. {
  298. case Win32Errors.NERR_Success:
  299. switch (shareLevel)
  300. {
  301. case ShareInfoLevel.Info1005:
  302. return new ShareInfo(stripUnc, shareLevel, safeBuffer.PtrToStructure<NativeMethods.SHARE_INFO_1005>(0))
  303. {
  304. NetFullPath = Path.CombineCore(false, Path.UncPrefix + stripUnc, share)
  305. };
  306. case ShareInfoLevel.Info503:
  307. return new ShareInfo(stripUnc, shareLevel, safeBuffer.PtrToStructure<NativeMethods.SHARE_INFO_503>(0));
  308. case ShareInfoLevel.Info2:
  309. return new ShareInfo(stripUnc, shareLevel, safeBuffer.PtrToStructure<NativeMethods.SHARE_INFO_2>(0));
  310. case ShareInfoLevel.Info1:
  311. return new ShareInfo(stripUnc, shareLevel, safeBuffer.PtrToStructure<NativeMethods.SHARE_INFO_1>(0));
  312. }
  313. break;
  314. // Observed when SHARE_INFO_503 is requested, but not supported/possible.
  315. // Fall back on SHARE_INFO_2 structure and try again.
  316. case Win32Errors.RPC_X_BAD_STUB_DATA:
  317. case Win32Errors.ERROR_ACCESS_DENIED:
  318. if (!fallback && shareLevel != ShareInfoLevel.Info2)
  319. {
  320. shareLevel = ShareInfoLevel.Info2;
  321. fallback = true;
  322. goto startNetShareGetInfo;
  323. }
  324. break;
  325. default:
  326. if (!continueOnException)
  327. throw new NetworkInformationException((int) lastError);
  328. break;
  329. }
  330. return null;
  331. }
  332. }
  333. #endregion // GetShareInfoCore
  334. #endregion // Internal Methods
  335. }
  336. }