/// <summary>
        /// Creates a BindRequest with simple bind.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="name">
        /// The name field of BindRequest, see TD Section 5.1.1.1.1 for full list of legal names.
        /// </param>
        /// <param name="password">The password credential of the object.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsBindRequestPacket CreateSimpleBindRequest(
            AdtsLdapContext context,
            string name,
            string password)
        {
            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(AuthenticationChoice.simple, new Asn1OctetString(password ?? string.Empty));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(name ?? string.Empty),
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
        /// <summary>
        /// Creates a BindRequest with simple bind for Active Directory Domain Services(AD DS).
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="username">User name which doesn't include domain prefix.</param>
        /// <param name="password">Password of user.</param>
        /// <param name="domainNetbiosName">NetBIOS domain name(with suffix like ".com" removed).</param>
        /// <returns>The packet that contains the request.</returns>
        /// <exception cref="ArgumentNullException">Thrown when username is null.</exception>
        internal override AdtsBindRequestPacket CreateSimpleBindRequest(
            AdtsLdapContext context,
            string username,
            string password,
            string domainNetbiosName)
        {
            if (username == null)
            {
                throw new ArgumentNullException("username");
            }

            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(AuthenticationChoice.simple, new Asn1OctetString(password ?? string.Empty));

            string fullname = (domainNetbiosName != null) ? (domainNetbiosName + "\\" + username) : username;
            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(fullname),
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
        /// <summary>
        /// Creates a sicily package discovery BindRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <returns>The sicily package discovery BindRequest.</returns>
        internal override AdtsBindRequestPacket CreateSicilyPackageDiscoveryBindRequest(AdtsLdapContext context)
        {
            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(AuthenticationChoice.sicilyPackageDiscovery, new Asn1OctetString(string.Empty));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(new byte[0]),    // For Sicily package discovery, DN is not required.
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
        /// <summary>
        /// Creates a sicily response BindRequest packet. Usually it's the last packet of authentication during
        /// the bind process.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="credential">The credential to be sent, it can be calculated with SSPI.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsBindRequestPacket CreateSicilyResponseBindRequest(
            AdtsLdapContext context,
            byte[] credential)
        {
            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(AuthenticationChoice.sicilyResponse, new Asn1OctetString(credential ?? (new byte[0])));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(new byte[0]),
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
        /// <summary>
        /// Creates a BindRequest with SASL bind. This method is for LDAP v3 only.
        /// Note that for GSS-SPNEGO with NTLM, two rounds of bind requests is required.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="mechanism">Authentication mechanism used, e.g., GSS-SPNEGO, etc.</param>
        /// <param name="credential">The credential to be sent, it can be calculated with SSPI.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsBindRequestPacket CreateSaslBindRequest(
            AdtsLdapContext context,
            string mechanism,
            byte[] credential)
        {
            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(
                AuthenticationChoice.sasl,
                new SaslCredentials(
                    new LDAPString(mechanism ?? string.Empty),
                    new Asn1OctetString(credential ?? (new byte[0]))));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(new byte[0]),    // For SASL, DN is not required.
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }