Vanara/PInvoke/NetApi32/DsGetDC.cs

1549 lines
90 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Linq;
using Vanara.InteropServices;
using static Vanara.PInvoke.AdvApi32;
using static Vanara.PInvoke.Ws2_32;
namespace Vanara.PInvoke
{
public static partial class NetApi32
{
/// <summary>Enumeration supporting <see cref="DOMAIN_CONTROLLER_INFO.DomainControllerAddressType"/>.</summary>
[PInvokeData("DsGetDC.h", MSDNShortId = "ms675912")]
public enum DomainControllerAddressType
{
/// <summary>The address is a string IP address (for example, "\\157.55.94.74") of the domain controller.</summary>
DS_INET_ADDRESS = 1,
/// <summary>The address is a NetBIOS name, for example, "\\phoenix", of the domain controller.</summary>
DS_NETBIOS_ADDRESS = 2
}
/// <summary>Enumeration supporting <see cref="DOMAIN_CONTROLLER_INFO.Flags"/>.</summary>
[Flags]
[PInvokeData("DsGetDC.h", MSDNShortId = "ms675912")]
public enum DomainControllerType : uint
{
/// <summary>The domain controller is PDC of Domain.</summary>
DS_PDC_FLAG = 0x00000001,
/// <summary>The domain controller is a GC of forest.</summary>
DS_GC_FLAG = 0x00000004,
/// <summary>Server supports an LDAP server.</summary>
DS_LDAP_FLAG = 0x00000008,
/// <summary>The domain controller supports a DS and is a Domain Controller.</summary>
DS_DS_FLAG = 0x00000010,
/// <summary>The domain controller is running KDC service.</summary>
DS_KDC_FLAG = 0x00000020,
/// <summary>The domain controller is running time service.</summary>
DS_TIMESERV_FLAG = 0x00000040,
/// <summary>The domain controller is in closest site to client.</summary>
DS_CLOSEST_FLAG = 0x00000080,
/// <summary>The domain controller has a writable DS.</summary>
DS_WRITABLE_FLAG = 0x00000100,
/// <summary>The domain controller is running time service (and has clock hardware).</summary>
DS_GOOD_TIMESERV_FLAG = 0x00000200,
/// <summary>DomainName is non-domain NC serviced by the LDAP server.</summary>
DS_NDNC_FLAG = 0x00000400,
/// <summary>The domain controller has some secrets.</summary>
DS_SELECT_SECRET_DOMAIN_6_FLAG = 0x00000800,
/// <summary>The domain controller has all secrets.</summary>
DS_FULL_SECRET_DOMAIN_6_FLAG = 0x00001000,
/// <summary>The domain controller is running web service.</summary>
DS_WS_FLAG = 0x00002000,
/// <summary>The domain controller is running Win8 or later.</summary>
DS_DS_8_FLAG = 0x00004000,
/// <summary>The domain controller is running Win8.1 or later.</summary>
DS_DS_9_FLAG = 0x00008000,
/// <summary>The domain controller is running WinThreshold or later.</summary>
DS_DS_10_FLAG = 0x00010000,
/// <summary>Flags returned on ping.</summary>
DS_PING_FLAGS = 0x000FFFFF,
/// <summary>The DomainControllerName is a DNS name.</summary>
DS_DNS_CONTROLLER_FLAG = 0x20000000,
/// <summary>The DomainName is a DNS name.</summary>
DS_DNS_DOMAIN_FLAG = 0x40000000,
/// <summary>The DnsForestName is a DNS name.</summary>
DS_DNS_FOREST_FLAG = 0x80000000,
}
/// <summary>
/// A set of flags that specify more data about the domain trust. This can be zero or a combination of one or more of the following values.
/// </summary>
[PInvokeData("dsgetdc.h", MSDNShortId = "cd260fd1-dc38-4405-95ba-097a23faf668")]
public enum DomainTrustFlag
{
/// <summary>
/// The domain represented by this structure is a member of the same forest as the server specified in the ServerName parameter
/// of the DsEnumerateDomainTrusts function.
/// </summary>
DS_DOMAIN_IN_FOREST = 0x0001,
/// <summary>
/// The domain represented by this structure is directly trusted by the domain that the server specified in the ServerName
/// parameter of the DsEnumerateDomainTrusts function is a member of.
/// </summary>
DS_DOMAIN_DIRECT_OUTBOUND = 0x0002,
/// <summary>
/// The domain represented by this structure is the root of a tree and a member of the same forest as the server specified in the
/// ServerName parameter of the DsEnumerateDomainTrusts function.
/// </summary>
DS_DOMAIN_TREE_ROOT = 0x0004,
/// <summary>
/// The domain represented by this structure is the primary domain of the server specified in the ServerName parameter of the
/// DsEnumerateDomainTrusts function.
/// </summary>
DS_DOMAIN_PRIMARY = 0x0008,
/// <summary>The domain represented by this structure is running in the Windows 2000 native mode.</summary>
DS_DOMAIN_NATIVE_MODE = 0x0010,
/// <summary>
/// The domain represented by this structure directly trusts the domain that the server specified in the ServerName parameter of
/// the DsEnumerateDomainTrusts function is a member of.
/// </summary>
DS_DOMAIN_DIRECT_INBOUND = 0x0020,
}
/// <summary>Flags supporting behavior of <see cref="DsGetDcName(string, string, in Guid, string, DsGetDcNameFlags, out SafeNetApiBuffer)"/>.</summary>
[Flags]
[PInvokeData("DsGetDC.h", MSDNShortId = "ms675983")]
public enum DsGetDcNameFlags : uint
{
/// <summary>
/// Forces cached domain controller data to be ignored. When the DS_FORCE_REDISCOVERY flag is not specified, DsGetDcName may
/// return cached domain controller data. If this flag is specified, DsGetDcName will not use cached information (if any exists)
/// but will instead perform a fresh domain controller discovery.
/// <para>
/// This flag should not be used under normal conditions, as using the cached domain controller information has better
/// performance characteristics and helps to ensure that the same domain controller is used consistently by all applications.
/// This flag should be used only after the application determines that the domain controller returned by DsGetDcName (when
/// called without this flag) is not accessible. In that case, the application should repeat the DsGetDcName call with this flag
/// to ensure that the unuseful cached information (if any) is ignored and a reachable domain controller is discovered.
/// </para>
/// </summary>
DS_FORCE_REDISCOVERY = 0x1,
/// <summary>Requires that the returned domain controller support directory services.</summary>
DS_DIRECTORY_SERVICE_REQUIRED = 0x10,
/// <summary>
/// DsGetDcName attempts to find a domain controller that supports directory service functions. If a domain controller that
/// supports directory services is not available, DsGetDcName returns the name of a non-directory service domain controller.
/// However, DsGetDcName only returns a non-directory service domain controller after the attempt to find a directory service
/// domain controller times out.
/// </summary>
DS_DIRECTORY_SERVICE_PREFERRED = 0x20,
/// <summary>
/// Requires that the returned domain controller be a global catalog server for the forest of domains with this domain as the
/// root. If this flag is set and the DomainName parameter is not NULL, DomainName must specify a forest name. This flag cannot
/// be combined with the DS_PDC_REQUIRED or DS_KDC_REQUIRED flags.
/// </summary>
DS_GC_SERVER_REQUIRED = 0x40,
/// <summary>
/// Requires that the returned domain controller be the primary domain controller for the domain. This flag cannot be combined
/// with the DS_KDC_REQUIRED or DS_GC_SERVER_REQUIRED flags.
/// </summary>
DS_PDC_REQUIRED = 0x80,
/// <summary>
/// If the DS_FORCE_REDISCOVERY flag is not specified, this function uses cached domain controller data. If the cached data is
/// more than 15 minutes old, the cache is refreshed by pinging the domain controller. If this flag is specified, this refresh is
/// avoided even if the cached data is expired. This flag should be used if the DsGetDcName function is called periodically.
/// </summary>
DS_BACKGROUND_ONLY = 0x100,
/// <summary>
/// This parameter indicates that the domain controller must have an IP address. In that case, DsGetDcName will place the
/// Internet protocol address of the domain controller in the DomainControllerAddress member of DomainControllerInfo.
/// </summary>
DS_IP_REQUIRED = 0x200,
/// <summary>
/// Requires that the returned domain controller be currently running the Kerberos Key Distribution Center service. This flag
/// cannot be combined with the DS_PDC_REQUIRED or DS_GC_SERVER_REQUIRED flags.
/// </summary>
DS_KDC_REQUIRED = 0x400,
/// <summary>Requires that the returned domain controller be currently running the Windows Time Service.</summary>
DS_TIMESERV_REQUIRED = 0x800,
/// <summary>Requires that the returned domain controller be writable; that is, host a writable copy of the directory service.</summary>
DS_WRITABLE_REQUIRED = 0x1000,
/// <summary>
/// DsGetDcName attempts to find a domain controller that is a reliable time server. The Windows Time Service can be configured
/// to declare one or more domain controllers as a reliable time server. For more information, see the Windows Time Service
/// documentation. This flag is intended to be used only by the Windows Time Service.
/// </summary>
DS_GOOD_TIMESERV_PREFERRED = 0x2000,
/// <summary>
/// When called from a domain controller, specifies that the returned domain controller name should not be the current computer.
/// If the current computer is not a domain controller, this flag is ignored. This flag can be used to obtain the name of another
/// domain controller in the domain.
/// </summary>
DS_AVOID_SELF = 0x4000,
/// <summary>
/// Specifies that the server returned is an LDAP server. The server returned is not necessarily a domain controller. No other
/// services are implied to be present at the server. The server returned does not necessarily have a writable config container
/// nor a writable schema container. The server returned may not necessarily be used to create or modify security principles.
/// This flag may be used with the DS_GC_SERVER_REQUIRED flag to return an LDAP server that also hosts a global catalog server.
/// The returned global catalog server is not necessarily a domain controller. No other services are implied to be present at the
/// server. If this flag is specified, the DS_PDC_REQUIRED, DS_TIMESERV_REQUIRED, DS_GOOD_TIMESERV_PREFERRED,
/// DS_DIRECTORY_SERVICES_PREFERED, DS_DIRECTORY_SERVICES_REQUIRED, and DS_KDC_REQUIRED flags are ignored.
/// </summary>
DS_ONLY_LDAP_NEEDED = 0x8000,
/// <summary>
/// Specifies that the DomainName parameter is a flat name. This flag cannot be combined with the DS_IS_DNS_NAME flag.
/// </summary>
DS_IS_FLAT_NAME = 0x10000,
/// <summary>
/// Specifies that the DomainName parameter is a DNS name. This flag cannot be combined with the DS_IS_FLAT_NAME flag.
/// <para>
/// Specify either DS_IS_DNS_NAME or DS_IS_FLAT_NAME. If neither flag is specified, DsGetDcName may take longer to find a domain
/// controller because it may have to search for both the DNS-style and flat name.
/// </para>
/// </summary>
DS_IS_DNS_NAME = 0x20000,
/// <summary>
/// When this flag is specified, DsGetDcName attempts to find a domain controller in the same site as the caller. If no such
/// domain controller is found, it will find a domain controller that can provide topology information and call DsBindToISTG to
/// obtain a bind handle, then call DsQuerySitesByCost over UDP to determine the "next closest site," and finally cache the name
/// of the site found. If no domain controller is found in that site, then DsGetDcName falls back on the default method of
/// locating a domain controller.
/// <para>
/// If this flag is used in conjunction with a non-NULL value in the input parameter SiteName, then ERROR_INVALID_FLAGS is thrown.
/// </para>
/// <para>
/// Also, the kind of search employed with DS_TRY_NEXT_CLOSEST_SITE is site-specific, so this flag is ignored if it is used in
/// conjunction with DS_PDC_REQUIRED. Finally, DS_TRY_NEXTCLOSEST_SITE is ignored when used in conjunction with
/// DS_RETURN_FLAT_NAME because that uses NetBIOS to resolve the name, but the domain of the domain controller found won't
/// necessarily match the domain to which the client is joined.
/// </para>
/// <note>Note This flag is Group Policy enabled. If you enable the "Next Closest Site" policy setting, Next Closest Site DC
/// Location will be turned on for the machine across all available but un-configured network adapters. If you disable the policy
/// setting, Next Closest Site DC Location will not be used by default for the machine across all available but un-configured
/// network adapters. However, if a DC Locator call is made using the DS_TRY_NEXTCLOSEST_SITE flag explicitly, DsGetDcName honors
/// the Next Closest Site behavior. If you do not configure this policy setting, Next Closest Site DC Location will be not be
/// used by default for the machine across all available but un-configured network adapters. If the DS_TRY_NEXTCLOSEST_SITE flag
/// is used explicitly, the Next Closest Site behavior will be used.</note>
/// </summary>
DS_TRY_NEXTCLOSEST_SITE = 0x40000,
/// <summary>Requires that the returned domain controller be running Windows Server 2008 or later.</summary>
DS_DIRECTORY_SERVICE_6_REQUIRED = 0x80000,
/// <summary>Requires that the returned domain controller be currently running the Active Directory web service.</summary>
DS_WEB_SERVICE_REQUIRED = 0x100000,
/// <summary>Requires that the returned domain controller be running Windows Server 2012 or later.</summary>
DS_DIRECTORY_SERVICE_8_REQUIRED = 0x200000,
/// <summary>Requires that the returned domain controller be running Windows Server 2012 R2 or later.</summary>
DS_DIRECTORY_SERVICE_9_REQUIRED = 0x400000,
/// <summary>Requires that the returned domain controller be running Windows Server 2016 or later.</summary>
DS_DIRECTORY_SERVICE_10_REQUIRED = 0x800000,
/// <summary>
/// Specifies that the names returned in the DomainControllerName and DomainName members of DomainControllerInfo should be DNS
/// names. If a DNS name is not available, an error is returned. This flag cannot be specified with the DS_RETURN_FLAT_NAME flag.
/// This flag implies the DS_IP_REQUIRED flag.
/// </summary>
DS_RETURN_DNS_NAME = 0x40000000,
/// <summary>
/// Specifies that the names returned in the DomainControllerName and DomainName members of DomainControllerInfo should be flat
/// names. If a flat name is not available, an error is returned. This flag cannot be specified with the DS_RETURN_DNS_NAME flag.
/// </summary>
DS_RETURN_FLAT_NAME = 0x80000000,
}
/// <summary>Flags used by <c>DsGetDcOpen</c>.</summary>
[PInvokeData("dsgetdc.h", MSDNShortId = "2811cc30-f367-4f1a-8f0c-ed0a77dad24c")]
[Flags]
public enum DsGetDcOpenOptions
{
/// <summary>Only site-specific domain controllers are enumerated.</summary>
DS_ONLY_DO_SITE_NAME = 0x01,
/// <summary>
/// The DsGetDcNext function will return the ERROR_FILEMARK_DETECTED value after all of the site-specific domain controllers are
/// retrieved. DsGetDcNext will then enumerate the second group, which contains all domain controllers in the domain, including
/// the site-specific domain controllers contained in the first group.
/// </summary>
DS_NOTIFY_AFTER_SITE_RECORDS = 0x02,
}
/// <summary>Flags used by <c>DsGetForestTrustInformationW</c>.</summary>
[PInvokeData("dsgetdc.h", MSDNShortId = "c94fdc5b-920b-4807-9cbf-3172ec1c7386")]
[Flags]
public enum DsGetForestTrustInformationFlags
{
/// <summary>
/// If this flag is set, DsGetForestTrustInformationW will update the forest trust data of the trusted domain identified by the
/// TrustedDomainNameparameter. In this case, the TrustedDomainName parameter cannot be NULL. The caller must have access to
/// modify the trust data or ERROR_ACCESS_DENIED is returned.
/// <para>This flag is only valid if ServerName specifies the primary domain controller of the domain.</para>
/// </summary>
DS_GFTI_UPDATE_TDO = 1
}
/// <summary>The <c>DsAddressToSiteNames</c> function obtains the site names corresponding to the specified addresses.</summary>
/// <param name="ComputerName">
/// Pointer to a null-terminated string that specifies the name of the remote server to process this function. This parameter must be
/// the name of a domain controller. A non-domain controller can call this function by calling DsGetDcName to find the domain controller.
/// </param>
/// <param name="EntryCount">Contains the number of elements in the SocketAddresses array.</param>
/// <param name="SocketAddresses">
/// Contains an array of SOCKET_ADDRESS structures that contain the addresses to convert. Each address in this array must be of the
/// type <c>AF_INET</c>. EntryCount contains the number of elements in this array.
/// </param>
/// <param name="SiteNames">
/// Receives an array of null-terminated string pointers that contain the site names for the addresses. Each element in this array
/// corresponds to the same element in the SocketAddresses array. An element is <c>NULL</c> if the corresponding address does not map
/// to any known site or if the address entry is not of the proper form. The caller must free this array when it is no longer
/// required by calling NetApiBufferFree.
/// </param>
/// <returns>
/// Returns <c>NO_ERROR</c> if successful or a Win32 or RPC error otherwise. The following list lists possible error codes.
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsaddresstositenamesa DSGETDCAPI DWORD
// DsAddressToSiteNamesA( IN LPCSTR ComputerName, IN DWORD EntryCount, IN PSOCKET_ADDRESS SocketAddresses, OUT LPSTR **SiteNames );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "4d70dbee-be33-4d2a-a200-3696443fa853")]
public static extern Win32Error DsAddressToSiteNames(string ComputerName, uint EntryCount, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] SOCKET_ADDRESS[] SocketAddresses, out SafeNetApiBuffer SiteNames);
/// <summary>The <c>DsAddressToSiteNamesEx</c> function obtains the site and subnet names corresponding to the addresses specified.</summary>
/// <param name="ComputerName">
/// Pointer to a null-terminated string that specifies the name of the remote server to process this function. This parameter must be
/// the name of a domain controller. A non-domain controller can call this function by calling DsGetDcName to find the domain controller.
/// </param>
/// <param name="EntryCount">Contains the number of elements in the SocketAddresses array.</param>
/// <param name="SocketAddresses">
/// Contains an array of SOCKET_ADDRESS structures that contain the addresses to convert. Each address in this array must be of the
/// type <c>AF_INET</c>. EntryCount contains the number of elements in this array.
/// </param>
/// <param name="SiteNames">
/// Receives an array of null-terminated string pointers that contain the site names for the addresses. Each element in this array
/// corresponds to the same element in the SocketAddresses array. An element is <c>NULL</c> if the corresponding address does not map
/// to any known site or if the address entry is not of the proper form. The caller must free this array when it is no longer
/// required by calling NetApiBufferFree.
/// </param>
/// <param name="SubnetNames">
/// Receives an array of null-terminated string pointers that contain the subnet names used to perform the address to site name
/// mappings. Each element in this array corresponds to the same element in the SocketAddresses array. An element is <c>NULL</c> if
/// the corresponding address to site name mapping was not determined or if no subnet was used to perform the corresponding address
/// to site mapping. The latter will be the case when there is exactly one site in the enterprise with no subnet objects mapped to
/// it. The caller must free this array when it is no longer required by calling NetApiBufferFree.
/// </param>
/// <returns>Returns <c>NO_ERROR</c> if successful or a Win32 or RPC error otherwise. The following are possible error codes.</returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsaddresstositenamesexw
// DSGETDCAPI DWORD DsAddressToSiteNamesExW( IN LPCWSTR ComputerName, IN DWORD EntryCount, IN PSOCKET_ADDRESS SocketAddresses, OUT LPWSTR **SiteNames, OUT LPWSTR **SubnetNames );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "60ac6195-6e43-46da-a1e6-74ec989cd0c4")]
public static extern Win32Error DsAddressToSiteNamesEx(string ComputerName, uint EntryCount, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] SOCKET_ADDRESS[] SocketAddresses, out SafeNetApiBuffer SiteNames, out SafeNetApiBuffer SubnetNames);
/// <summary>
/// <para>
/// The <c>DsDeregisterDnsHostRecords</c> function deletes DNS entries, except for type A records registered by a domain controller.
/// Only an administrator, account operator, or server operator may call this function.
/// </para>
/// </summary>
/// <param name="ServerName">
/// <para>
/// The null-terminated string that specifies the name of the remote domain controller. Can be set to <c>NULL</c> if the calling
/// application is running on the domain controller being updated.
/// </para>
/// </param>
/// <param name="DnsDomainName">
/// <para>
/// The null-terminated string that specifies the DNS domain name of the domain occupied by the domain controller. It is unnecessary
/// for this to be a domain hosted by this domain controller. If <c>NULL</c>, the DnsHostName with the leftmost label removed is specified.
/// </para>
/// </param>
/// <param name="DomainGuid">
/// <para>Pointer to the Domain GUID of the domain. If <c>NULL</c>, GUID specific names are not removed.</para>
/// </param>
/// <param name="DsaGuid">
/// <para>
/// Pointer to the GUID of the <c>NTDS-DSA</c> object to be deleted. If <c>NULL</c>, <c>NTDS-DSA</c> specific names are not removed.
/// </para>
/// </param>
/// <param name="DnsHostName">
/// <para>
/// Pointer to the null-terminated string that specifies the DNS host name of the domain controller whose DNS records are being deleted.
/// </para>
/// </param>
/// <returns>
/// <para>This function returns DSGETDCAPI DWORD.</para>
/// </returns>
/// <remarks>
/// <para>
/// This function deregisters SRV and CNAME records only. It leaves type A records intact. Deletion of site specific records, for
/// example, _ldap.tcp.&lt;SiteName&gt;._sites.dc._msdcs.&lt;DnsDomainName&gt;, is attempted for every site (&lt;SiteName&gt; in this
/// example) in the enterprise of the domain controller on which the function is executed. Therefore, this function call could create
/// a time-consuming run and may generate significant network traffic for enterprises with many sites.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsderegisterdnshostrecordsa DSGETDCAPI DWORD
// DsDeregisterDnsHostRecordsA( LPSTR ServerName, LPSTR DnsDomainName, GUID *DomainGuid, GUID *DsaGuid, LPSTR DnsHostName );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "18ab6455-dab2-42d9-b68e-a8f0ad2d8091")]
public static extern Win32Error DsDeregisterDnsHostRecords([Optional] string ServerName, string DnsDomainName, in Guid DomainGuid, in Guid DsaGuid, string DnsHostName);
/// <summary>
/// <para>
/// The <c>DsDeregisterDnsHostRecords</c> function deletes DNS entries, except for type A records registered by a domain controller.
/// Only an administrator, account operator, or server operator may call this function.
/// </para>
/// </summary>
/// <param name="ServerName">
/// <para>
/// The null-terminated string that specifies the name of the remote domain controller. Can be set to <c>NULL</c> if the calling
/// application is running on the domain controller being updated.
/// </para>
/// </param>
/// <param name="DnsDomainName">
/// <para>
/// The null-terminated string that specifies the DNS domain name of the domain occupied by the domain controller. It is unnecessary
/// for this to be a domain hosted by this domain controller. If <c>NULL</c>, the DnsHostName with the leftmost label removed is specified.
/// </para>
/// </param>
/// <param name="DomainGuid">
/// <para>Pointer to the Domain GUID of the domain. If <c>NULL</c>, GUID specific names are not removed.</para>
/// </param>
/// <param name="DsaGuid">
/// <para>
/// Pointer to the GUID of the <c>NTDS-DSA</c> object to be deleted. If <c>NULL</c>, <c>NTDS-DSA</c> specific names are not removed.
/// </para>
/// </param>
/// <param name="DnsHostName">
/// <para>
/// Pointer to the null-terminated string that specifies the DNS host name of the domain controller whose DNS records are being deleted.
/// </para>
/// </param>
/// <returns>
/// <para>This function returns DSGETDCAPI DWORD.</para>
/// </returns>
/// <remarks>
/// <para>
/// This function deregisters SRV and CNAME records only. It leaves type A records intact. Deletion of site specific records, for
/// example, _ldap.tcp.&lt;SiteName&gt;._sites.dc._msdcs.&lt;DnsDomainName&gt;, is attempted for every site (&lt;SiteName&gt; in this
/// example) in the enterprise of the domain controller on which the function is executed. Therefore, this function call could create
/// a time-consuming run and may generate significant network traffic for enterprises with many sites.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsderegisterdnshostrecordsa DSGETDCAPI DWORD
// DsDeregisterDnsHostRecordsA( LPSTR ServerName, LPSTR DnsDomainName, GUID *DomainGuid, GUID *DsaGuid, LPSTR DnsHostName );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "18ab6455-dab2-42d9-b68e-a8f0ad2d8091")]
public static extern Win32Error DsDeregisterDnsHostRecords([Optional] string ServerName, string DnsDomainName, IntPtr DomainGuid, IntPtr DsaGuid, string DnsHostName);
/// <summary>The <c>DsEnumerateDomainTrusts</c> function obtains domain trust data for a specified domain.</summary>
/// <param name="ServerName"><para>
/// Pointer to a null-terminated string that specifies the name of a computer in the domain to obtain the trust information for. If
/// this parameter is <c>NULL</c>, the name of the local computer is used. The caller must be an authenticated user in this domain.
/// </para>
/// <para>
/// If this computer is a domain controller, this function returns the trust data immediately. If this computer is not a domain
/// controller, this function obtains the trust data from cached data if the cached data is not expired. If the cached data is
/// expired, this function obtains the trust data from a domain controller in the domain that this computer is a member of and
/// updates the cache. The cached data automatically expires after five minutes.
/// </para></param>
/// <param name="Flags"><para>
/// Contains a set of flags that determines which domain trusts to enumerate. This can be zero or a combination of one or more of the
/// following values.
/// </para>
/// <para>DS_DOMAIN_DIRECT_INBOUND</para>
/// <para>Enumerate domains that directly trust the domain which has ServerName as a member.</para>
/// <para>DS_DOMAIN_DIRECT_OUTBOUND</para>
/// <para>Enumerate domains directly trusted by the domain which has ServerName as a member.</para>
/// <para>DS_DOMAIN_IN_FOREST</para>
/// <para>Enumerate domains that are a member of the same forest which has ServerName as a member.</para>
/// <para>DS_DOMAIN_NATIVE_MODE</para>
/// <para>Enumerate domains where the primary domain is running in Windows 2000 native mode.</para>
/// <para>DS_DOMAIN_PRIMARY</para>
/// <para>Enumerate domains that are the primary domain of the domain which has ServerName as a member.</para>
/// <para>DS_DOMAIN_TREE_ROOT</para>
/// <para>Enumerate domains that are at the root of the forest which has ServerName as a member.</para></param>
/// <param name="Domains">Pointer to a <c>PDS_DOMAIN_TRUSTS</c> value that receives an array of DS_DOMAIN_TRUSTS structures. Each structure in this array
/// contains trust data about a domain. The caller must free this memory when it is no longer required by calling NetApiBufferFree.</param>
/// <param name="DomainCount">Pointer to a <c>ULONG</c> value that receives the number of elements returned in the Domains array.</param>
/// <returns>
/// Returns <c>ERROR_SUCCESS</c> if successful or a Win32 error code otherwise. Possible error codes include those listed in the
/// following list.
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsenumeratedomaintrustsa DSGETDCAPI DWORD
// DsEnumerateDomainTrustsA( LPSTR ServerName, ULONG Flags, PDS_DOMAIN_TRUSTSA *Domains, PULONG DomainCount );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "6c3b788f-ee53-4637-acdb-04316e8464fe")]
public static extern Win32Error DsEnumerateDomainTrusts([Optional] string ServerName, [Optional] DomainTrustFlag Flags, out SafeNetApiBuffer Domains, out uint DomainCount);
/// <summary>
/// <para>The <c>DsGetDcClose</c> function closes a domain controller enumeration operation.</para>
/// </summary>
/// <param name="GetDcContextHandle">
/// <para>Contains the domain controller enumeration context handle provided by the DsGetDcOpen function.</para>
/// </param>
/// <returns>
/// <para>This function does not return a value.</para>
/// </returns>
/// <remarks>
/// <para>When this function is called, GetDcContextHandle is invalid and cannot be used.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsgetdcclosew DSGETDCAPI VOID DsGetDcCloseW( IN HANDLE
// GetDcContextHandle );
[DllImport(Lib.NetApi32, SetLastError = false, EntryPoint = "DsGetDcCloseW")]
[PInvokeData("dsgetdc.h", MSDNShortId = "d193e4cd-ad66-4d93-b912-348f17e93a6f")]
public static extern void DsGetDcClose(HANDLE GetDcContextHandle);
/// <summary>
/// The <c>DsGetDcName</c> function returns the name of a domain controller in a specified domain. This function accepts additional
/// domain controller selection criteria to indicate preference for a domain controller with particular characteristics.
/// </summary>
/// <param name="ComputerName">
/// Pointer to a null-terminated string that specifies the name of the server to process this function. Typically, this parameter is
/// <c>NULL</c>, which indicates that the local computer is used.
/// </param>
/// <param name="DomainName">
/// <para>
/// Pointer to a null-terminated string that specifies the name of the domain or application partition to query. This name can either
/// be a DNS style name, for example, fabrikam.com, or a flat-style name, for example, Fabrikam. If a DNS style name is specified,
/// the name may be specified with or without a trailing period.
/// </para>
/// <para>
/// If the Flags parameter contains the <c>DS_GC_SERVER_REQUIRED</c> flag, DomainName must be the name of the forest. In this case,
/// <c>DsGetDcName</c> fails if DomainName specifies a name that is not the forest root.
/// </para>
/// <para>
/// If the Flags parameter contains the <c>DS_GC_SERVER_REQUIRED</c> flag and DomainName is <c>NULL</c>, <c>DsGetDcName</c> attempts
/// to find a global catalog in the forest of the computer identified by ComputerName, which is the local computer if ComputerName is <c>NULL</c>.
/// </para>
/// <para>
/// If DomainName is <c>NULL</c> and the Flags parameter does not contain the <c>DS_GC_SERVER_REQUIRED</c> flag, ComputerName is set
/// to the default domain name of the primary domain of the computer identified by ComputerName.
/// </para>
/// </param>
/// <param name="DomainGuid">
/// Pointer to a GUID structure that specifies the <c>GUID</c> of the domain queried. If DomainGuid is not <c>NULL</c> and the domain
/// specified by DomainName or ComputerName cannot be found, <c>DsGetDcName</c> attempts to locate a domain controller in the domain
/// having the GUID specified by DomainGuid.
/// </param>
/// <param name="SiteName">
/// Pointer to a null-terminated string that specifies the name of the site where the returned domain controller should physically
/// exist. If this parameter is <c>NULL</c>, <c>DsGetDcName</c> attempts to return a domain controller in the site closest to the
/// site of the computer specified by ComputerName. This parameter should be <c>NULL</c>, by default.
/// </param>
/// <param name="Flags">
/// <para>
/// Contains a set of flags that provide additional data used to process the request. This parameter can be a combination of the
/// following values.
/// </para>
/// <para>DS_AVOID_SELF</para>
/// <para>
/// When called from a domain controller, specifies that the returned domain controller name should not be the current computer. If
/// the current computer is not a domain controller, this flag is ignored. This flag can be used to obtain the name of another domain
/// controller in the domain.
/// </para>
/// <para>DS_BACKGROUND_ONLY</para>
/// <para>
/// If the <c>DS_FORCE_REDISCOVERY</c> flag is not specified, this function uses cached domain controller data. If the cached data is
/// more than 15 minutes old, the cache is refreshed by pinging the domain controller. If this flag is specified, this refresh is
/// avoided even if the cached data is expired. This flag should be used if the <c>DsGetDcName</c> function is called periodically.
/// </para>
/// <para>DS_DIRECTORY_SERVICE_PREFERRED</para>
/// <para>
/// <c>DsGetDcName</c> attempts to find a domain controller that supports directory service functions. If a domain controller that
/// supports directory services is not available, <c>DsGetDcName</c> returns the name of a non-directory service domain controller.
/// However, <c>DsGetDcName</c> only returns a non-directory service domain controller after the attempt to find a directory service
/// domain controller times out.
/// </para>
/// <para>DS_DIRECTORY_SERVICE_REQUIRED</para>
/// <para>Requires that the returned domain controller support directory services.</para>
/// <para>DS_DIRECTORY_SERVICE_6_REQUIRED</para>
/// <para>Requires that the returned domain controller be running Windows Server 2008 or later.</para>
/// <para>DS_DIRECTORY_SERVICE_8_REQUIRED</para>
/// <para>Requires that the returned domain controller be running Windows Server 2012 or later.</para>
/// <para>DS_FORCE_REDISCOVERY</para>
/// <para>
/// Forces cached domain controller data to be ignored. When the <c>DS_FORCE_REDISCOVERY</c> flag is not specified,
/// <c>DsGetDcName</c> may return cached domain controller data. If this flag is specified, <c>DsGetDcName</c> will not use cached
/// information (if any exists) but will instead perform a fresh domain controller discovery.
/// </para>
/// <para>
/// This flag should not be used under normal conditions, as using the cached domain controller information has better performance
/// characteristics and helps to ensure that the same domain controller is used consistently by all applications. This flag should be
/// used only after the application determines that the domain controller returned by <c>DsGetDcName</c> (when called without this
/// flag) is not accessible. In that case, the application should repeat the <c>DsGetDcName</c> call with this flag to ensure that
/// the unuseful cached information (if any) is ignored and a reachable domain controller is discovered.
/// </para>
/// <para>DS_GC_SERVER_REQUIRED</para>
/// <para>
/// Requires that the returned domain controller be a global catalog server for the forest of domains with this domain as the root.
/// If this flag is set and the DomainName parameter is not <c>NULL</c>, DomainName must specify a forest name. This flag cannot be
/// combined with the <c>DS_PDC_REQUIRED</c> or <c>DS_KDC_REQUIRED</c> flags.
/// </para>
/// <para>DS_GOOD_TIMESERV_PREFERRED</para>
/// <para>
/// <c>DsGetDcName</c> attempts to find a domain controller that is a reliable time server. The Windows Time Service can be
/// configured to declare one or more domain controllers as a reliable time server. For more information, see the Windows Time
/// Service documentation. This flag is intended to be used only by the Windows Time Service.
/// </para>
/// <para>DS_IP_REQUIRED</para>
/// <para>
/// This parameter indicates that the domain controller must have an IP address. In that case, <c>DsGetDcName</c> will place the
/// Internet protocol address of the domain controller in the <c>DomainControllerAddress</c> member of DomainControllerInfo.
/// </para>
/// <para>DS_IS_DNS_NAME</para>
/// <para>Specifies that the DomainName parameter is a DNS name. This flag cannot be combined with the <c>DS_IS_FLAT_NAME</c> flag.</para>
/// <para>
/// Specify either <c>DS_IS_DNS_NAME</c> or <c>DS_IS_FLAT_NAME</c>. If neither flag is specified, <c>DsGetDcName</c> may take longer
/// to find a domain controller because it may have to search for both the DNS-style and flat name.
/// </para>
/// <para>DS_IS_FLAT_NAME</para>
/// <para>Specifies that the DomainName parameter is a flat name. This flag cannot be combined with the <c>DS_IS_DNS_NAME</c> flag.</para>
/// <para>DS_KDC_REQUIRED</para>
/// <para>
/// Requires that the returned domain controller be currently running the Kerberos Key Distribution Center service. This flag cannot
/// be combined with the <c>DS_PDC_REQUIRED</c> or <c>DS_GC_SERVER_REQUIRED</c> flags.
/// </para>
/// <para>DS_ONLY_LDAP_NEEDED</para>
/// <para>
/// Specifies that the server returned is an LDAP server. The server returned is not necessarily a domain controller. No other
/// services are implied to be present at the server. The server returned does not necessarily have a writable <c>config</c>
/// container nor a writable <c>schema</c> container. The server returned may not necessarily be used to create or modify security
/// principles. This flag may be used with the <c>DS_GC_SERVER_REQUIRED</c> flag to return an LDAP server that also hosts a global
/// catalog server. The returned global catalog server is not necessarily a domain controller. No other services are implied to be
/// present at the server. If this flag is specified, the <c>DS_PDC_REQUIRED</c>, <c>DS_TIMESERV_REQUIRED</c>,
/// <c>DS_GOOD_TIMESERV_PREFERRED</c>, <c>DS_DIRECTORY_SERVICES_PREFERED</c>, <c>DS_DIRECTORY_SERVICES_REQUIRED</c>, and
/// <c>DS_KDC_REQUIRED</c> flags are ignored.
/// </para>
/// <para>DS_PDC_REQUIRED</para>
/// <para>
/// Requires that the returned domain controller be the primary domain controller for the domain. This flag cannot be combined with
/// the <c>DS_KDC_REQUIRED</c> or <c>DS_GC_SERVER_REQUIRED</c> flags.
/// </para>
/// <para>DS_RETURN_DNS_NAME</para>
/// <para>
/// Specifies that the names returned in the <c>DomainControllerName</c> and <c>DomainName</c> members of DomainControllerInfo should
/// be DNS names. If a DNS name is not available, an error is returned. This flag cannot be specified with the
/// <c>DS_RETURN_FLAT_NAME</c> flag. This flag implies the <c>DS_IP_REQUIRED</c> flag.
/// </para>
/// <para>DS_RETURN_FLAT_NAME</para>
/// <para>
/// Specifies that the names returned in the <c>DomainControllerName</c> and <c>DomainName</c> members of DomainControllerInfo should
/// be flat names. If a flat name is not available, an error is returned. This flag cannot be specified with the
/// <c>DS_RETURN_DNS_NAME</c> flag.
/// </para>
/// <para>DS_TIMESERV_REQUIRED</para>
/// <para>Requires that the returned domain controller be currently running the Windows Time Service.</para>
/// <para>DS_TRY_NEXTCLOSEST_SITE</para>
/// <para>
/// When this flag is specified, <c>DsGetDcName</c> attempts to find a domain controller in the same site as the caller. If no such
/// domain controller is found, it will find a domain controller that can provide topology information and call DsBindToISTG to
/// obtain a bind handle, then call DsQuerySitesByCost over UDP to determine the "next closest site," and finally cache the name of
/// the site found. If no domain controller is found in that site, then <c>DsGetDcName</c> falls back on the default method of
/// locating a domain controller.
/// </para>
/// <para>
/// If this flag is used in conjunction with a non-NULL value in the input parameter SiteName, then <c>ERROR_INVALID_FLAGS</c> is thrown.
/// </para>
/// <para>
/// Also, the kind of search employed with <c>DS_TRY_NEXT_CLOSEST_SITE</c> is site-specific, so this flag is ignored if it is used in
/// conjunction with <c>DS_PDC_REQUIRED</c>. Finally, <c>DS_TRY_NEXTCLOSEST_SITE</c> is ignored when used in conjunction with
/// <c>DS_RETURN_FLAT_NAME</c> because that uses NetBIOS to resolve the name, but the domain of the domain controller found won't
/// necessarily match the domain to which the client is joined.
/// </para>
/// <para>
/// <c>Note</c> This flag is Group Policy enabled. If you enable the "Next Closest Site" policy setting, Next Closest Site DC
/// Location will be turned on for the machine across all available but un-configured network adapters. If you disable the policy
/// setting, Next Closest Site DC Location will not be used by default for the machine across all available but un-configured network
/// adapters. However, if a DC Locator call is made using the <c>DS_TRY_NEXTCLOSEST_SITE</c> flag explicitly, <c>DsGetDcName</c>
/// honors the Next Closest Site behavior. If you do not configure this policy setting, Next Closest Site DC Location will be not be
/// used by default for the machine across all available but un-configured network adapters. If the <c>DS_TRY_NEXTCLOSEST_SITE</c>
/// flag is used explicitly, the Next Closest Site behavior will be used.
/// </para>
/// <para>DS_WRITABLE_REQUIRED</para>
/// <para>Requires that the returned domain controller be writable; that is, host a writable copy of the directory service.</para>
/// <para>DS_WEB_SERVICE_REQUIRED</para>
/// <para>Requires that the returned domain controller be currently running the Active Directory web service.</para>
/// </param>
/// <param name="DomainControllerInfo">
/// Pointer to a <c>PDOMAIN_CONTROLLER_INFO</c> value that receives a pointer to a DOMAIN_CONTROLLER_INFO structure that contains
/// data about the domain controller selected. This structure is allocated by <c>DsGetDcName</c>. The caller must free the structure
/// using the NetApiBufferFree function when it is no longer required.
/// </param>
/// <returns>
/// <para>If the function returns domain controller data, the return value is <c>ERROR_SUCCESS</c>.</para>
/// <para>If the function fails, the return value can be one of the following error codes.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>DsGetDcName</c> function is sent to the Netlogon service on the remote computer specified by ComputerName. If ComputerName
/// is <c>NULL</c>, the function is processed on the local computer.
/// </para>
/// <para>
/// <c>DsGetDcName</c> does not verify that the domain controller name returned is the name of an actual domain controller or global
/// catalog. If mutual authentication is required, the caller must perform the authentication.
/// </para>
/// <para>
/// <c>DsGetDcName</c> does not require any particular access to the specified domain. By default, this function does not ensure that
/// the returned domain controller is currently available. Instead, the caller should attempt to use the returned domain controller.
/// If the domain controller is not available, the caller should call the <c>DsGetDcName</c> function again, specifying the
/// <c>DS_FORCE_REDISCOVERY</c> flag.
/// </para>
/// <para>Response Time</para>
/// <para>When using <c>DsGetDcName</c> be aware of the following timing details:</para>
/// <list type="bullet">
/// <item>
/// <term>
/// <c>DsGetDcName</c> makes network calls and can take from a few seconds up to one minute, depending on network traffic, topology,
/// DC load, and so on.
/// </term>
/// </item>
/// <item>
/// <term>It is NOT recommended to call <c>DsGetDcName</c> from a UI or other timing critical thread.</term>
/// </item>
/// <item>
/// <term>
/// The DC Locator does use optimized logic to provide the DC information as quickly as possible. It also uses cached information at
/// the site to contact the closest DC.
/// </term>
/// </item>
/// </list>
/// <para>Notes on Domain Controller Stickiness</para>
/// <para>
/// In Active Directory Domain Services, the domain controller locator function is designed so that once a client finds a preferred
/// domain controller, the client will not look for another unless that domain controller stops responding or the client is
/// restarted. This is referred to as "Domain Controller Stickiness." Because workstations typically operate for months without a
/// problem or restart, one unintended consequence of this behavior is that if a particular domain controller goes down for
/// maintenance, all of the clients that were connected to it shift their connections to another domain controller. But when the
/// domain controller comes back up, no clients ever reconnect to it because the clients do not restart very often. This can cause
/// load-balancing problems.
/// </para>
/// <para>
/// Previously, the most common solution to this problem was to deploy a script on each client machine that periodically called
/// <c>DsGetDcName</c> using the flag. This was a somewhat cumbersome solution, so Windows Server 2008 and Windows Vista introduced a
/// new mechanism that caused issues with domain controller stickiness.
/// </para>
/// <para>
/// Whenever <c>DsGetDcName</c> retrieves a domain controller name from its cache, it checks to see if this cached entry is expired,
/// and if so, discards that domain controller name and tries to rediscover a domain controller name. The life span of a cached entry
/// is controlled by the value in the following registry keys
/// </para>
/// <para><c>HKEY_LOCAL_MACHINE</c>&lt;b&gt;SYSTEM&lt;b&gt;CurrentControlSet&lt;b&gt;Services&lt;b&gt;Netlogon&lt;b&gt;Parameters&lt;b&gt;ForceRediscoveryInterval</para>
/// <para>and</para>
/// <para><c>HKEY_LOCAL_MACHINE</c>&lt;b&gt;Software&lt;b&gt;Policies&lt;b&gt;Microsoft&lt;b&gt;Netlogon&lt;b&gt;Parameters&lt;b&gt;ForceRediscoveryInterval</para>
/// <para>
/// The values in these registry keys are of type <c>REG_DWORD</c>. They specify the length in seconds before <c>DsGetDcName</c>
/// should try to rediscover the domain controller name. The default value is 43200 seconds (12 hours). If the value of the
/// <c>ForceRediscoveryInterval</c> registry entry is set to 0, the client always performs rediscovery. If the value is set to
/// 4294967295, the cache never expires, and the cached domain controller continues to be used. We recommend that you do not set the
/// <c>ForceRediscoveryInterval</c> registry entry to a value that is less than 3600 seconds (60 minutes).
/// </para>
/// <para>
/// <c>Note</c> The registry settings of <c>ForceRediscoveryInterval</c> are group policy enabled. If you disable the policy setting,
/// Force Rediscovery will used by default for the machine at every 12 hour interval. If you do not configure this policy setting,
/// Force Rediscovery will used by default for the machine at every 12 hour interval, unless the local machine setting in the
/// registry is a different value.
/// </para>
/// <para>
/// Note that if the <c>DS_BACKGROUND_ONLY</c> flag is specified, <c>DsGetDcName</c> will never try to rediscover the domain
/// controller name, since the point of that flag is to force <c>DsGetDcName</c> to use the cached domain controller name even if it
/// is expired.
/// </para>
/// <para>ETW Tracing in DsGetDcName</para>
/// <para>To turn on ETW Tracing for <c>DsGetDcName</c>, create the following registry key:</para>
/// <para><c>HKEY_LOCAL_MACHINE</c>&lt;b&gt;System&lt;b&gt;CurrentControlSet&lt;b&gt;Services&lt;b&gt;DCLocator&lt;b&gt;Tracing</para>
/// <para>The key will have a structure as follows:</para>
/// <para>
/// ProcessName must be the full name including extension of the process that you want to get trace information for. PID is only
/// required when multiple processes with the same name exist. If it is defined, then only the process with that PID will be enabled
/// for tracing. It is not possible to trace only 2 out of 3 (or more) processes with the same name. You can enable one instance or
/// all instances (when multiple instances with the same process name exist and PID is not specified, all instances will be enabled
/// for tracing).
/// </para>
/// <para>
/// For example, this would trace all instances of App1.exe and App2.exe, but only the instance of App3.exe that has a PID of 999:
/// </para>
/// <para>Run the following command to start the tracing session:</para>
/// <para><c>tracelog.exe -start &lt;sessionname&gt; -guid #cfaa5446-c6c4-4f5c-866f-31c9b55b962d -f &lt;filename&gt; -flag &lt;traceFlags&gt;</c></para>
/// <para>
/// sessionname is the name given for the trace session. The guid for the DCLocator tracing provider is
/// "cfaa5446-c6c4-4f5c-866f-31c9b55b962d". filename is the name of the log file to which the events are written. traceFlags is one
/// or more of the following flags which signify which areas to trace:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Hex Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>DCLOCATOR_MISC</term>
/// <term>0x00000002</term>
/// <term>Miscellaneous debugging</term>
/// </item>
/// <item>
/// <term>DCLOCATOR_MAILSLOT</term>
/// <term>0x00000010</term>
/// <term>Mailslot messages</term>
/// </item>
/// <item>
/// <term>DCLOCATOR_SITE</term>
/// <term>0x00000020</term>
/// <term>Sites</term>
/// </item>
/// <item>
/// <term>DCLOCATOR_CRITICAL</term>
/// <term>0x00000100</term>
/// <term>Important errors</term>
/// </item>
/// <item>
/// <term>DCLOCATOR_SESSION_SETUP</term>
/// <term>0x00000200</term>
/// <term>Trusted Domain Maintenance</term>
/// </item>
/// <item>
/// <term>DCLOCATOR_DNS</term>
/// <term>0x00004000</term>
/// <term>Name Registration</term>
/// </item>
/// <item>
/// <term>DCLOCATOR_DNS_MORE</term>
/// <term>0x00020000</term>
/// <term>Verbose Name Registration</term>
/// </item>
/// <item>
/// <term>DCLOCATOR_MAILBOX_TEXT</term>
/// <term>0x02000000</term>
/// <term>Verbose Mailbox Messages</term>
/// </item>
/// <item>
/// <term>DCLOCATOR_SITE_MORE</term>
/// <term>0x08000000</term>
/// <term>Verbose sites</term>
/// </item>
/// </list>
/// <para>Run the following command to stop the trace session:</para>
/// <para><c>tracelog.exe -stop &lt;sessionname&gt;</c></para>
/// <para>sessionname is the same name as the name you used when starting the session.</para>
/// <para>
/// <c>Note</c> The registry key for the process being traced must be present in the registry at the time the trace session is
/// started. When the session starts, the process will verify whether or not it should be generating trace messages (based on the
/// presence or absence of a registry key for that process name and optional PID). The process checks the registry only at the start
/// of the session. Any changes in the registry occurring after that will not have any effect on tracing.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsgetdcnamea
// DSGETDCAPI DWORD DsGetDcNameA( IN LPCSTR ComputerName, IN LPCSTR DomainName, IN GUID *DomainGuid, IN LPCSTR SiteName, IN ULONG Flags, OUT PDOMAIN_CONTROLLER_INFOA *DomainControllerInfo );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "da8b2983-5e45-40b0-b552-c9b3a1d8ae94")]
public static extern Win32Error DsGetDcName([Optional] string ComputerName, [Optional] string DomainName, in Guid DomainGuid, [Optional] string SiteName, DsGetDcNameFlags Flags, out SafeNetApiBuffer DomainControllerInfo);
/// <summary>
/// The DsGetDcName function returns the name of a domain controller in a specified domain. This function accepts additional domain
/// controller selection criteria to indicate preference for a domain controller with particular characteristics.
/// </summary>
/// <param name="ComputerName">
/// Pointer to a null-terminated string that specifies the name of the server to process this function. Typically, this parameter is
/// NULL, which indicates that the local computer is used.
/// </param>
/// <param name="DomainName">
/// Pointer to a null-terminated string that specifies the name of the domain or application partition to query. This name can either
/// be a DNS style name, for example, fabrikam.com, or a flat-style name, for example, Fabrikam. If a DNS style name is specified,
/// the name may be specified with or without a trailing period.
/// <para>
/// If the Flags parameter contains the DS_GC_SERVER_REQUIRED flag, DomainName must be the name of the forest. In this case,
/// DsGetDcName fails if DomainName specifies a name that is not the forest root.
/// </para>
/// <para>
/// If the Flags parameter contains the DS_GC_SERVER_REQUIRED flag and DomainName is NULL, DsGetDcName attempts to find a global
/// catalog in the forest of the computer identified by ComputerName, which is the local computer if ComputerName is NULL.
/// </para>
/// <para>
/// If DomainName is NULL and the Flags parameter does not contain the DS_GC_SERVER_REQUIRED flag, ComputerName is set to the default
/// domain name of the primary domain of the computer identified by ComputerName.
/// </para>
/// </param>
/// <param name="DomainGuid">
/// Pointer to a GUID structure that specifies the GUID of the domain queried. If DomainGuid is not NULL and the domain specified by
/// DomainName or ComputerName cannot be found, DsGetDcName attempts to locate a domain controller in the domain having the GUID
/// specified by DomainGuid.
/// </param>
/// <param name="SiteName">
/// Pointer to a null-terminated string that specifies the name of the site where the returned domain controller should physically
/// exist. If this parameter is NULL, DsGetDcName attempts to return a domain controller in the site closest to the site of the
/// computer specified by ComputerName. This parameter should be NULL, by default.
/// </param>
/// <param name="Flags">
/// Contains a set of flags that provide additional data used to process the request. This parameter can be a combination of the
/// following values.
/// </param>
/// <param name="DomainControllerInfo">
/// Pointer to a PDOMAIN_CONTROLLER_INFO value that receives a pointer to a DOMAIN_CONTROLLER_INFO structure that contains data about
/// the domain controller selected. This structure is allocated by DsGetDcName. The caller must free the structure using the
/// NetApiBufferFree function when it is no longer required.
/// </param>
/// <returns>
/// If the function returns domain controller data, the return value is ERROR_SUCCESS.
/// <para>If the function fails, the return value can be one of the following error codes.</para>
/// </returns>
[DllImport(Lib.NetApi32, CharSet = CharSet.Auto)]
[PInvokeData("DsGetDC.h", MSDNShortId = "ms675983")]
public static extern Win32Error DsGetDcName([Optional] string ComputerName, [Optional] string DomainName, [Optional] IntPtr DomainGuid, [Optional] string SiteName, DsGetDcNameFlags Flags, out SafeNetApiBuffer DomainControllerInfo);
/// <summary>
/// <para>The <c>DsGetDcNext</c> function retrieves the next domain controller in a domain controller enumeration operation.</para>
/// </summary>
/// <param name="GetDcContextHandle">
/// <para>Contains the domain controller enumeration context handle provided by the DsGetDcOpen function.</para>
/// </param>
/// <param name="SockAddressCount">
/// <para>
/// Pointer to a <c>ULONG</c> value that receives the number of elements in the SockAddresses array. If this parameter is
/// <c>NULL</c>, socket addresses are not retrieved.
/// </para>
/// </param>
/// <param name="SockAddresses">
/// <para>
/// Pointer to an array of SOCKET_ADDRESS structures that receives the socket address data for the domain controller.
/// SockAddressCount receives the number of elements in this array.
/// </para>
/// <para>
/// All returned addresses will be of type <c>AF_INET</c> or <c>AF_INET6</c>. The <c>sin_port</c> member contains the port from the
/// server record. A port of 0 indicates no port is available from DNS.
/// </para>
/// <para>The caller must free this memory when it is no longer required by calling LocalFree.</para>
/// <para>This parameter is ignored if SockAddressCount is <c>NULL</c>.</para>
/// </param>
/// <param name="DnsHostName">
/// <para>
/// Pointer to a string pointer that receives the DNS name of the domain controller. This parameter receives <c>NULL</c> if no host
/// name is known. The caller must free this memory when it is no longer required by calling NetApiBufferFree.
/// </para>
/// </param>
/// <returns>
/// <para>Returns <c>ERROR_SUCCESS</c> if successful or a Win32 or RPC error otherwise. Possible error values include the following.</para>
/// </returns>
/// <remarks>
/// <para>
/// To reset the enumeration, close the current enumeration by calling DsGetDcClose and then reopen the enumeration by calling
/// DsGetDcOpen again.
/// </para>
/// <para>
/// The DC returned by <c>DsGetDcNext</c> will not be a Read-only DC (RODC) because those DCs only register site-specific and CName
/// records, and both <c>DsGetDcNext</c> and DsGetDcOpen look for DNS SRV records.
/// </para>
/// <para>The following procedure shows how to get a complete DC list from a computer running Windows Server 2008.</para>
/// <para><c>To obtain a complete list of domain controllers</c></para>
/// <list type="number">
/// <item>
/// <term>Use DsGetDcName to get a domain controller name.</term>
/// </item>
/// <item>
/// <term>Use DsBind to connect to that domain controller.</term>
/// </item>
/// <item>
/// <term>
/// Call DsGetDomainControllerInfo with InfoLevel 3 ( <c>DS_DOMAIN_CONTROLLER_INFO_3</c>) to get the complete list, including RODCs.
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/Dsgetdc/nf-dsgetdc-dsgetdcnexta DSGETDCAPI DWORD DsGetDcNextA( IN HANDLE
// GetDcContextHandle, OUT PULONG SockAddressCount, OUT LPSOCKET_ADDRESS *SockAddresses, OUT LPSTR *DnsHostName );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "2906772f-4391-411b-b0a9-5a20ebb6c0ee")]
public static extern Win32Error DsGetDcNext(SafeDCEnumHandle GetDcContextHandle, out uint SockAddressCount, out SafeLocalHandle SockAddresses, out SafeNetApiBuffer DnsHostName);
/// <summary>
/// <para>The <c>DsGetDcOpen</c> function opens a new domain controller enumeration operation.</para>
/// </summary>
/// <param name="DnsName">
/// <para>
/// Pointer to a null-terminated string that contains the domain naming system (DNS) name of the domain to enumerate the domain
/// controllers for. This parameter cannot be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="OptionFlags">
/// <para>
/// Contains a set of flags that modify the behavior of the function. This can be zero or a combination of one or more of the
/// following values.
/// </para>
/// <para>DS_ONLY_DO_SITE_NAME</para>
/// <para>Only site-specific domain controllers are enumerated.</para>
/// <para>DS_NOTIFY_AFTER_SITE_RECORDS</para>
/// <para>
/// The DsGetDcNext function will return the <c>ERROR_FILEMARK_DETECTED</c> value after all of the site-specific domain controllers
/// are retrieved. <c>DsGetDcNext</c> will then enumerate the second group, which contains all domain controllers in the domain,
/// including the site-specific domain controllers contained in the first group.
/// </para>
/// </param>
/// <param name="SiteName">
/// <para>
/// Pointer to a null-terminated string that contains the name of site the client is in. This parameter is optional and may be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="DomainGuid">
/// <para>
/// Pointer to a <c>GUID</c> value that contains the identifier of the domain specified by DnsName. This identifier is used to handle
/// the case of a renamed domain. If this value is specified and the domain specified in DnsName is renamed, this function attempts
/// to enumerate domain controllers in the domain that contains the specified identifier. This parameter is optional and may be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="DnsForestName">
/// <para>
/// Pointer to a null-terminated string that contains the name of the forest that contains the DnsName domain. This value is used in
/// conjunction with DomainGuidto enumerate the domain controllers if the domain has been renamed. This parameter is optional and may
/// be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="DcFlags">
/// <para>
/// Contains a set of flags that identify the type of domain controllers to enumerate. This can be zero or a combination of one or
/// more of the following values.
/// </para>
/// <para>DS_FORCE_REDISCOVERY</para>
/// <para>
/// Forces cached domain controller data to be ignored. When this flag is not specified, <c>DsGetDcOpen</c> obtains the domain
/// controller enumeration from cached domain controller data.
/// </para>
/// <para>DS_GC_SERVER_REQUIRED</para>
/// <para>
/// Requires that the enumerated domain controllers be global catalog servers for the forest of domains with this domain as the root.
/// This flag cannot be combined with the <c>DS_PDC_REQUIRED</c> flag.
/// </para>
/// <para>DS_KDC_REQUIRED</para>
/// <para>
/// Requires that the enumerated domain controllers currently be running the Kerberos Key Distribution Center service. This flag
/// cannot be combined with the <c>DS_PDC_REQUIRED</c> or <c>DS_GC_SERVER_REQUIRED</c> flags.
/// </para>
/// <para>DS_ONLY_LDAP_NEEDED</para>
/// <para>
/// Specifies that the enumerated servers are LDAP servers. The servers are not necessarily domain controllers. No other services are
/// implied to be present at each enumerated server. The servers do not necessarily have a writable <c>config</c> container nor a
/// writable <c>schema</c> container. The servers may not necessarily be used to create or modify security principles. This flag may
/// be used with the <c>DS_GC_SERVER_REQUIRED</c> flag to enumerate LDAP servers that also host a global catalog server. In that
/// case, the enumerated global catalog servers are not necessarily domain controllers and other services are implied to be present
/// at each server. If this flag is specified, the <c>DS_PDC_REQUIRED</c>, <c>DS_TIMESERV_REQUIRED</c>,
/// <c>DS_GOOD_TIMESERV_PREFERRED</c>, <c>DS_DIRECTORY_SERVICES_PREFERED</c>, <c>DS_DIRECTORY_SERVICES_REQUIRED</c>, and
/// <c>DS_KDC_REQUIRED</c> flags are ignored.
/// </para>
/// <para>DS_PDC_REQUIRED</para>
/// <para>
/// Requires that the enumerated domain controllers be the primary domain controllers for the domain. This flag cannot be combined
/// with the <c>DS_GC_SERVER_REQUIRED</c> flag.
/// </para>
/// </param>
/// <param name="RetGetDcContext">
/// <para>
/// Pointer to a <c>HANDLE</c> value that receives the domain controller enumeration context handle. This handle is used with the
/// DsGetDcNext function to identify the domain controller enumeration operation. This handle is passed to DsGetDcClose to close the
/// domain controller enumeration operation.
/// </para>
/// </param>
/// <returns>
/// <para>Returns <c>ERROR_SUCCESS</c> if successful or a Win32 or RPC error otherwise. Possible error values include the following.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsgetdcopena DSGETDCAPI DWORD DsGetDcOpenA( IN LPCSTR
// DnsName, IN ULONG OptionFlags, IN LPCSTR SiteName, IN GUID *DomainGuid, IN LPCSTR DnsForestName, IN ULONG DcFlags, OUT PHANDLE
// RetGetDcContext );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "2811cc30-f367-4f1a-8f0c-ed0a77dad24c")]
public static extern Win32Error DsGetDcOpen(string DnsName, DsGetDcOpenOptions OptionFlags, [Optional] string SiteName, in Guid DomainGuid, [Optional] string DnsForestName, DsGetDcNameFlags DcFlags, out SafeDCEnumHandle RetGetDcContext);
/// <summary>
/// <para>The <c>DsGetDcOpen</c> function opens a new domain controller enumeration operation.</para>
/// </summary>
/// <param name="DnsName">
/// <para>
/// Pointer to a null-terminated string that contains the domain naming system (DNS) name of the domain to enumerate the domain
/// controllers for. This parameter cannot be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="OptionFlags">
/// <para>
/// Contains a set of flags that modify the behavior of the function. This can be zero or a combination of one or more of the
/// following values.
/// </para>
/// <para>DS_ONLY_DO_SITE_NAME</para>
/// <para>Only site-specific domain controllers are enumerated.</para>
/// <para>DS_NOTIFY_AFTER_SITE_RECORDS</para>
/// <para>
/// The DsGetDcNext function will return the <c>ERROR_FILEMARK_DETECTED</c> value after all of the site-specific domain controllers
/// are retrieved. <c>DsGetDcNext</c> will then enumerate the second group, which contains all domain controllers in the domain,
/// including the site-specific domain controllers contained in the first group.
/// </para>
/// </param>
/// <param name="SiteName">
/// <para>
/// Pointer to a null-terminated string that contains the name of site the client is in. This parameter is optional and may be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="DomainGuid">
/// <para>
/// Pointer to a <c>GUID</c> value that contains the identifier of the domain specified by DnsName. This identifier is used to handle
/// the case of a renamed domain. If this value is specified and the domain specified in DnsName is renamed, this function attempts
/// to enumerate domain controllers in the domain that contains the specified identifier. This parameter is optional and may be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="DnsForestName">
/// <para>
/// Pointer to a null-terminated string that contains the name of the forest that contains the DnsName domain. This value is used in
/// conjunction with DomainGuidto enumerate the domain controllers if the domain has been renamed. This parameter is optional and may
/// be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="DcFlags">
/// <para>
/// Contains a set of flags that identify the type of domain controllers to enumerate. This can be zero or a combination of one or
/// more of the following values.
/// </para>
/// <para>DS_FORCE_REDISCOVERY</para>
/// <para>
/// Forces cached domain controller data to be ignored. When this flag is not specified, <c>DsGetDcOpen</c> obtains the domain
/// controller enumeration from cached domain controller data.
/// </para>
/// <para>DS_GC_SERVER_REQUIRED</para>
/// <para>
/// Requires that the enumerated domain controllers be global catalog servers for the forest of domains with this domain as the root.
/// This flag cannot be combined with the <c>DS_PDC_REQUIRED</c> flag.
/// </para>
/// <para>DS_KDC_REQUIRED</para>
/// <para>
/// Requires that the enumerated domain controllers currently be running the Kerberos Key Distribution Center service. This flag
/// cannot be combined with the <c>DS_PDC_REQUIRED</c> or <c>DS_GC_SERVER_REQUIRED</c> flags.
/// </para>
/// <para>DS_ONLY_LDAP_NEEDED</para>
/// <para>
/// Specifies that the enumerated servers are LDAP servers. The servers are not necessarily domain controllers. No other services are
/// implied to be present at each enumerated server. The servers do not necessarily have a writable <c>config</c> container nor a
/// writable <c>schema</c> container. The servers may not necessarily be used to create or modify security principles. This flag may
/// be used with the <c>DS_GC_SERVER_REQUIRED</c> flag to enumerate LDAP servers that also host a global catalog server. In that
/// case, the enumerated global catalog servers are not necessarily domain controllers and other services are implied to be present
/// at each server. If this flag is specified, the <c>DS_PDC_REQUIRED</c>, <c>DS_TIMESERV_REQUIRED</c>,
/// <c>DS_GOOD_TIMESERV_PREFERRED</c>, <c>DS_DIRECTORY_SERVICES_PREFERED</c>, <c>DS_DIRECTORY_SERVICES_REQUIRED</c>, and
/// <c>DS_KDC_REQUIRED</c> flags are ignored.
/// </para>
/// <para>DS_PDC_REQUIRED</para>
/// <para>
/// Requires that the enumerated domain controllers be the primary domain controllers for the domain. This flag cannot be combined
/// with the <c>DS_GC_SERVER_REQUIRED</c> flag.
/// </para>
/// </param>
/// <param name="RetGetDcContext">
/// <para>
/// Pointer to a <c>HANDLE</c> value that receives the domain controller enumeration context handle. This handle is used with the
/// DsGetDcNext function to identify the domain controller enumeration operation. This handle is passed to DsGetDcClose to close the
/// domain controller enumeration operation.
/// </para>
/// </param>
/// <returns>
/// <para>Returns <c>ERROR_SUCCESS</c> if successful or a Win32 or RPC error otherwise. Possible error values include the following.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsgetdcopena DSGETDCAPI DWORD DsGetDcOpenA( IN LPCSTR
// DnsName, IN ULONG OptionFlags, IN LPCSTR SiteName, IN GUID *DomainGuid, IN LPCSTR DnsForestName, IN ULONG DcFlags, OUT PHANDLE
// RetGetDcContext );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "2811cc30-f367-4f1a-8f0c-ed0a77dad24c")]
public static extern Win32Error DsGetDcOpen(string DnsName, DsGetDcOpenOptions OptionFlags, [Optional] string SiteName, [Optional] IntPtr DomainGuid, [Optional] string DnsForestName, DsGetDcNameFlags DcFlags, out SafeDCEnumHandle RetGetDcContext);
/// <summary>
/// <para>The <c>DsGetDcSiteCoverage</c> function returns the site names of all sites covered by a domain controller.</para>
/// </summary>
/// <param name="ServerName">
/// <para>The null-terminated string value that specifies the name of the remote domain controller.</para>
/// </param>
/// <param name="EntryCount">
/// <para>Pointer to a <c>ULONG</c> value that receives the number of sites covered by the domain controller.</para>
/// </param>
/// <param name="SiteNames">
/// <para>
/// Pointer to an array of pointers to null-terminated strings that receives the site names. To free the returned buffer, call the
/// NetApiBufferFree function.
/// </para>
/// </param>
/// <returns>
/// <para>This function returns DSGETDCAPI DWORD.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsgetdcsitecoveragew DSGETDCAPI DWORD
// DsGetDcSiteCoverageW( IN LPCWSTR ServerName, OUT PULONG EntryCount, OUT LPWSTR **SiteNames );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "e0f757d9-36b6-40f8-a1db-fb5b9862b46a")]
public static extern Win32Error DsGetDcSiteCoverage([Optional] string ServerName, out uint EntryCount, out SafeNetApiBuffer SiteNames);
/// <summary>
/// <para>The <c>DsGetForestTrustInformationW</c> function obtains forest trust data for a specified domain.</para>
/// </summary>
/// <param name="ServerName">
/// <para>
/// Contains the name of the domain controller that <c>DsGetForestTrustInformationW</c> is connected to remotely. The caller must be
/// an authenticated user on this server. If this parameter is <c>NULL</c>, the local server is used.
/// </para>
/// </param>
/// <param name="TrustedDomainName">
/// <para>
/// Contains the NETBIOS or DNS name of the trusted domain that the forest trust data is to be retrieved for. This domain must have
/// the <c>TRUST_ATTRIBUTE_FOREST_TRANSITIVE</c> trust attribute. For more information, see TRUSTED_DOMAIN_INFORMATION_EX.
/// </para>
/// <para>If this parameter is <c>NULL</c>, the forest trust data for the domain hosted by ServerName is retrieved.</para>
/// </param>
/// <param name="Flags">
/// <para>Contains a set of flags that modify the behavior of this function. This can be zero or the following value.</para>
/// <para>DS_GFTI_UPDATE_TDO</para>
/// <para>
/// If this flag is set, <c>DsGetForestTrustInformationW</c> will update the forest trust data of the trusted domain identified by
/// the TrustedDomainNameparameter. In this case, the TrustedDomainName parameter cannot be <c>NULL</c>. The caller must have access
/// to modify the trust data or <c>ERROR_ACCESS_DENIED</c> is returned.
/// </para>
/// <para>This flag is only valid if ServerName specifies the primary domain controller of the domain.</para>
/// </param>
/// <param name="ForestTrustInfo">
/// <para>
/// Pointer to an LSA_FOREST_TRUST_INFORMATION structure pointer that receives the forest trust data that describes the namespaces
/// claimed by the domain specified by TrustedDomainName. The <c>Time</c> member of all returned records will be zero.
/// </para>
/// <para>The caller must free this structure when it is no longer required by calling NetApiBufferFree.</para>
/// </param>
/// <returns>
/// <para>Returns <c>NO_ERROR</c> if successful or a Win32 error code otherwise. Possible error codes include the following.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsgetforesttrustinformationw DSGETDCAPI DWORD
// DsGetForestTrustInformationW( IN LPCWSTR ServerName, IN LPCWSTR TrustedDomainName, IN DWORD Flags, OUT
// PLSA_FOREST_TRUST_INFORMATION *ForestTrustInfo );
[DllImport(Lib.NetApi32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)]
[PInvokeData("dsgetdc.h", MSDNShortId = "c94fdc5b-920b-4807-9cbf-3172ec1c7386")]
public static extern Win32Error DsGetForestTrustInformationW([Optional] string ServerName, [Optional] string TrustedDomainName, DsGetForestTrustInformationFlags Flags, out SafeNetApiBuffer ForestTrustInfo);
/// <summary>
/// <para>
/// The <c>DsGetSiteName</c> function returns the name of the site where a computer resides. For a domain controller (DC), the name
/// of the site is the location of the configured DC. For a member workstation or member server, the name specifies the workstation
/// site as configured in the domain of the computer.
/// </para>
/// </summary>
/// <param name="ComputerName">
/// <para>
/// Pointer to a null-terminated string that specifies the name of the server to send this function. A <c>NULL</c> implies the local computer.
/// </para>
/// </param>
/// <param name="SiteName">
/// <para>
/// Pointer to a variable that receives a pointer to a null-terminated string specifying the site location of this computer.
/// </para>
/// </param>
/// <returns>
/// <para>If the function returns account information, the return value is <c>NO_ERROR</c>.</para>
/// <para>If the function fails, the return value can be one of the following error codes.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>DsGetSiteName</c> function does not require any particular access to the specified domain. The function is sent to the
/// "NetLogon" service on the computer specified by ComputerName.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsgetsitenamea DSGETDCAPI DWORD DsGetSiteNameA( IN LPCSTR
// ComputerName, OUT LPSTR *SiteName );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "2dfffd9a-af4f-4a93-8b3c-966e4f7c455f")]
public static extern Win32Error DsGetSiteName([Optional] string ComputerName, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NetApiBufferUnicodeStringMarshaler))] out string SiteName);
/// <summary>
/// <para>
/// The <c>DsMergeForestTrustInformationW</c> function merges the changes from a new forest trust data structure with an old forest
/// trust data structure.
/// </para>
/// </summary>
/// <param name="DomainName">
/// <para>Pointer to a null-terminated Unicode string that specifies the trusted domain to update.</para>
/// </param>
/// <param name="NewForestTrustInfo">
/// <para>
/// Pointer to an <c>LSA_FOREST_TRUST_INFORMATION</c> structure that contains the new forest trust data to be merged. The
/// <c>Flags</c> and <c>Time</c> members of the entries are ignored.
/// </para>
/// </param>
/// <param name="OldForestTrustInfo">
/// <para>
/// Pointer to an <c>LSA_FOREST_TRUST_INFORMATION</c> structure that contains the old forest trust data to be merged. This parameter
/// may be <c>NULL</c> if no records exist.
/// </para>
/// </param>
/// <param name="MergedForestTrustInfo">
/// <para>Pointer to an <c>LSA_FOREST_TRUST_INFORMATION</c> structure pointer that receives the merged forest trust data.</para>
/// <para>The caller must free this structure when it is no longer required by calling NetApiBufferFree.</para>
/// </param>
/// <returns>
/// <para>Returns <c>NO_ERROR</c> if successful or a Windows error code otherwise.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsmergeforesttrustinformationw DSGETDCAPI DWORD
// DsMergeForestTrustInformationW( IN LPCWSTR DomainName, IN PLSA_FOREST_TRUST_INFORMATION NewForestTrustInfo, IN
// PLSA_FOREST_TRUST_INFORMATION OldForestTrustInfo, OUT PLSA_FOREST_TRUST_INFORMATION *MergedForestTrustInfo );
[DllImport(Lib.NetApi32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)]
[PInvokeData("dsgetdc.h", MSDNShortId = "f42e16d0-62b2-49c4-b182-d1e744afe58c")]
public static extern Win32Error DsMergeForestTrustInformationW(string DomainName, in LSA_FOREST_TRUST_INFORMATION NewForestTrustInfo, in LSA_FOREST_TRUST_INFORMATION OldForestTrustInfo, out SafeNetApiBuffer MergedForestTrustInfo);
/// <summary>
/// <para>
/// The <c>DsMergeForestTrustInformationW</c> function merges the changes from a new forest trust data structure with an old forest
/// trust data structure.
/// </para>
/// </summary>
/// <param name="DomainName">
/// <para>Pointer to a null-terminated Unicode string that specifies the trusted domain to update.</para>
/// </param>
/// <param name="NewForestTrustInfo">
/// <para>
/// Pointer to an <c>LSA_FOREST_TRUST_INFORMATION</c> structure that contains the new forest trust data to be merged. The
/// <c>Flags</c> and <c>Time</c> members of the entries are ignored.
/// </para>
/// </param>
/// <param name="OldForestTrustInfo">
/// <para>
/// Pointer to an <c>LSA_FOREST_TRUST_INFORMATION</c> structure that contains the old forest trust data to be merged. This parameter
/// may be <c>NULL</c> if no records exist.
/// </para>
/// </param>
/// <param name="MergedForestTrustInfo">
/// <para>Pointer to an <c>LSA_FOREST_TRUST_INFORMATION</c> structure pointer that receives the merged forest trust data.</para>
/// <para>The caller must free this structure when it is no longer required by calling NetApiBufferFree.</para>
/// </param>
/// <returns>
/// <para>Returns <c>NO_ERROR</c> if successful or a Windows error code otherwise.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsmergeforesttrustinformationw DSGETDCAPI DWORD
// DsMergeForestTrustInformationW( IN LPCWSTR DomainName, IN PLSA_FOREST_TRUST_INFORMATION NewForestTrustInfo, IN
// PLSA_FOREST_TRUST_INFORMATION OldForestTrustInfo, OUT PLSA_FOREST_TRUST_INFORMATION *MergedForestTrustInfo );
[DllImport(Lib.NetApi32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)]
[PInvokeData("dsgetdc.h", MSDNShortId = "f42e16d0-62b2-49c4-b182-d1e744afe58c")]
public static extern Win32Error DsMergeForestTrustInformationW(string DomainName, in LSA_FOREST_TRUST_INFORMATION NewForestTrustInfo, [Optional] IntPtr OldForestTrustInfo, out SafeNetApiBuffer MergedForestTrustInfo);
/// <summary>
/// <para>
/// The <c>DsValidateSubnetName</c> function validates a subnet name in the form xxx.xxx.xxx.xxx/YY. The Xxx.xxx.xxx.xxx portion must
/// be a valid IP address. Yy must be the number of leftmost significant bits included in the mask. All bits of the IP address that
/// are not covered by the mask must be specified as zero.
/// </para>
/// </summary>
/// <param name="SubnetName">
/// <para>Pointer to a null-terminated string that specifies the name of the subnet to validate.</para>
/// </param>
/// <returns>
/// <para>If the function returns account information, the return value is <c>NO_ERROR</c>.</para>
/// <para>If the function fails, the return value is the following error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/nf-dsgetdc-dsvalidatesubnetnamew DSGETDCAPI DWORD
// DsValidateSubnetNameW( IN LPCWSTR SubnetName );
[DllImport(Lib.NetApi32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsgetdc.h", MSDNShortId = "bed49e08-4cb7-439c-bfb7-815263ec7568")]
public static extern Win32Error DsValidateSubnetName(string SubnetName);
/// <summary>The DOMAIN_CONTROLLER_INFO structure is used with the DsGetDcName function to receive data about a domain controller.</summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[PInvokeData("DsGetDC.h", MSDNShortId = "ms675912")]
public struct DOMAIN_CONTROLLER_INFO
{
/// <summary>
/// Pointer to a null-terminated string that specifies the computer name of the discovered domain controller. The returned
/// computer name is prefixed with "\\". The DNS-style name, for example, "\\phoenix.fabrikam.com", is returned, if available. If
/// the DNS-style name is not available, the flat-style name (for example, "\\phoenix") is returned. This example would apply if
/// the domain is a Windows NT 4.0 domain or if the domain does not support the IP family of protocols.
/// </summary>
public string DomainControllerName;
/// <summary>
/// Pointer to a null-terminated string that specifies the address of the discovered domain controller. The address is prefixed
/// with "\\". This string is one of the types defined by the DomainControllerAddressType member.
/// </summary>
public string DomainControllerAddress;
/// <summary>Indicates the type of string that is contained in the DomainControllerAddress member.</summary>
public DomainControllerAddressType DomainControllerAddressType;
/// <summary>
/// The GUID of the domain. This member is zero if the domain controller does not have a Domain GUID; for example, the domain
/// controller is not a Windows 2000 domain controller.
/// </summary>
public Guid DomainGuid;
/// <summary>
/// Pointer to a null-terminated string that specifies the name of the domain. The DNS-style name, for example, "fabrikam.com",
/// is returned if available. Otherwise, the flat-style name, for example, "fabrikam", is returned. This name may be different
/// than the requested domain name if the domain has been renamed.
/// </summary>
public string DomainName;
/// <summary>
/// Pointer to a null-terminated string that specifies the name of the domain at the root of the DS tree. The DNS-style name, for
/// example, "fabrikam.com", is returned if available. Otherwise, the flat-style name, for example, "fabrikam" is returned.
/// </summary>
public string DnsForestName;
/// <summary>
/// Contains a set of flags that describe the domain controller. This can be zero or a combination of one or more of the
/// following values.
/// </summary>
public DomainControllerType Flags;
/// <summary>
/// Pointer to a null-terminated string that specifies the name of the site where the domain controller is located. This member
/// may be NULL if the domain controller is not in a site; for example, the domain controller is a Windows NT 4.0 domain controller.
/// </summary>
public string DcSiteName;
/// <summary>
/// Pointer to a null-terminated string that specifies the name of the site that the computer belongs to. The computer is
/// specified in the ComputerName parameter passed to DsGetDcName. This member may be NULL if the site that contains the computer
/// cannot be found; for example, if the DS administrator has not associated the subnet that the computer is in with a valid site.
/// </summary>
public string ClientSiteName;
}
/// <summary>
/// <para>The <c>DS_DOMAIN_TRUSTS</c> structure is used with the DsEnumerateDomainTrusts function to contain trust data for a domain.</para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsgetdc/ns-dsgetdc-_ds_domain_trustsa typedef struct _DS_DOMAIN_TRUSTSA {
// LPSTR NetbiosDomainName; LPSTR DnsDomainName; ULONG Flags; ULONG ParentIndex; ULONG TrustType; ULONG TrustAttributes; PSID
// DomainSid; GUID DomainGuid; } DS_DOMAIN_TRUSTSA, *PDS_DOMAIN_TRUSTSA;
[PInvokeData("dsgetdc.h", MSDNShortId = "cd260fd1-dc38-4405-95ba-097a23faf668")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DS_DOMAIN_TRUSTS
{
/// <summary>
/// <para>Pointer to a null-terminated string that contains the NetBIOS name of the domain.</para>
/// </summary>
public string NetbiosDomainName;
/// <summary>
/// <para>Pointer to a null-terminated string that contains the DNS name of the domain. This member may be <c>NULL</c>.</para>
/// </summary>
public string DnsDomainName;
/// <summary>
/// <para>
/// Contains a set of flags that specify more data about the domain trust. This can be zero or a combination of one or more of
/// the following values.
/// </para>
/// <para>DS_DOMAIN_IN_FOREST (1 (0x1))</para>
/// <para>
/// The domain represented by this structure is a member of the same forest as the server specified in the ServerName parameter
/// of the DsEnumerateDomainTrusts function.
/// </para>
/// <para>DS_DOMAIN_DIRECT_OUTBOUND (2 (0x2))</para>
/// <para>
/// The domain represented by this structure is directly trusted by the domain that the server specified in the ServerName
/// parameter of the DsEnumerateDomainTrusts function is a member of.
/// </para>
/// <para>DS_DOMAIN_TREE_ROOT (4 (0x4))</para>
/// <para>
/// The domain represented by this structure is the root of a tree and a member of the same forest as the server specified in the
/// ServerName parameter of the DsEnumerateDomainTrusts function.
/// </para>
/// <para>DS_DOMAIN_PRIMARY (8 (0x8))</para>
/// <para>
/// The domain represented by this structure is the primary domain of the server specified in the ServerName parameter of the
/// DsEnumerateDomainTrusts function.
/// </para>
/// <para>DS_DOMAIN_NATIVE_MODE (16 (0x10))</para>
/// <para>The domain represented by this structure is running in the Windows 2000 native mode.</para>
/// <para>DS_DOMAIN_DIRECT_INBOUND (32 (0x20))</para>
/// <para>
/// The domain represented by this structure directly trusts the domain that the server specified in the ServerName parameter of
/// the DsEnumerateDomainTrusts function is a member of.
/// </para>
/// </summary>
public DomainTrustFlag Flags;
/// <summary>
/// <para>
/// Contains the index in the Domains array returned by the DsEnumerateDomainTrusts function that corresponds to the parent
/// domain of the domain represented by this structure. This member is only valid if the all of the following conditions are met:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>The <c>DS_DOMAIN_IN_FOREST</c> flag was specified in the Flags parameter of the DsEnumerateDomainTrusts function.</term>
/// </item>
/// <item>
/// <term>The <c>Flags</c> member of this structure does not contain the <c>DS_DOMAIN_TREE_ROOT</c> flag.</term>
/// </item>
/// </list>
/// </summary>
public uint ParentIndex;
/// <summary>
/// <para>
/// Contains a value that indicates the type of trust represented by this structure. Possible values for this member are
/// documented in the <c>TrustType</c> member of the TRUSTED_DOMAIN_INFORMATION_EX structure.
/// </para>
/// </summary>
public TrustType TrustType;
/// <summary>
/// <para>
/// Contains a value that indicates the attributes of the trust represented by this structure. Possible values for this member
/// are documented in the <c>TrustAttribute</c> member of the TRUSTED_DOMAIN_INFORMATION_EX structure.
/// </para>
/// </summary>
public TrustAttributes TrustAttributes;
/// <summary>
/// <para>Contains the security identifier of the domain represented by this structure.</para>
/// </summary>
public IntPtr DomainSid;
/// <summary>
/// <para>Contains the GUID of the domain represented by this structure.</para>
/// </summary>
public Guid DomainGuid;
}
/// <summary>
/// Provides a <see cref="SafeHandle"/> to a domain controller enumeration handle that is released at disposal using DsGetDcClose.
/// </summary>
public class SafeDCEnumHandle : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeDCEnumHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeDCEnumHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeDCEnumHandle"/> class.</summary>
private SafeDCEnumHandle() : base() { }
/// <inheritdoc/>
protected override bool InternalReleaseHandle() { DsGetDcClose(handle); return true; }
}
}
}