Advertisement
Guest User

Untitled

a guest
May 26th, 2017
391
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 80.07 KB | None | 0 0
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4.  
  5. namespace System.DirectoryServices.Protocols
  6. {
  7.     using System;
  8.     using System.Globalization;
  9.     using System.Net;
  10.     using System.Collections;
  11.     using System.ComponentModel;
  12.     using System.Text;
  13.     using System.Diagnostics;
  14.     using System.Runtime.InteropServices;
  15.     using System.Xml;
  16.     using System.Threading;
  17.     using System.Security.Cryptography.X509Certificates;
  18.     using System.DirectoryServices;
  19.     using System.Security.Permissions;
  20.  
  21.     internal delegate DirectoryResponse GetLdapResponseCallback(int messageId, LdapOperation operation, ResultAll resultType, TimeSpan requestTimeout, bool exceptionOnTimeOut);
  22.  
  23.     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  24.     internal delegate bool QUERYCLIENTCERT(IntPtr Connection, IntPtr trusted_CAs, ref IntPtr certificateHandle);
  25.  
  26.     public class LdapConnection : DirectoryConnection, IDisposable
  27.     {
  28.         internal enum LdapResult
  29.         {
  30.             LDAP_RES_SEARCH_RESULT = 0x65,
  31.             LDAP_RES_SEARCH_ENTRY = 0x64,
  32.             LDAP_RES_MODIFY = 0x67,
  33.             LDAP_RES_ADD = 0x69,
  34.             LDAP_RES_DELETE = 0x6b,
  35.             LDAP_RES_MODRDN = 0x6d,
  36.             LDAP_RES_COMPARE = 0x6f,
  37.             LDAP_RES_REFERRAL = 0x73,
  38.             LDAP_RES_EXTENDED = 0x78
  39.         }
  40.  
  41.         private const int LDAP_MOD_BVALUES = 0x80;
  42.         private AuthType _connectionAuthType = AuthType.Negotiate;
  43.         private LdapSessionOptions _options = null;
  44.         internal ConnectionHandle ldapHandle = null;
  45.         internal bool disposed = false;
  46.         private bool _bounded = false;
  47.         private bool _needRebind = false;
  48.         internal static Hashtable handleTable = null;
  49.         internal static object objectLock = null;
  50.         private GetLdapResponseCallback _fd = null;
  51.         private static Hashtable s_asyncResultTable = null;
  52.         private static LdapPartialResultsProcessor s_partialResultsProcessor = null;
  53.         private static ManualResetEvent s_waitHandle = null;
  54.         private static PartialResultsRetriever s_retriever = null;
  55.         private bool _setFQDNDone = false;
  56.         internal bool automaticBind = true;
  57.         internal bool needDispose = true;
  58.         private bool _connected = false;
  59.         internal QUERYCLIENTCERT clientCertificateRoutine = null;
  60.  
  61.         static LdapConnection()
  62.         {
  63.             handleTable = new Hashtable();
  64.             // initialize the lock
  65.             objectLock = new Object();
  66.  
  67.             Hashtable tempAsyncTable = new Hashtable();
  68.             s_asyncResultTable = Hashtable.Synchronized(tempAsyncTable);
  69.  
  70.             s_waitHandle = new ManualResetEvent(false);
  71.  
  72.             s_partialResultsProcessor = new LdapPartialResultsProcessor(s_waitHandle);
  73.  
  74.             s_retriever = new PartialResultsRetriever(s_waitHandle, s_partialResultsProcessor);
  75.         }
  76.  
  77.         public LdapConnection(string server) : this(new LdapDirectoryIdentifier(server))
  78.         {
  79.         }
  80.  
  81.         public LdapConnection(LdapDirectoryIdentifier identifier) : this(identifier, null, AuthType.Negotiate)
  82.         {
  83.         }
  84.  
  85.         public LdapConnection(LdapDirectoryIdentifier identifier, NetworkCredential credential) : this(identifier, credential, AuthType.Negotiate)
  86.         {
  87.         }
  88.  
  89.         public LdapConnection(LdapDirectoryIdentifier identifier, NetworkCredential credential, AuthType authType)
  90.         {
  91.             _fd = new GetLdapResponseCallback(ConstructResponse);
  92.             directoryIdentifier = identifier;
  93.             directoryCredential = (credential != null) ? new NetworkCredential(credential.UserName, credential.Password, credential.Domain) : null;
  94.  
  95.             _connectionAuthType = authType;
  96.  
  97.             if (authType < AuthType.Anonymous || authType > AuthType.Kerberos)
  98.                 throw new InvalidEnumArgumentException("authType", (int)authType, typeof(AuthType));
  99.  
  100.             // if user wants to do anonymous bind, but specifies credential, error out
  101.             if (AuthType == AuthType.Anonymous && (directoryCredential != null && ((directoryCredential.Password != null && directoryCredential.Password.Length != 0) || (directoryCredential.UserName != null && directoryCredential.UserName.Length != 0))))
  102.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.InvalidAuthCredential));
  103.  
  104.             Init();
  105.             _options = new LdapSessionOptions(this);
  106.             clientCertificateRoutine = new QUERYCLIENTCERT(ProcessClientCertificate);
  107.         }
  108.  
  109.         internal LdapConnection(LdapDirectoryIdentifier identifier, NetworkCredential credential, AuthType authType, IntPtr handle)
  110.         {
  111.             directoryIdentifier = identifier;
  112.             needDispose = false;
  113.             ldapHandle = new ConnectionHandle(handle, needDispose);
  114.             directoryCredential = credential;
  115.             _connectionAuthType = authType;
  116.             _options = new LdapSessionOptions(this);
  117.             clientCertificateRoutine = new QUERYCLIENTCERT(ProcessClientCertificate);
  118.         }
  119.  
  120.         ~LdapConnection()
  121.         {
  122.             Dispose(false);
  123.         }
  124.  
  125.         public override TimeSpan Timeout
  126.         {
  127.             get
  128.             {
  129.                 return connectionTimeOut;
  130.             }
  131.             set
  132.             {
  133.                 if (value < TimeSpan.Zero)
  134.                 {
  135.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.NoNegativeTime), "value");
  136.                 }
  137.  
  138.                 // prevent integer overflow
  139.                 if (value.TotalSeconds > Int32.MaxValue)
  140.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.TimespanExceedMax), "value");
  141.  
  142.                 connectionTimeOut = value;
  143.             }
  144.         }
  145.  
  146.         public AuthType AuthType
  147.         {
  148.             get
  149.             {
  150.                 return _connectionAuthType;
  151.             }
  152.             set
  153.             {
  154.                 if (value < AuthType.Anonymous || value > AuthType.Kerberos)
  155.                     throw new InvalidEnumArgumentException("value", (int)value, typeof(AuthType));
  156.  
  157.                 // if the change is made after we have bound to the server and value is really changed, set the flag to indicate the need to do rebind
  158.                 if (_bounded && (value != _connectionAuthType))
  159.                 {
  160.                     _needRebind = true;
  161.                 }
  162.  
  163.                 _connectionAuthType = value;
  164.             }
  165.         }
  166.  
  167.         public LdapSessionOptions SessionOptions
  168.         {
  169.             get
  170.             {
  171.                 return _options;
  172.             }
  173.         }
  174.  
  175.         public override NetworkCredential Credential
  176.         {
  177.             set
  178.             {
  179.                 if (_bounded && !SameCredential(directoryCredential, value))
  180.                     _needRebind = true;
  181.  
  182.                 directoryCredential = (value != null) ? new NetworkCredential(value.UserName, value.Password, value.Domain) : null;
  183.             }
  184.         }
  185.  
  186.         public bool AutoBind
  187.         {
  188.             get
  189.             {
  190.                 return automaticBind;
  191.             }
  192.             set
  193.             {
  194.                 automaticBind = value;
  195.             }
  196.         }
  197.  
  198.         internal bool NeedDispose
  199.         {
  200.             get
  201.             {
  202.                 return needDispose;
  203.             }
  204.             set
  205.             {
  206.                 if (null != ldapHandle)
  207.                 {
  208.                     ldapHandle.needDispose = value;
  209.                 }
  210.                 needDispose = value;
  211.             }
  212.         }
  213.  
  214.         internal void Init()
  215.         {
  216.             string hostname = null;
  217.             string[] servers = (directoryIdentifier == null ? null : ((LdapDirectoryIdentifier)directoryIdentifier).Servers);
  218.             if (servers != null && servers.Length != 0)
  219.             {
  220.                 StringBuilder temp = new StringBuilder(200);
  221.                 for (int i = 0; i < servers.Length; i++)
  222.                 {
  223.                     if (servers[i] != null)
  224.                     {
  225.                         temp.Append(servers[i]);
  226.                         if (i < servers.Length - 1)
  227.                             temp.Append(" ");
  228.                     }
  229.                 }
  230.                 if (temp.Length != 0)
  231.                     hostname = temp.ToString();
  232.             }
  233.  
  234.             // user wants to setup a connectionless session with server
  235.             if (((LdapDirectoryIdentifier)directoryIdentifier).Connectionless == true)
  236.             {
  237.                 ldapHandle = new ConnectionHandle(Wldap32.cldap_open(hostname, ((LdapDirectoryIdentifier)directoryIdentifier).PortNumber), needDispose);
  238.             }
  239.             else
  240.             {
  241.                 ldapHandle = new ConnectionHandle(Wldap32.ldap_init(hostname, ((LdapDirectoryIdentifier)directoryIdentifier).PortNumber), needDispose);
  242.             }
  243.  
  244.             // create a WeakReference object with the target of ldapHandle and put it into our handle table.
  245.             lock (objectLock)
  246.             {
  247.                 if (handleTable[ldapHandle.DangerousGetHandle()] != null)
  248.                     handleTable.Remove(ldapHandle.DangerousGetHandle());
  249.  
  250.                 handleTable.Add(ldapHandle.DangerousGetHandle(), new WeakReference(this));
  251.             }
  252.         }
  253.  
  254.         public override DirectoryResponse SendRequest(DirectoryRequest request)
  255.         {
  256.             // no request specific timeout is specified, use the connection timeout
  257.             return SendRequest(request, connectionTimeOut);
  258.         }
  259.  
  260.         public DirectoryResponse SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
  261.         {
  262.             if (this.disposed)
  263.                 throw new ObjectDisposedException(GetType().Name);
  264.  
  265.             if (request == null)
  266.                 throw new ArgumentNullException("request");
  267.  
  268.             if (request is DsmlAuthRequest)
  269.                 throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, SR.DsmlAuthRequestNotSupported));
  270.  
  271.             int messageID = 0;
  272.             int error = SendRequestHelper(request, ref messageID);
  273.  
  274.             LdapOperation operation = LdapOperation.LdapSearch;
  275.             if (request is DeleteRequest)
  276.                 operation = LdapOperation.LdapDelete;
  277.             else if (request is AddRequest)
  278.                 operation = LdapOperation.LdapAdd;
  279.             else if (request is ModifyRequest)
  280.                 operation = LdapOperation.LdapModify;
  281.             else if (request is SearchRequest)
  282.                 operation = LdapOperation.LdapSearch;
  283.             else if (request is ModifyDNRequest)
  284.                 operation = LdapOperation.LdapModifyDn;
  285.             else if (request is CompareRequest)
  286.                 operation = LdapOperation.LdapCompare;
  287.             else if (request is ExtendedRequest)
  288.                 operation = LdapOperation.LdapExtendedRequest;
  289.  
  290.             if (error == 0 && messageID != -1)
  291.             {
  292.                 return ConstructResponse(messageID, operation, ResultAll.LDAP_MSG_ALL, requestTimeout, true);
  293.             }
  294.             else
  295.             {
  296.                 if (error == 0)
  297.                 {
  298.                     // success code but message is -1, unexpected
  299.                     error = Wldap32.LdapGetLastError();
  300.                 }
  301.  
  302.                 throw ConstructException(error, operation);
  303.             }
  304.         }
  305.  
  306.         public IAsyncResult BeginSendRequest(DirectoryRequest request, PartialResultProcessing partialMode, AsyncCallback callback, object state)
  307.         {
  308.             return BeginSendRequest(request, connectionTimeOut, partialMode, callback, state);
  309.         }
  310.  
  311.         public IAsyncResult BeginSendRequest(DirectoryRequest request, TimeSpan requestTimeout, PartialResultProcessing partialMode, AsyncCallback callback, object state)
  312.         {
  313.             int messageID = 0;
  314.             int error = 0;
  315.  
  316.             if (this.disposed)
  317.                 throw new ObjectDisposedException(GetType().Name);
  318.  
  319.             // parameter validation
  320.             if (request == null)
  321.                 throw new ArgumentNullException("request");
  322.  
  323.             if (partialMode < PartialResultProcessing.NoPartialResultSupport || partialMode > PartialResultProcessing.ReturnPartialResultsAndNotifyCallback)
  324.                 throw new InvalidEnumArgumentException("partialMode", (int)partialMode, typeof(PartialResultProcessing));
  325.  
  326.             if (partialMode != PartialResultProcessing.NoPartialResultSupport && !(request is SearchRequest))
  327.                 throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, SR.PartialResultsNotSupported));
  328.  
  329.             if (partialMode == PartialResultProcessing.ReturnPartialResultsAndNotifyCallback && (callback == null))
  330.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.CallBackIsNull), "callback");
  331.  
  332.             error = SendRequestHelper(request, ref messageID);
  333.  
  334.             LdapOperation operation = LdapOperation.LdapSearch;
  335.             if (request is DeleteRequest)
  336.                 operation = LdapOperation.LdapDelete;
  337.             else if (request is AddRequest)
  338.                 operation = LdapOperation.LdapAdd;
  339.             else if (request is ModifyRequest)
  340.                 operation = LdapOperation.LdapModify;
  341.             else if (request is SearchRequest)
  342.                 operation = LdapOperation.LdapSearch;
  343.             else if (request is ModifyDNRequest)
  344.                 operation = LdapOperation.LdapModifyDn;
  345.             else if (request is CompareRequest)
  346.                 operation = LdapOperation.LdapCompare;
  347.             else if (request is ExtendedRequest)
  348.                 operation = LdapOperation.LdapExtendedRequest;
  349.  
  350.             if (error == 0 && messageID != -1)
  351.             {
  352.                 if (partialMode == PartialResultProcessing.NoPartialResultSupport)
  353.                 {
  354.                     LdapRequestState rs = new LdapRequestState();
  355.                     LdapAsyncResult asyncResult = new LdapAsyncResult(callback, state, false);
  356.  
  357.                     rs.ldapAsync = asyncResult;
  358.                     asyncResult.resultObject = rs;
  359.  
  360.                     s_asyncResultTable.Add(asyncResult, messageID);
  361.  
  362.                     _fd.BeginInvoke(messageID, operation, ResultAll.LDAP_MSG_ALL, requestTimeout, true, new AsyncCallback(ResponseCallback), rs);
  363.  
  364.                     return (IAsyncResult)asyncResult;
  365.                 }
  366.                 else
  367.                 {
  368.                     // the user registers to retrieve partial results
  369.                     bool partialCallback = false;
  370.                     if (partialMode == PartialResultProcessing.ReturnPartialResultsAndNotifyCallback)
  371.                         partialCallback = true;
  372.                     LdapPartialAsyncResult asyncResult = new LdapPartialAsyncResult(messageID, callback, state, true, this, partialCallback, requestTimeout);
  373.                     s_partialResultsProcessor.Add(asyncResult);
  374.  
  375.                     return (IAsyncResult)asyncResult;
  376.                 }
  377.             }
  378.             else
  379.             {
  380.                 if (error == 0)
  381.                 {
  382.                     // success code but message is -1, unexpected
  383.                     error = Wldap32.LdapGetLastError();
  384.                 }
  385.  
  386.                 throw ConstructException(error, operation);
  387.             }
  388.         }
  389.  
  390.         private void ResponseCallback(IAsyncResult asyncResult)
  391.         {
  392.             LdapRequestState rs = (LdapRequestState)asyncResult.AsyncState;
  393.  
  394.             try
  395.             {
  396.                 DirectoryResponse response = _fd.EndInvoke(asyncResult);
  397.                 rs.response = response;
  398.             }
  399.             catch (Exception e)
  400.             {
  401.                 rs.exception = e;
  402.                 rs.response = null;
  403.             }
  404.  
  405.             // signal waitable object, indicate operation completed and fire callback
  406.             rs.ldapAsync.manualResetEvent.Set();
  407.             rs.ldapAsync.completed = true;
  408.             if (rs.ldapAsync.callback != null && !rs.abortCalled)
  409.             {
  410.                 rs.ldapAsync.callback((IAsyncResult)rs.ldapAsync);
  411.             }
  412.         }
  413.  
  414.         public void Abort(IAsyncResult asyncResult)
  415.         {
  416.             if (this.disposed)
  417.                 throw new ObjectDisposedException(GetType().Name);
  418.  
  419.             if (asyncResult == null)
  420.                 throw new ArgumentNullException("asyncResult");
  421.  
  422.             if (!(asyncResult is LdapAsyncResult))
  423.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.NotReturnedAsyncResult, "asyncResult"));
  424.  
  425.             int messageId = -1;
  426.  
  427.             LdapAsyncResult result = (LdapAsyncResult)asyncResult;
  428.  
  429.             if (!result.partialResults)
  430.             {
  431.                 if (!s_asyncResultTable.Contains(asyncResult))
  432.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.InvalidAsyncResult));
  433.  
  434.                 messageId = (int)(s_asyncResultTable[asyncResult]);
  435.  
  436.                 // remove the asyncResult from our connection table
  437.                 s_asyncResultTable.Remove(asyncResult);
  438.             }
  439.             else
  440.             {
  441.                 s_partialResultsProcessor.Remove((LdapPartialAsyncResult)asyncResult);
  442.                 messageId = ((LdapPartialAsyncResult)asyncResult).messageID;
  443.             }
  444.  
  445.             // cancel the request
  446.             Wldap32.ldap_abandon(ldapHandle, messageId);
  447.  
  448.             LdapRequestState rs = result.resultObject;
  449.             if (rs != null)
  450.                 rs.abortCalled = true;
  451.         }
  452.  
  453.         public PartialResultsCollection GetPartialResults(IAsyncResult asyncResult)
  454.         {
  455.             if (this.disposed)
  456.                 throw new ObjectDisposedException(GetType().Name);
  457.  
  458.             if (asyncResult == null)
  459.                 throw new ArgumentNullException("asyncResult");
  460.  
  461.             if (!(asyncResult is LdapAsyncResult))
  462.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.NotReturnedAsyncResult, "asyncResult"));
  463.  
  464.             if (!(asyncResult is LdapPartialAsyncResult))
  465.                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.NoPartialResults));
  466.  
  467.             return s_partialResultsProcessor.GetPartialResults((LdapPartialAsyncResult)asyncResult);
  468.         }
  469.  
  470.         public DirectoryResponse EndSendRequest(IAsyncResult asyncResult)
  471.         {
  472.             if (this.disposed)
  473.                 throw new ObjectDisposedException(GetType().Name);
  474.  
  475.             if (asyncResult == null)
  476.                 throw new ArgumentNullException("asyncResult");
  477.  
  478.             if (!(asyncResult is LdapAsyncResult))
  479.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.NotReturnedAsyncResult, "asyncResult"));
  480.  
  481.             LdapAsyncResult result = (LdapAsyncResult)asyncResult;
  482.  
  483.             if (!result.partialResults)
  484.             {
  485.                 // not a partial results
  486.                 if (!s_asyncResultTable.Contains(asyncResult))
  487.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.InvalidAsyncResult));
  488.  
  489.                 // remove the asyncResult from our connection table
  490.                 s_asyncResultTable.Remove(asyncResult);
  491.  
  492.                 asyncResult.AsyncWaitHandle.WaitOne();
  493.  
  494.                 if (result.resultObject.exception != null)
  495.                     throw result.resultObject.exception;
  496.                 else
  497.                     return result.resultObject.response;
  498.             }
  499.             else
  500.             {
  501.                 // deal with partial results
  502.                 s_partialResultsProcessor.NeedCompleteResult((LdapPartialAsyncResult)asyncResult);
  503.                 asyncResult.AsyncWaitHandle.WaitOne();
  504.  
  505.                 return s_partialResultsProcessor.GetCompleteResult((LdapPartialAsyncResult)asyncResult);
  506.             }
  507.         }
  508.  
  509.         private int SendRequestHelper(DirectoryRequest request, ref int messageID)
  510.         {
  511.             IntPtr serverControlArray = (IntPtr)0;
  512.             LdapControl[] managedServerControls = null;
  513.             IntPtr clientControlArray = (IntPtr)0;
  514.             LdapControl[] managedClientControls = null;
  515.  
  516.             string strValue = null;
  517.  
  518.             ArrayList ptrToFree = new ArrayList();
  519.             LdapMod[] modifications = null;
  520.             IntPtr modArray = (IntPtr)0;
  521.             int addModCount = 0;
  522.  
  523.             berval berValuePtr = null;
  524.  
  525.             IntPtr searchAttributes = (IntPtr)0;
  526.             DereferenceAlias searchAliases;
  527.             int attributeCount = 0;
  528.  
  529.             int error = 0;
  530.  
  531.             // connect to the server first if have not done so
  532.             if (!_connected)
  533.             {
  534.                 Connect();
  535.                 _connected = true;
  536.             }
  537.  
  538.             //do Bind if user has not turned off automatic bind, have not done so or there is a need to do rebind, also connectionless LDAP does not need to do bind
  539.             if (AutoBind && (!_bounded || _needRebind) && ((LdapDirectoryIdentifier)Directory).Connectionless != true)
  540.             {
  541.                 Debug.WriteLine("rebind occurs\n");
  542.                 Bind();
  543.             }
  544.  
  545.             try
  546.             {
  547.                 IntPtr controlPtr = (IntPtr)0;
  548.                 IntPtr tempPtr = (IntPtr)0;
  549.  
  550.                 // build server control
  551.                 managedServerControls = BuildControlArray(request.Controls, true);
  552.                 int structSize = Marshal.SizeOf(typeof(LdapControl));
  553.  
  554.                 if (managedServerControls != null)
  555.                 {
  556.                     serverControlArray = Utility.AllocHGlobalIntPtrArray(managedServerControls.Length + 1);
  557.                     for (int i = 0; i < managedServerControls.Length; i++)
  558.                     {
  559.                         controlPtr = Marshal.AllocHGlobal(structSize);
  560.                         Marshal.StructureToPtr(managedServerControls[i], controlPtr, false);
  561.                         tempPtr = (IntPtr)((long)serverControlArray + IntPtr.Size * i);
  562.                         Marshal.WriteIntPtr(tempPtr, controlPtr);
  563.                     }
  564.                     tempPtr = (IntPtr)((long)serverControlArray + IntPtr.Size * managedServerControls.Length);
  565.                     Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
  566.                 }
  567.  
  568.                 // build client control
  569.                 managedClientControls = BuildControlArray(request.Controls, false);
  570.                 if (managedClientControls != null)
  571.                 {
  572.                     clientControlArray = Utility.AllocHGlobalIntPtrArray(managedClientControls.Length + 1);
  573.                     for (int i = 0; i < managedClientControls.Length; i++)
  574.                     {
  575.                         controlPtr = Marshal.AllocHGlobal(structSize);
  576.                         Marshal.StructureToPtr(managedClientControls[i], controlPtr, false);
  577.                         tempPtr = (IntPtr)((long)clientControlArray + IntPtr.Size * i);
  578.                         Marshal.WriteIntPtr(tempPtr, controlPtr);
  579.                     }
  580.                     tempPtr = (IntPtr)((long)clientControlArray + IntPtr.Size * managedClientControls.Length);
  581.                     Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
  582.                 }
  583.  
  584.                 if (request is DeleteRequest)
  585.                 {
  586.                     // it is an delete operation                      
  587.                     error = Wldap32.ldap_delete_ext(ldapHandle, ((DeleteRequest)request).DistinguishedName, serverControlArray, clientControlArray, ref messageID);
  588.                 }
  589.                 else if (request is ModifyDNRequest)
  590.                 {
  591.                     // it is a modify dn operation
  592.                     error = Wldap32.ldap_rename(ldapHandle,
  593.                                                  ((ModifyDNRequest)request).DistinguishedName,
  594.                                                  ((ModifyDNRequest)request).NewName,
  595.                                                  ((ModifyDNRequest)request).NewParentDistinguishedName,
  596.                                                  ((ModifyDNRequest)request).DeleteOldRdn ? 1 : 0,
  597.                                                  serverControlArray, clientControlArray, ref messageID);
  598.                 }
  599.                 else if (request is CompareRequest)
  600.                 {
  601.                     // it is a compare request
  602.                     DirectoryAttribute assertion = ((CompareRequest)request).Assertion;
  603.                     if (assertion == null)
  604.                         throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.WrongAssertionCompare));
  605.  
  606.                     if (assertion.Count != 1)
  607.                         throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.WrongNumValuesCompare));
  608.  
  609.                     // process the attribute
  610.                     byte[] byteArray = assertion[0] as byte[];
  611.                     if (byteArray != null)
  612.                     {
  613.                         if (byteArray != null && byteArray.Length != 0)
  614.                         {
  615.                             berValuePtr = new berval();
  616.                             berValuePtr.bv_len = byteArray.Length;
  617.                             berValuePtr.bv_val = Marshal.AllocHGlobal(byteArray.Length);
  618.                             Marshal.Copy(byteArray, 0, berValuePtr.bv_val, byteArray.Length);
  619.                         }
  620.                     }
  621.                     else
  622.                     {
  623.                         strValue = assertion[0].ToString();
  624.                     }
  625.  
  626.                     // it is a compare request
  627.                     error = Wldap32.ldap_compare(ldapHandle,
  628.                                                   ((CompareRequest)request).DistinguishedName,
  629.                                                   assertion.Name,
  630.                                                   strValue,
  631.                                                   berValuePtr,
  632.                                                   serverControlArray, clientControlArray, ref messageID);
  633.                 }
  634.                 else if (request is AddRequest || request is ModifyRequest)
  635.                 {
  636.                     // build the attributes
  637.  
  638.                     if (request is AddRequest)
  639.                         modifications = BuildAttributes(((AddRequest)request).Attributes, ptrToFree);
  640.                     else
  641.                         modifications = BuildAttributes(((ModifyRequest)request).Modifications, ptrToFree);
  642.  
  643.                     addModCount = (modifications == null ? 1 : modifications.Length + 1);
  644.                     modArray = Utility.AllocHGlobalIntPtrArray(addModCount);
  645.                     int modStructSize = Marshal.SizeOf(typeof(LdapMod));
  646.                     int i = 0;
  647.                     for (i = 0; i < addModCount - 1; i++)
  648.                     {
  649.                         controlPtr = Marshal.AllocHGlobal(modStructSize);
  650.                         Marshal.StructureToPtr(modifications[i], controlPtr, false);
  651.                         tempPtr = (IntPtr)((long)modArray + IntPtr.Size * i);
  652.                         Marshal.WriteIntPtr(tempPtr, controlPtr);
  653.                     }
  654.                     tempPtr = (IntPtr)((long)modArray + IntPtr.Size * i);
  655.                     Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
  656.  
  657.                     if (request is AddRequest)
  658.                     {
  659.                         error = Wldap32.ldap_add(ldapHandle,
  660.                                                   ((AddRequest)request).DistinguishedName,
  661.                                                   modArray,
  662.                                                   serverControlArray, clientControlArray, ref messageID);
  663.                     }
  664.                     else
  665.                     {
  666.                         error = Wldap32.ldap_modify(ldapHandle,
  667.                                                      ((ModifyRequest)request).DistinguishedName,
  668.                                                      modArray,
  669.                                                      serverControlArray, clientControlArray, ref messageID);
  670.                     }
  671.                 }
  672.                 else if (request is ExtendedRequest)
  673.                 {
  674.                     string name = ((ExtendedRequest)request).RequestName;
  675.                     byte[] val = ((ExtendedRequest)request).RequestValue;
  676.  
  677.                     // process the requestvalue
  678.                     if (val != null && val.Length != 0)
  679.                     {
  680.                         berValuePtr = new berval();
  681.                         berValuePtr.bv_len = val.Length;
  682.                         berValuePtr.bv_val = Marshal.AllocHGlobal(val.Length);
  683.                         Marshal.Copy(val, 0, berValuePtr.bv_val, val.Length);
  684.                     }
  685.  
  686.                     error = Wldap32.ldap_extended_operation(ldapHandle,
  687.                                                             name,
  688.                                                             berValuePtr,
  689.                                                             serverControlArray, clientControlArray, ref messageID);
  690.                 }
  691.                 else if (request is SearchRequest)
  692.                 {
  693.                     // processing the filter
  694.                     SearchRequest searchRequest = (SearchRequest)request;
  695.                     object filter = searchRequest.Filter;
  696.                     if (filter != null)
  697.                     {
  698.                         // LdapConnection only supports ldap filter
  699.                         if (filter is XmlDocument)
  700.                             throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.InvalidLdapSearchRequestFilter));
  701.                     }
  702.                     string searchRequestFilter = (string)filter;
  703.  
  704.                     // processing the attributes
  705.                     attributeCount = (searchRequest.Attributes == null ? 0 : searchRequest.Attributes.Count);
  706.                     if (attributeCount != 0)
  707.                     {
  708.                         searchAttributes = Utility.AllocHGlobalIntPtrArray(attributeCount + 1);
  709.                         int i = 0;
  710.                         for (i = 0; i < attributeCount; i++)
  711.                         {
  712.                             controlPtr = Marshal.StringToHGlobalUni(searchRequest.Attributes[i]);
  713.                             tempPtr = (IntPtr)((long)searchAttributes + IntPtr.Size * i);
  714.                             Marshal.WriteIntPtr(tempPtr, controlPtr);
  715.                         }
  716.                         tempPtr = (IntPtr)((long)searchAttributes + IntPtr.Size * i);
  717.                         Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
  718.                     }
  719.  
  720.                     // processing the scope
  721.                     int searchScope = (int)searchRequest.Scope;
  722.  
  723.                     // processing the timelimit
  724.                     int searchTimeLimit = (int)(searchRequest.TimeLimit.Ticks / TimeSpan.TicksPerSecond);
  725.  
  726.                     // processing the alias                    
  727.                     searchAliases = _options.DerefAlias;
  728.                     _options.DerefAlias = searchRequest.Aliases;
  729.  
  730.                     try
  731.                     {
  732.                         error = Wldap32.ldap_search(ldapHandle,
  733.                                                      searchRequest.DistinguishedName,
  734.                                                      searchScope,
  735.                                                      searchRequestFilter,
  736.                                                      searchAttributes,
  737.                                                      searchRequest.TypesOnly,
  738.                                                      serverControlArray,
  739.                                                      clientControlArray,
  740.                                                      searchTimeLimit,
  741.                                                      searchRequest.SizeLimit,
  742.                                                      ref messageID);
  743.                     }
  744.                     finally
  745.                     {
  746.                         // revert back
  747.                         _options.DerefAlias = searchAliases;
  748.                     }
  749.                 }
  750.                 else
  751.                 {
  752.                     throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, SR.InvliadRequestType));
  753.                 }
  754.  
  755.                 // the asynchronous call itself timeout, this actually means that we time out the LDAP_OPT_SEND_TIMEOUT specified in the session option
  756.                 // wldap32 does not differentiate that, but the application caller actually needs this information to determin what to do with the error code
  757.                 if (error == (int)LdapError.TimeOut)
  758.                     error = (int)LdapError.SendTimeOut;
  759.  
  760.                 return error;
  761.             }
  762.             finally
  763.             {
  764.                 GC.KeepAlive(modifications);
  765.  
  766.                 if (serverControlArray != (IntPtr)0)
  767.                 {
  768.                     //release the memory from the heap
  769.                     for (int i = 0; i < managedServerControls.Length; i++)
  770.                     {
  771.                         IntPtr tempPtr = Marshal.ReadIntPtr(serverControlArray, IntPtr.Size * i);
  772.                         if (tempPtr != (IntPtr)0)
  773.                             Marshal.FreeHGlobal(tempPtr);
  774.                     }
  775.                     Marshal.FreeHGlobal(serverControlArray);
  776.                 }
  777.  
  778.                 if (managedServerControls != null)
  779.                 {
  780.                     for (int i = 0; i < managedServerControls.Length; i++)
  781.                     {
  782.                         if (managedServerControls[i].ldctl_oid != (IntPtr)0)
  783.                             Marshal.FreeHGlobal(managedServerControls[i].ldctl_oid);
  784.  
  785.                         if (managedServerControls[i].ldctl_value != null)
  786.                         {
  787.                             if (managedServerControls[i].ldctl_value.bv_val != (IntPtr)0)
  788.                                 Marshal.FreeHGlobal(managedServerControls[i].ldctl_value.bv_val);
  789.                         }
  790.                     }
  791.                 }
  792.  
  793.                 if (clientControlArray != (IntPtr)0)
  794.                 {
  795.                     // release the memory from the heap
  796.                     for (int i = 0; i < managedClientControls.Length; i++)
  797.                     {
  798.                         IntPtr tempPtr = Marshal.ReadIntPtr(clientControlArray, IntPtr.Size * i);
  799.                         if (tempPtr != (IntPtr)0)
  800.                             Marshal.FreeHGlobal(tempPtr);
  801.                     }
  802.                     Marshal.FreeHGlobal(clientControlArray);
  803.                 }
  804.  
  805.                 if (managedClientControls != null)
  806.                 {
  807.                     for (int i = 0; i < managedClientControls.Length; i++)
  808.                     {
  809.                         if (managedClientControls[i].ldctl_oid != (IntPtr)0)
  810.                             Marshal.FreeHGlobal(managedClientControls[i].ldctl_oid);
  811.  
  812.                         if (managedClientControls[i].ldctl_value != null)
  813.                         {
  814.                             if (managedClientControls[i].ldctl_value.bv_val != (IntPtr)0)
  815.                                 Marshal.FreeHGlobal(managedClientControls[i].ldctl_value.bv_val);
  816.                         }
  817.                     }
  818.                 }
  819.  
  820.                 if (modArray != (IntPtr)0)
  821.                 {
  822.                     // release the memory from the heap
  823.                     for (int i = 0; i < addModCount - 1; i++)
  824.                     {
  825.                         IntPtr tempPtr = Marshal.ReadIntPtr(modArray, IntPtr.Size * i);
  826.                         if (tempPtr != (IntPtr)0)
  827.                             Marshal.FreeHGlobal(tempPtr);
  828.                     }
  829.                     Marshal.FreeHGlobal(modArray);
  830.                 }
  831.  
  832.                 // free the pointers
  833.                 for (int x = 0; x < ptrToFree.Count; x++)
  834.                 {
  835.                     IntPtr tempPtr = (IntPtr)ptrToFree[x];
  836.                     Marshal.FreeHGlobal(tempPtr);
  837.                 }
  838.  
  839.                 if (berValuePtr != null)
  840.                 {
  841.                     if (berValuePtr.bv_val != (IntPtr)0)
  842.                         Marshal.FreeHGlobal(berValuePtr.bv_val);
  843.                 }
  844.  
  845.                 if (searchAttributes != (IntPtr)0)
  846.                 {
  847.                     for (int i = 0; i < attributeCount; i++)
  848.                     {
  849.                         IntPtr tempPtr = Marshal.ReadIntPtr(searchAttributes, IntPtr.Size * i);
  850.                         if (tempPtr != (IntPtr)0)
  851.                             Marshal.FreeHGlobal(tempPtr);
  852.                     }
  853.                     Marshal.FreeHGlobal(searchAttributes);
  854.                 }
  855.             }
  856.         }
  857.  
  858.         private bool ProcessClientCertificate(IntPtr ldapHandle, IntPtr CAs, ref IntPtr certificate)
  859.         {
  860.             ArrayList list = new ArrayList();
  861.             byte[][] certAuthorities = null;
  862.             int count = ClientCertificates == null ? 0 : ClientCertificates.Count;
  863.  
  864.             if (count == 0 && _options.clientCertificateDelegate == null)
  865.             {
  866.                 return false;
  867.             }
  868.  
  869.             // if user specify certificate through property and not though option, we don't need to check CA
  870.             if (_options.clientCertificateDelegate == null)
  871.             {
  872.                 certificate = ClientCertificates[0].Handle;
  873.                 return true;
  874.             }
  875.  
  876.             // processing the CA
  877.             if (CAs != (IntPtr)0)
  878.             {
  879.                 SecPkgContext_IssuerListInfoEx trustedCAs = (SecPkgContext_IssuerListInfoEx)Marshal.PtrToStructure(CAs, typeof(SecPkgContext_IssuerListInfoEx));
  880.                 int issuerNumber = trustedCAs.cIssuers;
  881.                 IntPtr tempPtr = (IntPtr)0;
  882.                 for (int i = 0; i < issuerNumber; i++)
  883.                 {
  884.                     tempPtr = (IntPtr)((long)trustedCAs.aIssuers + Marshal.SizeOf(typeof(CRYPTOAPI_BLOB)) * i);
  885.                     CRYPTOAPI_BLOB info = (CRYPTOAPI_BLOB)Marshal.PtrToStructure(tempPtr, typeof(CRYPTOAPI_BLOB));
  886.                     int dataLength = info.cbData;
  887.                     byte[] context = new byte[dataLength];
  888.                     Marshal.Copy(info.pbData, context, 0, dataLength);
  889.                     list.Add(context);
  890.                 }
  891.             }
  892.  
  893.             if (list.Count != 0)
  894.             {
  895.                 certAuthorities = new byte[list.Count][];
  896.                 for (int i = 0; i < list.Count; i++)
  897.                 {
  898.                     certAuthorities[i] = (byte[])list[i];
  899.                 }
  900.             }
  901.  
  902.             X509Certificate cert = _options.clientCertificateDelegate(this, certAuthorities);
  903.             if (cert != null)
  904.             {
  905.                 certificate = cert.Handle;
  906.                 return true;
  907.             }
  908.             else
  909.             {
  910.                 certificate = (IntPtr)0;
  911.                 return false;
  912.             }
  913.         }
  914.  
  915.         private void Connect()
  916.         {
  917.             int error = 0;
  918.             string errorMessage;
  919.  
  920.             // currently ldap does not accept more than one certificate, so check here
  921.             if (ClientCertificates.Count > 1)
  922.                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.InvalidClientCertificates));
  923.  
  924.             // set the certificate callback routine here if user adds the certifcate to the certificate collection
  925.             if (ClientCertificates.Count != 0)
  926.             {
  927.                 int certerror = Wldap32.ldap_set_option_clientcert(ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, clientCertificateRoutine);
  928.                 if (certerror != (int)ResultCode.Success)
  929.                 {
  930.                     if (Utility.IsLdapError((LdapError)certerror))
  931.                     {
  932.                         string certerrorMessage = LdapErrorMappings.MapResultCode(certerror);
  933.                         throw new LdapException(certerror, certerrorMessage);
  934.                     }
  935.                     else
  936.                         throw new LdapException(certerror);
  937.                 }
  938.                 // when certificate is specified, automatic bind is disabled
  939.                 automaticBind = false;
  940.             }
  941.  
  942.             // set the LDAP_OPT_AREC_EXCLUSIVE flag if necessary
  943.             if (((LdapDirectoryIdentifier)Directory).FullyQualifiedDnsHostName && !_setFQDNDone)
  944.             {
  945.                 SessionOptions.FQDN = true;
  946.                 _setFQDNDone = true;
  947.             }
  948.  
  949.             // connect explicitly to the server
  950.             LDAP_TIMEVAL timeout = new LDAP_TIMEVAL();
  951.             timeout.tv_sec = (int)(connectionTimeOut.Ticks / TimeSpan.TicksPerSecond);
  952.             Debug.Assert(!ldapHandle.IsInvalid);
  953.             error = Wldap32.ldap_connect(ldapHandle, timeout);
  954.             // failed, throw exception
  955.             if (error != (int)ResultCode.Success)
  956.             {
  957.                 if (Utility.IsLdapError((LdapError)error))
  958.                 {
  959.                     errorMessage = LdapErrorMappings.MapResultCode(error);
  960.                     throw new LdapException(error, errorMessage);
  961.                 }
  962.                 else
  963.                     throw new LdapException(error);
  964.             }
  965.         }
  966.  
  967.         public void Bind()
  968.         {
  969.             BindHelper(directoryCredential, false /* no need to reset credential */);
  970.         }
  971.  
  972.         public void Bind(NetworkCredential newCredential)
  973.         {
  974.             BindHelper(newCredential, true /* need to reset credential */);
  975.         }
  976.  
  977.         [
  978.             EnvironmentPermission(SecurityAction.Assert, Unrestricted = true),
  979.             SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)
  980.         ]
  981.         private void BindHelper(NetworkCredential newCredential, bool needSetCredential)
  982.         {
  983.             int error = 0;
  984.             string errorMessage;
  985.             string username;
  986.             string domainname;
  987.             string password;
  988.             NetworkCredential tempCredential = null;
  989.  
  990.             // if already disposed, we need to throw exception
  991.             if (this.disposed)
  992.                 throw new ObjectDisposedException(GetType().Name);
  993.  
  994.             // if user wants to do anonymous bind, but specifies credential, error out
  995.             if (AuthType == AuthType.Anonymous && (newCredential != null && ((newCredential.Password != null && newCredential.Password.Length != 0) || (newCredential.UserName != null && newCredential.UserName.Length != 0))))
  996.                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.InvalidAuthCredential));
  997.  
  998.             // set the credential
  999.             if (needSetCredential)
  1000.                 directoryCredential = tempCredential = (newCredential != null ? new NetworkCredential(newCredential.UserName, newCredential.Password, newCredential.Domain) : null);
  1001.             else
  1002.                 tempCredential = directoryCredential;
  1003.  
  1004.             // connect to the server first
  1005.             if (!_connected)
  1006.             {
  1007.                 Connect();
  1008.                 _connected = true;
  1009.             }
  1010.  
  1011.             // bind to the server
  1012.             if (tempCredential != null && tempCredential.UserName.Length == 0 && tempCredential.Password.Length == 0 && tempCredential.Domain.Length == 0)
  1013.             {
  1014.                 // default credential
  1015.                 username = null;
  1016.                 domainname = null;
  1017.                 password = null;
  1018.             }
  1019.             else
  1020.             {
  1021.                 username = (tempCredential == null) ? null : tempCredential.UserName;
  1022.                 domainname = (tempCredential == null) ? null : tempCredential.Domain;
  1023.                 password = (tempCredential == null) ? null : tempCredential.Password;
  1024.             }
  1025.  
  1026.             if (AuthType == AuthType.Anonymous)
  1027.                 error = Wldap32.ldap_simple_bind_s(ldapHandle, null, null);
  1028.             else if (AuthType == AuthType.Basic)
  1029.             {
  1030.                 StringBuilder tempdn = new StringBuilder(100);
  1031.                 if (domainname != null && domainname.Length != 0)
  1032.                 {
  1033.                     tempdn.Append(domainname);
  1034.                     tempdn.Append("\\");
  1035.                 }
  1036.                 tempdn.Append(username);
  1037.                 error = Wldap32.ldap_simple_bind_s(ldapHandle, tempdn.ToString(), password);
  1038.             }
  1039.             else
  1040.             {
  1041.                 SEC_WINNT_AUTH_IDENTITY_EX cred = new SEC_WINNT_AUTH_IDENTITY_EX();
  1042.                 cred.version = Wldap32.SEC_WINNT_AUTH_IDENTITY_VERSION;
  1043.                 cred.length = Marshal.SizeOf(typeof(SEC_WINNT_AUTH_IDENTITY_EX));
  1044.                 cred.flags = Wldap32.SEC_WINNT_AUTH_IDENTITY_UNICODE;
  1045.                 if (AuthType == AuthType.Kerberos)
  1046.                 {
  1047.                     cred.packageList = Wldap32.MICROSOFT_KERBEROS_NAME_W;
  1048.                     cred.packageListLength = cred.packageList.Length;
  1049.                 }
  1050.  
  1051.                 if (tempCredential != null)
  1052.                 {
  1053.                     cred.user = username;
  1054.                     cred.userLength = (username == null ? 0 : username.Length);
  1055.                     cred.domain = domainname;
  1056.                     cred.domainLength = (domainname == null ? 0 : domainname.Length);
  1057.                     cred.password = password;
  1058.                     cred.passwordLength = (password == null ? 0 : password.Length);
  1059.                 }
  1060.  
  1061.                 BindMethod method = BindMethod.LDAP_AUTH_NEGOTIATE;
  1062.                 switch (AuthType)
  1063.                 {
  1064.                     case AuthType.Negotiate:
  1065.                         method = BindMethod.LDAP_AUTH_NEGOTIATE;
  1066.                         break;
  1067.                     case AuthType.Kerberos:
  1068.                         method = BindMethod.LDAP_AUTH_NEGOTIATE;
  1069.                         break;
  1070.                     case AuthType.Ntlm:
  1071.                         method = BindMethod.LDAP_AUTH_NTLM;
  1072.                         break;
  1073.                     case AuthType.Digest:
  1074.                         method = BindMethod.LDAP_AUTH_DIGEST;
  1075.                         break;
  1076.                     case AuthType.Sicily:
  1077.                         method = BindMethod.LDAP_AUTH_SICILY;
  1078.                         break;
  1079.                     case AuthType.Dpa:
  1080.                         method = BindMethod.LDAP_AUTH_DPA;
  1081.                         break;
  1082.                     case AuthType.Msn:
  1083.                         method = BindMethod.LDAP_AUTH_MSN;
  1084.                         break;
  1085.                     case AuthType.External:
  1086.                         method = BindMethod.LDAP_AUTH_EXTERNAL;
  1087.                         break;
  1088.                 }
  1089.  
  1090.                 if ((tempCredential == null) && (AuthType == AuthType.External))
  1091.                 {
  1092.                     error = Wldap32.ldap_bind_s(ldapHandle, null, null, method);
  1093.                 }
  1094.                 else
  1095.                 {
  1096.                     error = Wldap32.ldap_bind_s(ldapHandle, null, cred, method);
  1097.                 }
  1098.             }
  1099.  
  1100.             // failed, throw exception
  1101.             if (error != (int)ResultCode.Success)
  1102.             {
  1103.                 if (Utility.IsResultCode((ResultCode)error))
  1104.                 {
  1105.                     errorMessage = OperationErrorMappings.MapResultCode(error);
  1106.                     throw new DirectoryOperationException(null, errorMessage);
  1107.                 }
  1108.                 else if (Utility.IsLdapError((LdapError)error))
  1109.                 {
  1110.                     errorMessage = LdapErrorMappings.MapResultCode(error);
  1111.                     string serverErrorMessage = _options.ServerErrorMessage;
  1112.                     if ((serverErrorMessage != null) && (serverErrorMessage.Length > 0))
  1113.                     {
  1114.                         throw new LdapException(error, errorMessage, serverErrorMessage);
  1115.                     }
  1116.                     else
  1117.                     {
  1118.                         throw new LdapException(error, errorMessage);
  1119.                     }
  1120.                 }
  1121.                 else
  1122.                     throw new LdapException(error);
  1123.             }
  1124.  
  1125.             // we successfully bind to the server
  1126.             _bounded = true;
  1127.             // rebind has been done
  1128.             _needRebind = false;
  1129.         }
  1130.  
  1131.         public void Dispose()
  1132.         {
  1133.             Dispose(true);
  1134.             GC.SuppressFinalize(this);
  1135.         }
  1136.  
  1137.         protected virtual void Dispose(bool disposing)
  1138.         {
  1139.             if (disposing)
  1140.             {
  1141.                 // free other state (managed objects)                
  1142.  
  1143.                 // we need to remove the handle from the handle table
  1144.                 lock (objectLock)
  1145.                 {
  1146.                     if (null != ldapHandle)
  1147.                     {
  1148.                         handleTable.Remove(ldapHandle.DangerousGetHandle());
  1149.                     }
  1150.                 }
  1151.             }
  1152.             // free your own state (unmanaged objects)                     
  1153.  
  1154.             // close the ldap connection
  1155.             if (needDispose && ldapHandle != null && !ldapHandle.IsInvalid)
  1156.                 ldapHandle.Dispose();
  1157.             ldapHandle = null;
  1158.  
  1159.             disposed = true;
  1160.  
  1161.             Debug.WriteLine("Connection object is disposed\n");
  1162.         }
  1163.  
  1164.         internal LdapControl[] BuildControlArray(DirectoryControlCollection controls, bool serverControl)
  1165.         {
  1166.             int count = 0;
  1167.             LdapControl[] managedControls = null;
  1168.  
  1169.             if (controls != null && controls.Count != 0)
  1170.             {
  1171.                 ArrayList controlList = new ArrayList();
  1172.                 foreach (DirectoryControl col in controls)
  1173.                 {
  1174.                     if (serverControl == true)
  1175.                     {
  1176.                         if (col.ServerSide)
  1177.                             controlList.Add(col);
  1178.                     }
  1179.                     else
  1180.                     {
  1181.                         if (!col.ServerSide)
  1182.                             controlList.Add(col);
  1183.                     }
  1184.                 }
  1185.                 if (controlList.Count != 0)
  1186.                 {
  1187.                     count = controlList.Count;
  1188.  
  1189.                     managedControls = new LdapControl[count];
  1190.  
  1191.                     for (int i = 0; i < count; i++)
  1192.                     {
  1193.                         managedControls[i] = new LdapControl();
  1194.                         // get the control type
  1195.                         managedControls[i].ldctl_oid = Marshal.StringToHGlobalUni(((DirectoryControl)controlList[i]).Type);
  1196.                         //get the control cricality
  1197.                         managedControls[i].ldctl_iscritical = ((DirectoryControl)controlList[i]).IsCritical;
  1198.                         // get the control value
  1199.                         DirectoryControl tempControl = (DirectoryControl)controlList[i];
  1200.                         byte[] byteControlValue = tempControl.GetValue();
  1201.                         if (byteControlValue == null || byteControlValue.Length == 0)
  1202.                         {
  1203.                             // treat the control value as null
  1204.                             managedControls[i].ldctl_value = new berval();
  1205.                             managedControls[i].ldctl_value.bv_len = 0;
  1206.                             managedControls[i].ldctl_value.bv_val = (IntPtr)0;
  1207.                         }
  1208.                         else
  1209.                         {
  1210.                             managedControls[i].ldctl_value = new berval();
  1211.                             managedControls[i].ldctl_value.bv_len = byteControlValue.Length;
  1212.                             managedControls[i].ldctl_value.bv_val = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(byte)) * managedControls[i].ldctl_value.bv_len);
  1213.                             Marshal.Copy(byteControlValue, 0, managedControls[i].ldctl_value.bv_val, managedControls[i].ldctl_value.bv_len);
  1214.                         }
  1215.                     }
  1216.                 }
  1217.             }
  1218.  
  1219.             return managedControls;
  1220.         }
  1221.  
  1222.         internal LdapMod[] BuildAttributes(CollectionBase directoryAttributes, ArrayList ptrToFree)
  1223.         {
  1224.             LdapMod[] attributes = null;
  1225.             UTF8Encoding encoder = new UTF8Encoding();
  1226.             DirectoryAttributeCollection attributeCollection = null;
  1227.             DirectoryAttributeModificationCollection modificationCollection = null;
  1228.             DirectoryAttribute modAttribute = null;
  1229.  
  1230.             if (directoryAttributes != null && directoryAttributes.Count != 0)
  1231.             {
  1232.                 if (directoryAttributes is DirectoryAttributeModificationCollection)
  1233.                 {
  1234.                     modificationCollection = (DirectoryAttributeModificationCollection)directoryAttributes;
  1235.                 }
  1236.                 else
  1237.                 {
  1238.                     attributeCollection = (DirectoryAttributeCollection)directoryAttributes;
  1239.                 }
  1240.  
  1241.                 attributes = new LdapMod[directoryAttributes.Count];
  1242.                 for (int i = 0; i < directoryAttributes.Count; i++)
  1243.                 {
  1244.                     // get the managed attribute first
  1245.                     if (attributeCollection != null)
  1246.                         modAttribute = attributeCollection[i];
  1247.                     else
  1248.                         modAttribute = modificationCollection[i];
  1249.  
  1250.                     attributes[i] = new LdapMod();
  1251.  
  1252.                     // operation type
  1253.                     if (modAttribute is DirectoryAttributeModification)
  1254.                     {
  1255.                         attributes[i].type = (int)((DirectoryAttributeModification)modAttribute).Operation;
  1256.                     }
  1257.                     else
  1258.                     {
  1259.                         attributes[i].type = (int)DirectoryAttributeOperation.Add;
  1260.                     }
  1261.                     // we treat all the values as binary
  1262.                     attributes[i].type |= (int)LDAP_MOD_BVALUES;
  1263.  
  1264.                     //attribute name
  1265.                     attributes[i].attribute = Marshal.StringToHGlobalUni(modAttribute.Name);
  1266.  
  1267.                     // values
  1268.                     int valuesCount = 0;
  1269.                     berval[] berValues = null;
  1270.                     if (modAttribute.Count > 0)
  1271.                     {
  1272.                         valuesCount = modAttribute.Count;
  1273.                         berValues = new berval[valuesCount];
  1274.                         for (int j = 0; j < valuesCount; j++)
  1275.                         {
  1276.                             byte[] byteArray = null;
  1277.                             if (modAttribute[j] is string)
  1278.                                 byteArray = encoder.GetBytes((string)modAttribute[j]);
  1279.                             else if (modAttribute[j] is Uri)
  1280.                                 byteArray = encoder.GetBytes(((Uri)modAttribute[j]).ToString());
  1281.                             else
  1282.                                 byteArray = (byte[])modAttribute[j];
  1283.  
  1284.                             berValues[j] = new berval();
  1285.                             berValues[j].bv_len = byteArray.Length;
  1286.                             berValues[j].bv_val = Marshal.AllocHGlobal(berValues[j].bv_len);
  1287.                             // need to free the memory allocated on the heap when we are done
  1288.                             ptrToFree.Add(berValues[j].bv_val);
  1289.                             Marshal.Copy(byteArray, 0, berValues[j].bv_val, berValues[j].bv_len);
  1290.                         }
  1291.                     }
  1292.  
  1293.                     attributes[i].values = Utility.AllocHGlobalIntPtrArray(valuesCount + 1);
  1294.                     int structSize = Marshal.SizeOf(typeof(berval));
  1295.                     IntPtr controlPtr = (IntPtr)0;
  1296.                     IntPtr tempPtr = (IntPtr)0;
  1297.                     int m = 0;
  1298.                     for (m = 0; m < valuesCount; m++)
  1299.                     {
  1300.                         controlPtr = Marshal.AllocHGlobal(structSize);
  1301.                         // need to free the memory allocated on the heap when we are done
  1302.                         ptrToFree.Add(controlPtr);
  1303.                         Marshal.StructureToPtr(berValues[m], controlPtr, false);
  1304.                         tempPtr = (IntPtr)((long)attributes[i].values + IntPtr.Size * m);
  1305.                         Marshal.WriteIntPtr(tempPtr, controlPtr);
  1306.                     }
  1307.                     tempPtr = (IntPtr)((long)attributes[i].values + IntPtr.Size * m);
  1308.                     Marshal.WriteIntPtr(tempPtr, (IntPtr)0);
  1309.                 }
  1310.             }
  1311.  
  1312.             return attributes;
  1313.         }
  1314.  
  1315.         internal DirectoryResponse ConstructResponse(int messageId, LdapOperation operation, ResultAll resultType, TimeSpan requestTimeOut, bool exceptionOnTimeOut)
  1316.         {
  1317.             int error;
  1318.             LDAP_TIMEVAL timeout = new LDAP_TIMEVAL();
  1319.             timeout.tv_sec = (int)(requestTimeOut.Ticks / TimeSpan.TicksPerSecond);
  1320.             IntPtr ldapResult = (IntPtr)0;
  1321.             DirectoryResponse response = null;
  1322.  
  1323.             IntPtr requestName = (IntPtr)0;
  1324.             IntPtr requestValue = (IntPtr)0;
  1325.  
  1326.             IntPtr entryMessage = (IntPtr)0;
  1327.  
  1328.             bool needAbandon = true;
  1329.  
  1330.             // processing for the partial results retrieval
  1331.             if (resultType != ResultAll.LDAP_MSG_ALL)
  1332.             {
  1333.                 // we need to have 0 timeout as we are polling for the results and don't want to wait
  1334.                 timeout.tv_sec = 0;
  1335.                 timeout.tv_usec = 0;
  1336.  
  1337.                 if (resultType == ResultAll.LDAP_MSG_POLLINGALL)
  1338.                     resultType = ResultAll.LDAP_MSG_ALL;
  1339.  
  1340.                 // when doing partial results retrieving, if ldap_result failed, we don't do ldap_abandon here.
  1341.                 needAbandon = false;
  1342.             }
  1343.  
  1344.             error = Wldap32.ldap_result(ldapHandle, messageId, (int)resultType, timeout, ref ldapResult);
  1345.             if (error != -1 && error != 0)
  1346.             {
  1347.                 // parsing the result
  1348.                 int serverError = 0;
  1349.                 try
  1350.                 {
  1351.                     int resulterror = 0;
  1352.                     string responseDn = null;
  1353.                     string responseMessage = null;
  1354.                     Uri[] responseReferral = null;
  1355.                     DirectoryControl[] responseControl = null;
  1356.  
  1357.                     // ldap_parse_result skips over messages of type LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_REFERRAL
  1358.                     if (error != (int)LdapResult.LDAP_RES_SEARCH_ENTRY && error != (int)LdapResult.LDAP_RES_REFERRAL)
  1359.                         resulterror = ConstructParsedResult(ldapResult, ref serverError, ref responseDn, ref responseMessage, ref responseReferral, ref responseControl);
  1360.  
  1361.                     if (resulterror == 0)
  1362.                     {
  1363.                         resulterror = serverError;
  1364.  
  1365.                         if (error == (int)LdapResult.LDAP_RES_ADD)
  1366.                             response = new AddResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
  1367.                         else if (error == (int)LdapResult.LDAP_RES_MODIFY)
  1368.                             response = new ModifyResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
  1369.                         else if (error == (int)LdapResult.LDAP_RES_DELETE)
  1370.                             response = new DeleteResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
  1371.                         else if (error == (int)LdapResult.LDAP_RES_MODRDN)
  1372.                             response = new ModifyDNResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
  1373.                         else if (error == (int)LdapResult.LDAP_RES_COMPARE)
  1374.                             response = new CompareResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
  1375.                         else if (error == (int)LdapResult.LDAP_RES_EXTENDED)
  1376.                         {
  1377.                             response = new ExtendedResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
  1378.                             if (resulterror == (int)ResultCode.Success)
  1379.                             {
  1380.                                 resulterror = Wldap32.ldap_parse_extended_result(ldapHandle, ldapResult, ref requestName, ref requestValue, 0 /*not free it*/);
  1381.                                 if (resulterror == 0)
  1382.                                 {
  1383.                                     string name = null;
  1384.                                     if (requestName != (IntPtr)0)
  1385.                                     {
  1386.                                         name = Marshal.PtrToStringUni(requestName);
  1387.                                     }
  1388.  
  1389.                                     berval val = null;
  1390.                                     byte[] requestValueArray = null;
  1391.                                     if (requestValue != (IntPtr)0)
  1392.                                     {
  1393.                                         val = new berval();
  1394.                                         Marshal.PtrToStructure(requestValue, val);
  1395.                                         if (val.bv_len != 0 && val.bv_val != (IntPtr)0)
  1396.                                         {
  1397.                                             requestValueArray = new byte[val.bv_len];
  1398.                                             Marshal.Copy(val.bv_val, requestValueArray, 0, val.bv_len);
  1399.                                         }
  1400.                                     }
  1401.  
  1402.                                     ((ExtendedResponse)response).name = name;
  1403.                                     ((ExtendedResponse)response).value = requestValueArray;
  1404.                                 }
  1405.                             }
  1406.                         }
  1407.                         else if (error == (int)LdapResult.LDAP_RES_SEARCH_RESULT ||
  1408.                                error == (int)LdapResult.LDAP_RES_SEARCH_ENTRY ||
  1409.                                error == (int)LdapResult.LDAP_RES_REFERRAL)
  1410.                         {
  1411.                             response = new SearchResponse(responseDn, responseControl, (ResultCode)resulterror, responseMessage, responseReferral);
  1412.  
  1413.                             //set the flag here so our partial result processor knows whether the search is done or not
  1414.                             if (error == (int)LdapResult.LDAP_RES_SEARCH_RESULT)
  1415.                             {
  1416.                                 ((SearchResponse)response).searchDone = true;
  1417.                             }
  1418.  
  1419.                             SearchResultEntryCollection searchResultEntries = new SearchResultEntryCollection();
  1420.                             SearchResultReferenceCollection searchResultReferences = new SearchResultReferenceCollection();
  1421.  
  1422.                             // parsing the resultentry
  1423.                             entryMessage = Wldap32.ldap_first_entry(ldapHandle, ldapResult);
  1424.  
  1425.                             int entrycount = 0;
  1426.                             while (entryMessage != (IntPtr)0)
  1427.                             {
  1428.                                 SearchResultEntry entry = ConstructEntry(entryMessage);
  1429.                                 if (entry != null)
  1430.                                     searchResultEntries.Add(entry);
  1431.  
  1432.                                 entrycount++;
  1433.                                 entryMessage = Wldap32.ldap_next_entry(ldapHandle, entryMessage);
  1434.                             }
  1435.  
  1436.                             // parsing the reference
  1437.                             IntPtr referenceMessage = Wldap32.ldap_first_reference(ldapHandle, ldapResult);
  1438.  
  1439.                             while (referenceMessage != (IntPtr)0)
  1440.                             {
  1441.                                 SearchResultReference reference = ConstructReference(referenceMessage);
  1442.                                 if (reference != null)
  1443.                                     searchResultReferences.Add(reference);
  1444.  
  1445.                                 referenceMessage = Wldap32.ldap_next_reference(ldapHandle, referenceMessage);
  1446.                             }
  1447.  
  1448.                             ((SearchResponse)response).SetEntries(searchResultEntries);
  1449.                             ((SearchResponse)response).SetReferences(searchResultReferences);
  1450.                         }
  1451.  
  1452.                         if (resulterror != (int)ResultCode.Success && resulterror != (int)ResultCode.CompareFalse && resulterror != (int)ResultCode.CompareTrue && resulterror != (int)ResultCode.Referral && resulterror != (int)ResultCode.ReferralV2)
  1453.                         {
  1454.                             // throw operation exception                  
  1455.                             if (Utility.IsResultCode((ResultCode)resulterror))
  1456.                             {
  1457.                                 throw new DirectoryOperationException(response, OperationErrorMappings.MapResultCode(resulterror));
  1458.                             }
  1459.                             else
  1460.                                 // should not occur
  1461.                                 throw new DirectoryOperationException(response);
  1462.                         }
  1463.  
  1464.                         return response;
  1465.                     }
  1466.                     else
  1467.                     {
  1468.                         // fall over, throw the exception beow
  1469.                         error = resulterror;
  1470.                     }
  1471.                 }
  1472.                 finally
  1473.                 {
  1474.                     if (requestName != (IntPtr)0)
  1475.                         Wldap32.ldap_memfree(requestName);
  1476.  
  1477.                     if (requestValue != (IntPtr)0)
  1478.                         Wldap32.ldap_memfree(requestValue);
  1479.  
  1480.                     if (ldapResult != (IntPtr)0)
  1481.                     {
  1482.                         Wldap32.ldap_msgfree(ldapResult);
  1483.                     }
  1484.                 }
  1485.             }
  1486.             else
  1487.             {
  1488.                 // ldap_result failed
  1489.                 if (error == 0)
  1490.                 {
  1491.                     if (exceptionOnTimeOut)
  1492.                     {
  1493.                         // client side timeout                        
  1494.                         error = (int)LdapError.TimeOut;
  1495.                     }
  1496.                     else
  1497.                     {
  1498.                         // if we don't throw exception on time out (notification search for example), we just return empty resposne
  1499.                         return null;
  1500.                     }
  1501.                 }
  1502.                 else
  1503.                 {
  1504.                     error = Wldap32.LdapGetLastError();
  1505.                 }
  1506.  
  1507.                 // abandon the request
  1508.                 if (needAbandon)
  1509.                     Wldap32.ldap_abandon(ldapHandle, messageId);
  1510.             }
  1511.  
  1512.             // throw proper exception here            
  1513.             throw ConstructException(error, operation);
  1514.         }
  1515.  
  1516.         internal unsafe int ConstructParsedResult(IntPtr ldapResult, ref int serverError, ref string responseDn, ref string responseMessage, ref Uri[] responseReferral, ref DirectoryControl[] responseControl)
  1517.         {
  1518.             IntPtr dn = (IntPtr)0;
  1519.             IntPtr message = (IntPtr)0;
  1520.             IntPtr referral = (IntPtr)0;
  1521.             IntPtr control = (IntPtr)0;
  1522.             int resulterror = 0;
  1523.  
  1524.             try
  1525.             {
  1526.                 resulterror = Wldap32.ldap_parse_result(ldapHandle, ldapResult, ref serverError, ref dn, ref message, ref referral, ref control, 0 /* not free it */);
  1527.  
  1528.                 if (resulterror == 0)
  1529.                 {
  1530.                     // parsing dn
  1531.                     responseDn = Marshal.PtrToStringUni(dn);
  1532.  
  1533.                     // parsing message
  1534.                     responseMessage = Marshal.PtrToStringUni(message);
  1535.  
  1536.                     // parsing referral                    
  1537.                     if (referral != (IntPtr)0)
  1538.                     {
  1539.                         char** tempPtr = (char**)referral;
  1540.                         char* singleReferral = tempPtr[0];
  1541.                         int i = 0;
  1542.                         ArrayList referralList = new ArrayList();
  1543.                         while (singleReferral != null)
  1544.                         {
  1545.                             string s = Marshal.PtrToStringUni((IntPtr)singleReferral);
  1546.                             referralList.Add(s);
  1547.  
  1548.                             i++;
  1549.                             singleReferral = tempPtr[i];
  1550.                         }
  1551.  
  1552.                         if (referralList.Count > 0)
  1553.                         {
  1554.                             responseReferral = new Uri[referralList.Count];
  1555.                             for (int j = 0; j < referralList.Count; j++)
  1556.                                 responseReferral[j] = new Uri((string)referralList[j]);
  1557.                         }
  1558.                     }
  1559.  
  1560.                     // parsing control                                                
  1561.                     if (control != (IntPtr)0)
  1562.                     {
  1563.                         int i = 0;
  1564.                         IntPtr tempControlPtr = control;
  1565.                         IntPtr singleControl = Marshal.ReadIntPtr(tempControlPtr, 0);
  1566.                         ArrayList controlList = new ArrayList();
  1567.                         while (singleControl != (IntPtr)0)
  1568.                         {
  1569.                             DirectoryControl directoryControl = ConstructControl(singleControl);
  1570.                             controlList.Add(directoryControl);
  1571.  
  1572.                             i++;
  1573.                             singleControl = Marshal.ReadIntPtr(tempControlPtr, i * IntPtr.Size);
  1574.                         }
  1575.  
  1576.                         responseControl = new DirectoryControl[controlList.Count];
  1577.                         controlList.CopyTo(responseControl);
  1578.                     }
  1579.                 }
  1580.                 else
  1581.                 {
  1582.                     // we need to take care of one special case, when can't connect to the server, ldap_parse_result fails with local error
  1583.                     if (resulterror == (int)LdapError.LocalError)
  1584.                     {
  1585.                         int tmpResult = Wldap32.ldap_result2error(ldapHandle, ldapResult, 0 /* not free it */);
  1586.                         if (tmpResult != 0)
  1587.                         {
  1588.                             resulterror = tmpResult;
  1589.                         }
  1590.                     }
  1591.                 }
  1592.             }
  1593.             finally
  1594.             {
  1595.                 if (dn != (IntPtr)0)
  1596.                 {
  1597.                     Wldap32.ldap_memfree(dn);
  1598.                 }
  1599.  
  1600.                 if (message != (IntPtr)0)
  1601.                     Wldap32.ldap_memfree(message);
  1602.  
  1603.                 if (referral != (IntPtr)0)
  1604.                     Wldap32.ldap_value_free(referral);
  1605.  
  1606.                 if (control != (IntPtr)0)
  1607.                     Wldap32.ldap_controls_free(control);
  1608.             }
  1609.  
  1610.             return resulterror;
  1611.         }
  1612.  
  1613.         internal SearchResultEntry ConstructEntry(IntPtr entryMessage)
  1614.         {
  1615.             IntPtr dn = (IntPtr)0;
  1616.             string entryDn = null;
  1617.             IntPtr attribute = (IntPtr)0;
  1618.             IntPtr address = (IntPtr)0;
  1619.             SearchResultAttributeCollection attributes = null;
  1620.  
  1621.             try
  1622.             {
  1623.                 // get the dn
  1624.                 dn = Wldap32.ldap_get_dn(ldapHandle, entryMessage);
  1625.                 if (dn != (IntPtr)0)
  1626.                 {
  1627.                     entryDn = Marshal.PtrToStringUni(dn);
  1628.                     Wldap32.ldap_memfree(dn);
  1629.                     dn = (IntPtr)0;
  1630.                 }
  1631.  
  1632.                 SearchResultEntry resultEntry = new SearchResultEntry(entryDn);
  1633.                 attributes = resultEntry.Attributes;
  1634.  
  1635.                 // get attributes                
  1636.                 attribute = Wldap32.ldap_first_attribute(ldapHandle, entryMessage, ref address);
  1637.  
  1638.                 int tempcount = 0;
  1639.                 while (attribute != (IntPtr)0)
  1640.                 {
  1641.                     DirectoryAttribute attr = ConstructAttribute(entryMessage, attribute);
  1642.                     attributes.Add(attr.Name, attr);
  1643.  
  1644.                     Wldap32.ldap_memfree(attribute);
  1645.                     tempcount++;
  1646.                     attribute = Wldap32.ldap_next_attribute(ldapHandle, entryMessage, address);
  1647.                 }
  1648.  
  1649.                 if (address != (IntPtr)0)
  1650.                 {
  1651.                     Wldap32.ber_free(address, 0);
  1652.                     address = (IntPtr)0;
  1653.                 }
  1654.  
  1655.                 return resultEntry;
  1656.             }
  1657.             finally
  1658.             {
  1659.                 if (dn != (IntPtr)0)
  1660.                 {
  1661.                     Wldap32.ldap_memfree(dn);
  1662.                 }
  1663.  
  1664.                 if (attribute != (IntPtr)0)
  1665.                     Wldap32.ldap_memfree(attribute);
  1666.  
  1667.                 if (address != (IntPtr)0)
  1668.                 {
  1669.                     Wldap32.ber_free(address, 0);
  1670.                 }
  1671.             }
  1672.         }
  1673.  
  1674.         internal DirectoryAttribute ConstructAttribute(IntPtr entryMessage, IntPtr attributeName)
  1675.         {
  1676.             DirectoryAttribute attribute = new DirectoryAttribute();
  1677.             attribute.isSearchResult = true;
  1678.  
  1679.             // get name
  1680.             string name = Marshal.PtrToStringUni(attributeName);
  1681.             attribute.Name = name;
  1682.  
  1683.             // get values
  1684.             IntPtr valuesArray = Wldap32.ldap_get_values_len(ldapHandle, entryMessage, name);
  1685.             try
  1686.             {
  1687.                 IntPtr tempPtr = (IntPtr)0;
  1688.                 int count = 0;
  1689.                 if (valuesArray != (IntPtr)0)
  1690.                 {
  1691.                     tempPtr = Marshal.ReadIntPtr(valuesArray, IntPtr.Size * count);
  1692.                     while (tempPtr != (IntPtr)0)
  1693.                     {
  1694.                         berval bervalue = new berval();
  1695.                         Marshal.PtrToStructure(tempPtr, bervalue);
  1696.                         byte[] byteArray = null;
  1697.                         if (bervalue.bv_len > 0 && bervalue.bv_val != (IntPtr)0)
  1698.                         {
  1699.                             byteArray = new byte[bervalue.bv_len];
  1700.                             Marshal.Copy(bervalue.bv_val, byteArray, 0, bervalue.bv_len);
  1701.                             attribute.Add(byteArray);
  1702.                         }
  1703.  
  1704.                         count++;
  1705.                         tempPtr = Marshal.ReadIntPtr(valuesArray, IntPtr.Size * count);
  1706.                     }
  1707.                 }
  1708.             }
  1709.             finally
  1710.             {
  1711.                 if (valuesArray != (IntPtr)0)
  1712.                     Wldap32.ldap_value_free_len(valuesArray);
  1713.             }
  1714.  
  1715.             return attribute;
  1716.         }
  1717.  
  1718.         internal SearchResultReference ConstructReference(IntPtr referenceMessage)
  1719.         {
  1720.             SearchResultReference reference = null;
  1721.             ArrayList referralList = new ArrayList();
  1722.             Uri[] uris = null;
  1723.             IntPtr referenceArray = (IntPtr)0;
  1724.  
  1725.             int error = Wldap32.ldap_parse_reference(ldapHandle, referenceMessage, ref referenceArray);
  1726.  
  1727.             try
  1728.             {
  1729.                 if (error == 0)
  1730.                 {
  1731.                     IntPtr tempPtr = (IntPtr)0;
  1732.                     int count = 0;
  1733.                     if (referenceArray != (IntPtr)0)
  1734.                     {
  1735.                         tempPtr = Marshal.ReadIntPtr(referenceArray, IntPtr.Size * count);
  1736.                         while (tempPtr != (IntPtr)0)
  1737.                         {
  1738.                             string s = Marshal.PtrToStringUni(tempPtr);
  1739.                             referralList.Add(s);
  1740.  
  1741.                             count++;
  1742.                             tempPtr = Marshal.ReadIntPtr(referenceArray, IntPtr.Size * count);
  1743.                         }
  1744.  
  1745.                         Wldap32.ldap_value_free(referenceArray);
  1746.                         referenceArray = (IntPtr)0;
  1747.                     }
  1748.  
  1749.                     if (referralList.Count > 0)
  1750.                     {
  1751.                         uris = new Uri[referralList.Count];
  1752.                         for (int i = 0; i < referralList.Count; i++)
  1753.                         {
  1754.                             uris[i] = new Uri((string)referralList[i]);
  1755.                         }
  1756.  
  1757.                         reference = new SearchResultReference(uris);
  1758.                     }
  1759.                 }
  1760.             }
  1761.             finally
  1762.             {
  1763.                 if (referenceArray != (IntPtr)0)
  1764.                     Wldap32.ldap_value_free(referenceArray);
  1765.             }
  1766.  
  1767.             return reference;
  1768.         }
  1769.  
  1770.         private DirectoryException ConstructException(int error, LdapOperation operation)
  1771.         {
  1772.             DirectoryResponse response = null;
  1773.  
  1774.             if (Utility.IsResultCode((ResultCode)error))
  1775.             {
  1776.                 if (operation == LdapOperation.LdapAdd)
  1777.                     response = new AddResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
  1778.                 else if (operation == LdapOperation.LdapModify)
  1779.                     response = new ModifyResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
  1780.                 else if (operation == LdapOperation.LdapDelete)
  1781.                     response = new DeleteResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
  1782.                 else if (operation == LdapOperation.LdapModifyDn)
  1783.                     response = new ModifyDNResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
  1784.                 else if (operation == LdapOperation.LdapCompare)
  1785.                     response = new CompareResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
  1786.                 else if (operation == LdapOperation.LdapSearch)
  1787.                     response = new SearchResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
  1788.                 else if (operation == LdapOperation.LdapExtendedRequest)
  1789.                     response = new ExtendedResponse(null, null, (ResultCode)error, OperationErrorMappings.MapResultCode(error), null);
  1790.  
  1791.                 string errorMessage = OperationErrorMappings.MapResultCode(error);
  1792.                 return new DirectoryOperationException(response, errorMessage);
  1793.             }
  1794.             else
  1795.             {
  1796.                 if (Utility.IsLdapError((LdapError)error))
  1797.                 {
  1798.                     string errorMessage = LdapErrorMappings.MapResultCode(error);
  1799.                     string serverErrorMessage = _options.ServerErrorMessage;
  1800.                     if ((serverErrorMessage != null) && (serverErrorMessage.Length > 0))
  1801.                     {
  1802.                         throw new LdapException(error, errorMessage, serverErrorMessage);
  1803.                     }
  1804.                     else
  1805.                     {
  1806.                         return new LdapException(error, errorMessage);
  1807.                     }
  1808.                 }
  1809.                 else
  1810.                     return new LdapException(error);
  1811.             }
  1812.         }
  1813.  
  1814.         private DirectoryControl ConstructControl(IntPtr controlPtr)
  1815.         {
  1816.             LdapControl control = new LdapControl();
  1817.             Marshal.PtrToStructure(controlPtr, control);
  1818.  
  1819.             Debug.Assert(control.ldctl_oid != (IntPtr)0);
  1820.             string controlType = Marshal.PtrToStringUni(control.ldctl_oid);
  1821.  
  1822.             byte[] bytes = new byte[control.ldctl_value.bv_len];
  1823.             Marshal.Copy(control.ldctl_value.bv_val, bytes, 0, control.ldctl_value.bv_len);
  1824.  
  1825.             bool criticality = control.ldctl_iscritical;
  1826.  
  1827.             return new DirectoryControl(controlType, bytes, criticality, true);
  1828.         }
  1829.  
  1830.         private bool SameCredential(NetworkCredential oldCredential, NetworkCredential newCredential)
  1831.         {
  1832.             if (oldCredential == null && newCredential == null)
  1833.                 return true;
  1834.             else if (oldCredential == null && newCredential != null)
  1835.                 return false;
  1836.             else if (oldCredential != null && newCredential == null)
  1837.                 return false;
  1838.             else
  1839.             {
  1840.                 if (oldCredential.Domain == newCredential.Domain &&
  1841.                     oldCredential.UserName == newCredential.UserName &&
  1842.                     oldCredential.Password == newCredential.Password)
  1843.                     return true;
  1844.                 else
  1845.                     return false;
  1846.             }
  1847.         }
  1848.     }
  1849. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement