/* Copyright (C) 2008-2016 Peter Palotas, Jeffrey Jangli, Alexandr Normuradov * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ using Alphaleonis.Win32.Filesystem; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Net.NetworkInformation; using System.Security; namespace Alphaleonis.Win32.Network { partial class Host { #region EnumerateDfsLinks /// Enumerates the DFS Links from a DFS namespace. /// of DFS namespaces. /// /// /// /// The Universal Naming Convention (UNC) path of a DFS root or link. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "dfs")] [SecurityCritical] public static IEnumerable EnumerateDfsLinks(string dfsName) { if (!Filesystem.NativeMethods.IsAtLeastWindowsVista) throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher); if (Utils.IsNullOrWhiteSpace(dfsName)) throw new ArgumentNullException("dfsName"); var fd = new FunctionData(); return EnumerateNetworkObjectCore(fd, (NativeMethods.DFS_INFO_9 structure, SafeGlobalMemoryBufferHandle buffer) => new DfsInfo(structure), (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle1) => { totalEntries = 0; return NativeMethods.NetDfsEnum(dfsName, 9, prefMaxLen, out buffer, out entriesRead, out resumeHandle1); }, false); } #endregion // EnumerateDfsLinks #region EnumerateDfsRoot /// Enumerates the DFS namespaces from the local host. /// of DFS Root namespaces from the local host. /// /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SecurityCritical] public static IEnumerable EnumerateDfsRoot() { return EnumerateDfsRootCore(null, false); } /// Enumerates the DFS namespaces from a host. /// of DFS Root namespaces from a host. /// /// /// The DNS or NetBIOS name of a host. /// suppress any Exception that might be thrown as a result from a failure, such as unavailable resources. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SecurityCritical] public static IEnumerable EnumerateDfsRoot(string host, bool continueOnException) { return EnumerateDfsRootCore(host, continueOnException); } #endregion // EnumerateDfsRoot #region EnumerateDomainDfsRoot /// Enumerates the DFS namespaces from the domain. /// of DFS Root namespaces from the domain. /// /// [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SecurityCritical] public static IEnumerable EnumerateDomainDfsRoot() { return EnumerateDomainDfsRootCore(null, false); } /// Enumerates the DFS namespaces from a domain. /// of DFS Root namespaces from a domain. /// /// /// A domain name. /// suppress any Exception that might be thrown as a result from a failure, such as unavailable resources. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SecurityCritical] public static IEnumerable EnumerateDomainDfsRoot(string domain, bool continueOnException) { return EnumerateDomainDfsRootCore(domain, continueOnException); } #endregion // EnumerateDomainDfsRoot #region GetDfsClientInfo /// Gets information about a DFS root or link from the cache maintained by the DFS client. /// A instance. /// /// /// The Universal Naming Convention (UNC) path of a DFS root or link. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "dfs")] [SecurityCritical] public static DfsInfo GetDfsClientInfo(string dfsName) { return GetDfsInfoCore(true, dfsName, null, null); } /// Gets information about a DFS root or link from the cache maintained by the DFS client. /// A instance. /// /// /// The Universal Naming Convention (UNC) path of a DFS root or link. /// The name of the DFS root target or link target server. /// The name of the share corresponding to the DFS root target or link target. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "dfs")] [SecurityCritical] public static DfsInfo GetDfsClientInfo(string dfsName, string serverName, string shareName) { return GetDfsInfoCore(true, dfsName, serverName, shareName); } #endregion // GetDfsClientInfo #region GetDfsInfo /// Gets information about a specified DFS root or link in a DFS namespace. /// A instance. /// /// /// The Universal Naming Convention (UNC) path of a DFS root or link. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "dfs")] [SecurityCritical] public static DfsInfo GetDfsInfo(string dfsName) { return GetDfsInfoCore(false, dfsName, null, null); } #endregion // GetDfsInfo #region Internal Methods /// Enumerates the DFS namespaces from a host. /// of DFS Root namespaces from a host. /// /// /// /// The DNS or NetBIOS name of a host. /// suppress any Exception that might be thrown as a result from a failure, such as unavailable resources. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SecurityCritical] private static IEnumerable EnumerateDfsRootCore(string host, bool continueOnException) { if (!Filesystem.NativeMethods.IsAtLeastWindowsVista) throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher); return EnumerateNetworkObjectCore(new FunctionData(), (NativeMethods.DFS_INFO_300 structure, SafeGlobalMemoryBufferHandle buffer) => new DfsInfo { EntryPath = structure.DfsName }, (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle) => { totalEntries = 0; // When host == null, the local computer is used. // However, the resulting Host property will be empty. // So, explicitly state Environment.MachineName to prevent this. // Furthermore, the UNC prefix: \\ is not required and always removed. string stripUnc = Utils.IsNullOrWhiteSpace(host) ? Environment.MachineName : Path.GetRegularPathCore(host, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); return NativeMethods.NetDfsEnum(stripUnc, 300, prefMaxLen, out buffer, out entriesRead, out resumeHandle); }, continueOnException).Select(dfs => dfs.EntryPath); } /// Enumerates the DFS namespaces from a domain. /// of DFS Root namespaces from a domain. /// /// /// /// A domain name. /// suppress any Exception that might be thrown as a result from a failure, such as unavailable resources. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dfs")] [SecurityCritical] private static IEnumerable EnumerateDomainDfsRootCore(string domain, bool continueOnException) { if (!Filesystem.NativeMethods.IsAtLeastWindowsVista) throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher); return EnumerateNetworkObjectCore(new FunctionData(), (NativeMethods.DFS_INFO_200 structure, SafeGlobalMemoryBufferHandle buffer) => new DfsInfo { EntryPath = string.Format(CultureInfo.CurrentCulture, "{0}{1}{2}{3}", Path.UncPrefix, NativeMethods.ComputerDomain, Path.DirectorySeparatorChar, structure.FtDfsName) }, (FunctionData functionData, out SafeGlobalMemoryBufferHandle buffer, int prefMaxLen, out uint entriesRead, out uint totalEntries, out uint resumeHandle) => { totalEntries = 0; // When host == null, the local computer is used. // However, the resulting Host property will be empty. // So, explicitly state Environment.MachineName to prevent this. // Furthermore, the UNC prefix: \\ is not required and always removed. string stripUnc = Utils.IsNullOrWhiteSpace(domain) ? NativeMethods.ComputerDomain : Path.GetRegularPathCore(domain, GetFullPathOptions.CheckInvalidPathChars, false).Replace(Path.UncPrefix, string.Empty); return NativeMethods.NetDfsEnum(stripUnc, 200, prefMaxLen, out buffer, out entriesRead, out resumeHandle); }, continueOnException).Select(dfs => dfs.EntryPath); } /// Retrieves information about a specified DFS root or link in a DFS namespace. /// A instance. /// /// /// /// /// retrieves information about a Distributed File System (DFS) root or link from the cache maintained by the /// DFS client. When retrieves information about a specified Distributed File System (DFS) root or link in a /// DFS namespace. /// /// The Universal Naming Convention (UNC) path of a DFS root or link. /// /// The name of the DFS root target or link target server. If is , this /// parameter is always . /// /// /// The name of the share corresponding to the DFS root target or link target. If is /// , this parameter is always . /// [SecurityCritical] private static DfsInfo GetDfsInfoCore(bool getFromClient, string dfsName, string serverName, string shareName) { if (!Filesystem.NativeMethods.IsAtLeastWindowsVista) throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher); if (Utils.IsNullOrWhiteSpace(dfsName)) throw new ArgumentNullException("dfsName"); serverName = Utils.IsNullOrWhiteSpace(serverName) ? null : serverName; shareName = Utils.IsNullOrWhiteSpace(shareName) ? null : shareName; SafeGlobalMemoryBufferHandle safeBuffer; // Level 9 = DFS_INFO_9 uint lastError = getFromClient ? NativeMethods.NetDfsGetClientInfo(dfsName, serverName, shareName, 9, out safeBuffer) : NativeMethods.NetDfsGetInfo(dfsName, null, null, 9, out safeBuffer); if (lastError == Win32Errors.NERR_Success) return new DfsInfo(safeBuffer.PtrToStructure(0)); throw new NetworkInformationException((int) lastError); } #endregion // Internal Methods } }