public LdapSearchResults Search(String baseObject, SearchScope scope, AliasDereferencing aliases, Int32 size, Int32 time, Boolean typesOnly,
                                        String filter, String[] attributes)
        {
            if (attributes == null || attributes.Length == 0)
            {
                attributes = new String[] { AllAttributes }
            }
            ;

            BerValue[] attributevalues = new BerValue[attributes.Length];
            for (Int32 i = 0; i < attributes.Length; i++)
            {
                attributevalues[i] = new BerString(Asn1.OCTETSTRING, attributes[i]);
            }

            Int32 lSequenceId = SendLdapRequest(Asn1.LDAPSEARCHREQ,
                                                new BerString(Asn1.OCTETSTRING, baseObject),
                                                new BerEnumerated((Int32)scope),
                                                new BerEnumerated((Int32)aliases),
                                                new BerInteger(size),
                                                new BerInteger(time),
                                                new BerBoolean(typesOnly),
                                                Asn1.ParseFilter(String.IsNullOrEmpty(filter) ? "(objectclass=*)" : filter),
                                                new BerSequence(Asn1.SEQUENCE, attributevalues));

            LdapSearchResults lResults = new LdapSearchResults();

            while (true)
            {
                Response lResponse = ReadResponse();

                if (lResponse.SequenceId != lSequenceId)
                {
                    throw new LdapException("Invalid sequence id in bind response");
                }

                if (lResponse.Code != 0)
                {
                    throw new LdapException(lResponse.Code);
                }

                if (lResponse.TypeCode == Asn1.LDAPSEARCHENTRY)
                {
                    if (lResponse.RestData != null && lResponse.RestData.Length > 0 && lResponse.RestData[0].Type == BerType.String)
                    {
                        LdapObject obj = new LdapObject(((BerString)lResponse.RestData[0]).Value);
                        lResults.Add(obj);
                        if (lResponse.RestData.Length > 1 && lResponse.RestData[1].Type == BerType.Sequence)
                        {
                            foreach (BerValue attribute in ((BerSequence)lResponse.RestData[1]).Items)
                            {
                                if (attribute.Type == BerType.Sequence && ((BerSequence)attribute).Items.Count > 0 && ((BerSequence)attribute).Items[0].Type == BerType.String)
                                {
                                    LdapAttribute att = new LdapAttribute(((BerString)((BerSequence)attribute).Items[0]).Value);
                                    obj.Attributes.Add(att);
                                    if (((BerSequence)attribute).Items.Count <= 1 || ((BerSequence)attribute).Items[1].Type != BerType.Sequence)
                                    {
                                        continue;
                                    }

                                    foreach (BerValue value in ((BerSequence)((BerSequence)attribute).Items[1]).Items)
                                    {
                                        switch (value.Type)
                                        {
                                        case BerType.BitString:
                                            att.Binary = true;
                                            att.Add(((BerBinary)value).Value);
                                            break;

                                        case BerType.Boolean:
                                            att.Binary = false;
                                            att.Add(((BerBoolean)value).Value.ToString());
                                            break;

                                        case BerType.Enumerated:
                                        case BerType.Integer:
                                            att.Binary = false;
                                            att.Add(((BerInteger)value).Value.ToString());
                                            break;

                                        case BerType.IpAddress:
                                            att.Binary = false;
                                            att.Add(((BerIpAddress)value).Value.ToString());
                                            break;

                                        case BerType.Other:
                                            att.Binary = true;
                                            att.Add(((BerOther)value).Value);
                                            break;

                                        case BerType.String:
                                            att.Binary = false;
                                            att.Add(((BerString)value).Value);
                                            break;

                                        case BerType.UInteger:
                                            att.Binary = false;
                                            att.Add(((BerUInteger)value).Value.ToString());
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else if (lResponse.TypeCode == Asn1.LDAPSEARCHREF)
                {
                    if (lResponse.Referers != null)
                    {
                        foreach (BerValue val in lResponse.Referers.Items)
                        {
                            if (val is BerString)
                            {
                                lResults.Referals.Add(((BerString)val).Value);
                            }
                        }
                    }
                    else if (lResponse.RestData != null)
                    {
                        foreach (BerValue val in lResponse.RestData)
                        {
                            if (val is BerString)
                            {
                                lResults.Referals.Add(((BerString)val).Value);
                            }
                            if (val is BerSequence)
                            {
                                foreach (BerValue val2 in ((BerSequence)val).Items)
                                {
                                    if (val2 is BerString)
                                    {
                                        lResults.Referals.Add(((BerString)val2).Value);
                                    }
                                }
                            }
                        }
                    }
                }
                else if (lResponse.TypeCode == Asn1.LDAPSEARCHDONE)
                {
                    break;
                }
                else
                {
                    throw new LdapException("Unknown response from server");
                }
            }

            return(lResults);
        }
    }