/* 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 OpenResourceInfo.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 OpenResourceInfo.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
}
}