Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I use a couple of utility classes based off of the Win32 methods DsGetRdnW, DsQuoteRdnValueW, and DsUnquoteRdnValueW:</p> <pre><code>using System; using System.ComponentModel; using System.Collections.Generic; using System.Runtime.InteropServices; namespace UnmanagedCode { public class PInvoke { #region Constants public const int ERROR_SUCCESS = 0; public const int ERROR_BUFFER_OVERFLOW = 111; #endregion Constants #region DN Parsing [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] protected static extern int DsGetRdnW( ref IntPtr ppDN, ref int pcDN, out IntPtr ppKey, out int pcKey, out IntPtr ppVal, out int pcVal ); public static KeyValuePair&lt;string, string&gt; GetName(string distinguishedName) { IntPtr pDistinguishedName = Marshal.StringToHGlobalUni(distinguishedName); try { IntPtr pDN = pDistinguishedName, pKey, pVal; int cDN = distinguishedName.Length, cKey, cVal; int lastError = DsGetRdnW(ref pDN, ref cDN, out pKey, out cKey, out pVal, out cVal); if(lastError == ERROR_SUCCESS) { string key, value; if(cKey &lt; 1) { key = string.Empty; } else { key = Marshal.PtrToStringUni(pKey, cKey); } if(cVal &lt; 1) { value = string.Empty; } else { value = Marshal.PtrToStringUni(pVal, cVal); } return new KeyValuePair&lt;string, string&gt;(key, value); } else { throw new Win32Exception(lastError); } } finally { Marshal.FreeHGlobal(pDistinguishedName); } } public static IEnumerable&lt;KeyValuePair&lt;string, string&gt;&gt; ParseDN(string distinguishedName) { List&lt;KeyValuePair&lt;string, string&gt; components = new List&lt;KeyValuePair&lt;string, string&gt;&gt;(); IntPtr pDistinguishedName = Marshal.StringToHGlobalUni(distinguishedName); try { IntPtr pDN = pDistinguishedName, pKey, pVal; int cDN = distinguishedName.Length, cKey, cVal; do { int lastError = DsGetRdnW(ref pDN, ref cDN, out pKey, out cKey, out pVal, out cVal); if(lastError = ERROR_SUCCESS) { string key, value; if(cKey &lt; 0) { key = null; } else if(cKey == 0) { key = string.Empty; } else { key = Marshal.PtrToStringUni(pKey, cKey); } if(cVal &lt; 0) { value = null; } else if(cVal == 0) { value = string.Empty; } else { value = Marshal.PtrToStringUni(pVal, cVal); } components.Add(new KeyValuePair&lt;string, string&gt;(key, value)); pDN = (IntPtr)(pDN.ToInt64() + UnicodeEncoding.CharSize); //skip over comma cDN--; } else { throw new Win32Exception(lastError); } } while(cDN &gt; 0); return components; } finally { Marshal.FreeHGlobal(pDistinguishedName); } } [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] protected static extern int DsQuoteRdnValueW( int cUnquotedRdnValueLength, string psUnquotedRdnValue, ref int pcQuotedRdnValueLength, IntPtr psQuotedRdnValue ); public static string QuoteRDN(string rdn) { if (rdn == null) return null; int initialLength = rdn.Length; int quotedLength = 0; IntPtr pQuotedRDN = IntPtr.Zero; int lastError = DsQuoteRdnValueW(initialLength, rdn, ref quotedLength, pQuotedRDN); switch (lastError) { case ERROR_SUCCESS: { return string.Empty; } case ERROR_BUFFER_OVERFLOW: { break; //continue } default: { throw new Win32Exception(lastError); } } pQuotedRDN = Marshal.AllocHGlobal(quotedLength * UnicodeEncoding.CharSize); try { lastError = DsQuoteRdnValueW(initialLength, rdn, ref quotedLength, pQuotedRDN); switch(lastError) { case ERROR_SUCCESS: { return Marshal.PtrToStringUni(pQuotedRDN, quotedLength); } default: { throw new Win32Exception(lastError); } } } finally { if(pQuotedRDN != IntPtr.Zero) { Marshal.FreeHGlobal(pQuotedRDN); } } } [DllImport("ntdsapi.dll", CharSet = CharSet.Unicode)] protected static extern int DsUnquoteRdnValueW( int cQuotedRdnValueLength, string psQuotedRdnValue, ref int pcUnquotedRdnValueLength, IntPtr psUnquotedRdnValue ); public static string UnquoteRDN(string rdn) { if (rdn == null) return null; int initialLength = rdn.Length; int unquotedLength = 0; IntPtr pUnquotedRDN = IntPtr.Zero; int lastError = DsUnquoteRdnValueW(initialLength, rdn, ref unquotedLength, pUnquotedRDN); switch (lastError) { case ERROR_SUCCESS: { return string.Empty; } case ERROR_BUFFER_OVERFLOW: { break; //continue } default: { throw new Win32Exception(lastError); } } pUnquotedRDN = Marshal.AllocHGlobal(unquotedLength * UnicodeEncoding.CharSize); try { lastError = DsUnquoteRdnValueW(initialLength, rdn, ref unquotedLength, pUnquotedRDN); switch(lastError) { case ERROR_SUCCESS: { return Marshal.PtrToStringUni(pUnquotedRDN, unquotedLength); } default: { throw new Win32Exception(lastError); } } } finally { if(pUnquotedRDN != IntPtr.Zero) { Marshal.FreeHGlobal(pUnquotedRDN); } } } #endregion DN Parsing } public class DNComponent { public string Type { get; protected set; } public string EscapedValue { get; protected set; } public string UnescapedValue { get; protected set; } public string WholeComponent { get; protected set; } public DNComponent(string component, bool isEscaped) { string[] tokens = component.Split(new char[] { '=' }, 2); setup(tokens[0], tokens[1], isEscaped); } public DNComponent(string key, string value, bool isEscaped) { setup(key, value, isEscaped); } private void setup(string key, string value, bool isEscaped) { Type = key; if(isEscaped) { EscapedValue = value; UnescapedValue = PInvoke.UnquoteRDN(value); } else { EscapedValue = PInvoke.QuoteRDN(value); UnescapedValue = value; } WholeComponent = Type + "=" + EscapedValue; } public override bool Equals(object obj) { if (obj is DNComponent) { DNComponent dnObj = (DNComponent)obj; return dnObj.WholeComponent.Equals(this.WholeComponent, StringComparison.CurrentCultureIgnoreCase); } return base.Equals(obj); } public override int GetHashCode() { return WholeComponent.GetHashCode(); } } public class DistinguishedName { public DNComponent[] Components { get { return components.ToArray(); } } private List&lt;DNComponent&gt; components; private string cachedDN; public DistinguishedName(string distinguishedName) { cachedDN = distinguishedName; components = new List&lt;DNComponent&gt;(); foreach (KeyValuePair&lt;string, string&gt; kvp in PInvoke.ParseDN(distinguishedName)) { components.Add(new DNComponent(kvp.Key, kvp.Value, true)); } } public DistinguishedName(IEnumerable&lt;DNComponent&gt; dnComponents) { components = new List&lt;DNComponent&gt;(dnComponents); cachedDN = GetWholePath(","); } public bool Contains(DNComponent dnComponent) { return components.Contains(component); } public string GetDNSDomainName() { List&lt;string&gt; dcs = new List&lt;string&gt;(); foreach (DNComponent dnc in components) { if(dnc.Type.Equals("DC", StringComparison.CurrentCultureIgnoreCase)) { dcs.Add(dnc.UnescapedValue); } } return string.Join(".", dcs.ToArray()); } public string GetDomainDN() { List&lt;string&gt; dcs = new List&lt;string&gt;(); foreach (DNComponent dnc in components) { if(dnc.Type.Equals("DC", StringComparison.CurrentCultureIgnoreCase)) { dcs.Add(dnc.WholeComponent); } } return string.Join(",", dcs.ToArray()); } public string GetWholePath() { return GetWholePath(","); } public string GetWholePath(string separator) { List&lt;string&gt; parts = new List&lt;string&gt;(); foreach (DNComponent component in components) { parts.Add(component.WholeComponent); } return string.Join(separator, parts.ToArray()); } public DistinguishedName GetParent() { if(components.Count == 1) { return null; } List&lt;DNComponent&gt; tempList = new List&lt;DNComponent&gt;(components); tempList.RemoveAt(0); return new DistinguishedName(tempList); } public override bool Equals(object obj) { if(obj is DistinguishedName) { DistinguishedName objDN = (DistinguishedName)obj; if (this.Components.Length == objDN.Components.Length) { for (int i = 0; i &lt; this.Components.Length; i++) { if (!this.Components[i].Equals(objDN.Components[i])) { return false; } } return true; } return false; } return base.Equals(obj); } public override int GetHashCode() { return cachedDN.GetHashCode(); } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload