//Function to query the object list based on paging
        public int PagedSearchSynchronous(
                                 string ObjectDN,
                                 LdapAPI.LDAPSCOPE scope,
                                 string Query,
                                 string[] AttributeList,
                                 out List<LdapEntry> ldapEntries)
        {
            ldapEntries = new List<LdapEntry>();

            //Set up LDAP_OPT_SERVER_CONTROLS option so that server can respond with message that contains page control information
            LdapTimeVal timeout = new LdapTimeVal(600, 0);
            IntPtr page_cookiePtr = IntPtr.Zero;
            Berval cookie = new Berval(0, IntPtr.Zero);
            IntPtr[] serverCtrls = new IntPtr[2];
            IntPtr pagedControlPtr = IntPtr.Zero;
            IntPtr serverLdapControl = IntPtr.Zero;
            int errcodep = 0;
            ulong pageCount = 0;
            int PageSize = 1000;
            int ret = -1;

            //int ret = Setserver_PageControloption();
            Logger.Log("Before start using paging, enable paging control return " + ret);

            LdapMessage ldapMessage;

            do
            {
                serverCtrls = new IntPtr[2];

                if (PageSize > 0)
                {
                    //Create page control, the initial page control is created using a cookie  with Berval of {0,null}

                    //if the page size is set to be larger than the default page size in server,
                    //the actual page size will still be the default page size set in server.
                    int pagedRet = Ldap_Create_Page_Control((int)PageSize, page_cookiePtr, 'T', out pagedControlPtr);
                    Logger.Log("CreatePageControl return is " + pagedRet);
                    if (pagedControlPtr == IntPtr.Zero)
                    {
                        Logger.Log("The created pagedcontrol is null");
                    }

                    serverCtrls[0] = pagedControlPtr;
                    serverCtrls[1] = IntPtr.Zero;

                    ret = SearchExtSynchronous(
                                             ObjectDN,
                                             scope,
                                             Query,
                                             AttributeList,
                                             0,
                                             serverCtrls,
                                             null,
                                             timeout,
                                             0,
                                             out ldapMessage);

                    if (ldapMessage == null)
                    {
                        return ret;
                    }

                    if (serverLdapControl != IntPtr.Zero)
                    {
                        LdapAPI.ldap_control_free(serverLdapControl);
                        serverLdapControl = IntPtr.Zero; ;
                    }

                    ret = Ldap_Parse_Result(ldapMessage.MessagePtr, out errcodep, out serverLdapControl);

                    if (serverLdapControl == IntPtr.Zero)
                    {
                        Logger.Log(" LdapApi.ldap_parse_result" + ret.ToString());
                        return ret;
                    }

                    if (page_cookiePtr != IntPtr.Zero)
                    {
                        LdapAPI.ber_free(page_cookiePtr, 0);
                        page_cookiePtr = IntPtr.Zero;
                    }

                    ret = Ldap_Parse_Page_Control(serverLdapControl, out pageCount, out page_cookiePtr);

                    if (ret != 0)
                    {
                        Logger.Log("ParsePageControl" + ret.ToString());
                        return ret;
                    }

                    if (serverLdapControl != IntPtr.Zero)
                    {
                        LdapAPI.ldap_controls_free(serverLdapControl);
                        serverLdapControl = IntPtr.Zero;
                    }

                    if (pagedControlPtr != IntPtr.Zero)
                    {
                        LdapAPI.ldap_control_free(pagedControlPtr);
                        pagedControlPtr = IntPtr.Zero;
                    }
                }
                else
                {
                    ret = SearchExtSynchronous(
                                           ObjectDN,
                                           scope,
                                           Query,
                                           AttributeList,
                                           0,
                                           null,
                                           null,
                                           timeout,
                                           0,
                                           out ldapMessage);

                    if (ret != 0)
                    {
                        return ret;
                    }
                }

                //process the entries returned in the current page (in ldapMessage)
                List<LdapEntry> onePageldapEntries = (ldapMessage != null ? ldapMessage.Ldap_Get_Entries() : null);
                if (onePageldapEntries != null)
                {
                    foreach (LdapEntry entry in onePageldapEntries)
                    {
                        ldapEntries.Add(entry);
                    }
                }

                if (page_cookiePtr != IntPtr.Zero)
                {
                    cookie = (Berval)Marshal.PtrToStructure(page_cookiePtr, typeof(Berval));
                    Logger.Log("cookie.bv_len is " + cookie.bv_len + "cookie.bv_val is " + cookie.bv_val);
                }

            } while (PageSize > 0 && page_cookiePtr != IntPtr.Zero && cookie.bv_val != IntPtr.Zero && cookie.bv_len > 0);

            ServerCtrls[0] = pagedControlPtr;
            ServerCtrls[1] = IntPtr.Zero;

            return ret;
        }
        /// <summary>
        /// SearchExtSynchronous
        /// </summary>
        /// <param name="basedn"></param>
        /// <param name="scope"></param>
        /// <param name="filter"></param>
        /// <param name="search_attrs"></param>
        /// <param name="attrsonly"></param>
        /// <param name="ServerControls"></param>
        /// <param name="ClientControls"></param>
        /// <param name="timeout"></param>
        /// <param name="SizeLimit"></param>
        /// <param name="ret"> Return value to show up the correct pop up to the user while querying</param>
        /// <returns>LdapMessage</returns>
        public int SearchExtSynchronous(
                                 string basedn,
                                 LdapAPI.LDAPSCOPE scope,
                                 string filter,
                                 string[] search_attrs,
                                 int attrsonly,
                                 IntPtr[] ServerControls,
                                 IntPtr[] ClientControls,
                                 LdapTimeVal timeout,
                                 int SizeLimit,
                                 out LdapMessage message
                                 )
        {
            message = null;
            int ret = 0;

            lock (lockThis_searchExtsyn)
            {
                ret = _ldapHandle.Ldap_Search_Ext_S(
                     basedn,
                     (int)scope,
                     filter,
                     search_attrs,
                     attrsonly,
                     ServerControls,
                     ClientControls,
                     timeout,
                     SizeLimit,
                     out message);
            }
            ret = handleSearchError("SearchExtSynchronous", basedn, ret);

            return ret;
        }
        //this is an overload to use the style in MMCSupport
        public LdapMessage SearchSynchronous(
                         string basedn,
                         LdapAPI.LDAPSCOPE scope,
                         string filter,
                         string[] search_attrs,
                         bool attrsonly
                         )
        {
            int ret = 0;
            LdapMessage message = null;

            ret = SearchSynchronous(
                         basedn,
                         scope,
                         filter,
                         search_attrs,
                         attrsonly,
                         out message);

            return message;
        }
         /// <summary>
         /// SearchSynchronous function
         /// </summary>
         /// <param name="basedn"></param>
         /// <param name="scope"></param>
         /// <param name="filter"></param>
         /// <param name="search_attrs"></param>
         /// <param name="attrsonly"></param>
         /// <returns>LdapMessage</returns>
        public int SearchSynchronous(
                                 string basedn,
                                 LdapAPI.LDAPSCOPE scope,
                                 string filter,
                                 string[] search_attrs,
                                 bool attrsonly,
                                 out LdapMessage message
                                 )
        {
            int ret = 0;
            message = null;

            lock (lockThis_searchsyn)
            {
                ret = _ldapHandle.Ldap_Search_S(
                    basedn,
                    (int)scope,
                    filter,
                    search_attrs,
                    0,
                    out message);

                ret = handleSearchError("SearchSynchronous", basedn, ret);
            }
            return ret;
        }
         public int ListChildEntriesSynchronous(
                                 string basedn,
                                 LdapAPI.LDAPSCOPE scope,
                                 string filter,
                                 string[] search_attrs,
                                 bool attrsonly,
                                 out List<LdapEntry> ldapEntries
                                 )
         {
             int ret = 0;


             ldapEntries = new List<LdapEntry>();
             //LdapMessage message = null;

             //TODO: Need to replace this with Ldap_Paged_SearchSynchronous function call to query the objects based on paging
             //ret = SearchSynchronous(
             //         basedn,
             //         scope,
             //         filter,
             //         search_attrs,
             //         attrsonly,
             //         out message);
             ret = PagedSearchSynchronous(
                      basedn,
                      scope,
                      filter,
                      search_attrs,
                      out ldapEntries);
             ret = handleSearchError("ListChildEntriesSynchronous", basedn, ret);

             //process the entries returned in the current page (in ldapMessage)
             //Uncomment if we are not using paging
             //if (message != null)
             //{
             //    List<LdapEntry> ldapEntriesTemp = message.Ldap_Get_Entries();
             //    if (ldapEntriesTemp != null)
             //    {
             //        ldapEntries = ldapEntriesTemp;
             //    }
             //}

             return ret;
         }
        public void Search(string basedn,
                                 LdapAPI.LDAPSCOPE scope,
                                 string filter,
                                 string[] search_attrs,
                                 bool attrsonly,
                                 LDAPWrapper.ldapMsgDelegate callback)
        {
            LDAPArguments args = new LDAPArguments();
            args.initialize();

            args.basedn = basedn;
            args.scope = scope;
            args.filter = filter;
            args.search_attrs = search_attrs;
            args.attrsonly = attrsonly;

            args.ldapMsgCallback = callback;

            Logger.Log("Create a new thread to handle SearchSync API call", Logger.ldapLogLevel);

            Thread t = new Thread(new ParameterizedThreadStart(SearchSynchronousWrap));
            t.Start(args);

            t.Join();
        }