public override void Initialize(string name, NameValueCollection config)
        {
            if (System.Web.Hosting.HostingEnvironment.IsHosted)
                HttpRuntime.CheckAspNetHostingPermission (AspNetHostingPermissionLevel.Low, SR.Feature_not_supported_at_this_level);

            if (initialized)
                return;

            if (config == null)
                throw new ArgumentNullException("config");

            if (String.IsNullOrEmpty(name))
                name = "AspNetActiveDirectoryMembershipProvider";

            if (string.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", SR.GetString(SR.ADMembership_Description));
            }

            base.Initialize(name, config);

            appName = config["applicationName"];

            if (string.IsNullOrEmpty(appName))
                appName = SecUtility.GetDefaultAppName();

            if( appName.Length > 256 )
                throw new ProviderException(SR.GetString(SR.Provider_application_name_too_long));

            string temp = config["connectionStringName"];
            if (String.IsNullOrEmpty(temp))
                throw new ProviderException(SR.GetString(SR.Connection_name_not_specified));

            adConnectionString = GetConnectionString(temp, true);
            if (String.IsNullOrEmpty(adConnectionString))
                throw new ProviderException(SR.GetString(SR.Connection_string_not_found, temp));

            //
            // Get the provider specific configuration settings
            //

            // connectionProtection
            string connProtection = config["connectionProtection"];
            if (connProtection == null)
                connProtection = "Secure";
            else
            {
                if ((String.Compare(connProtection, "Secure", StringComparison.Ordinal) != 0) &&
                    (String.Compare(connProtection, "None", StringComparison.Ordinal) != 0))
                    throw new ProviderException(SR.GetString(SR.ADMembership_InvalidConnectionProtection, connProtection));
            }

            //
            // credentials
            // username and password if specified must not be empty, moreover if one is specified the other must
            // be specified as well
            //
            string username = config["connectionUsername"];
            if (username != null && username.Length == 0)
                throw new ProviderException(SR.GetString(SR.ADMembership_Connection_username_must_not_be_empty));

            string password = config["connectionPassword"];
            if (password != null && password.Length == 0)
                throw new ProviderException(SR.GetString(SR.ADMembership_Connection_password_must_not_be_empty));

            if ((username != null && password == null) || (password != null && username == null))
                throw new ProviderException(SR.GetString(SR.ADMembership_Username_and_password_reqd));

            NetworkCredential credential = new NetworkCredential(username, password);

            int clientSearchTimeout = SecUtility.GetIntValue(config, "clientSearchTimeout", -1, false, 0);
            int serverSearchTimeout = SecUtility.GetIntValue(config, "serverSearchTimeout", -1, false, 0);

            enableSearchMethods = SecUtility.GetBooleanValue(config, "enableSearchMethods", false);
            requiresUniqueEmail = SecUtility.GetBooleanValue(config, "requiresUniqueEmail", false);
            enablePasswordReset = SecUtility.GetBooleanValue(config, "enablePasswordReset", false);
            requiresQuestionAndAnswer = SecUtility.GetBooleanValue(config, "requiresQuestionAndAnswer", false);
            minRequiredPasswordLength = SecUtility.GetIntValue( config, "minRequiredPasswordLength", 7, false, 128 );
            minRequiredNonalphanumericCharacters = SecUtility.GetIntValue( config, "minRequiredNonalphanumericCharacters", 1, true, 128 );

            passwordStrengthRegularExpression = config["passwordStrengthRegularExpression"];
            if( passwordStrengthRegularExpression != null )
            {
                passwordStrengthRegularExpression = passwordStrengthRegularExpression.Trim();
                if( passwordStrengthRegularExpression.Length != 0 )
                {
                    try
                    {
                        Regex regex = new Regex( passwordStrengthRegularExpression );
                    }
                    catch( ArgumentException e )
                    {
                        throw new ProviderException( e.Message, e );
                    }
                }
            }
            else
            {
                passwordStrengthRegularExpression = string.Empty;
            }
            if (minRequiredNonalphanumericCharacters > minRequiredPasswordLength)
                throw new HttpException(SR.GetString(SR.MinRequiredNonalphanumericCharacters_can_not_be_more_than_MinRequiredPasswordLength));


            using (new ApplicationImpersonationContext())
            {
                //
                //  This will make some checks regarding whether the connectionProtection is valid (choose the right
                //  connectionprotection if necessary, make sure credentials are valid, container exists and the directory is
                //  either AD or ADAM)
                //
                directoryInfo = new DirectoryInformation(adConnectionString, credential, connProtection, clientSearchTimeout, serverSearchTimeout, enablePasswordReset);

                //
                // initialize the syntaxes table
                //
                syntaxes.Add("attributeMapUsername", "DirectoryString");
                syntaxes.Add("attributeMapEmail", "DirectoryString");
                syntaxes.Add("attributeMapPasswordQuestion", "DirectoryString");
                syntaxes.Add("attributeMapPasswordAnswer", "DirectoryString");
                syntaxes.Add("attributeMapFailedPasswordAnswerCount", "Integer");
                syntaxes.Add("attributeMapFailedPasswordAnswerTime", "Integer8");
                syntaxes.Add("attributeMapFailedPasswordAnswerLockoutTime", "Integer8");

                //
                // initialize the in use attributes list
                //
                attributesInUse.Add("objectclass", null);
                attributesInUse.Add("objectsid", null);
                attributesInUse.Add("comment", null);
                attributesInUse.Add("whencreated", null);
                attributesInUse.Add("pwdlastset", null);
                attributesInUse.Add("msds-user-account-control-computed", null);
                attributesInUse.Add("lockouttime", null);
                if (directoryInfo.DirectoryType == DirectoryType.AD)
                    attributesInUse.Add("useraccountcontrol", null);
                else
                    attributesInUse.Add("msds-useraccountdisabled", null);

                //
                // initialize the user attributes list
                //
                userObjectAttributes = GetUserObjectAttributes();

                //
                // get the username/email schema mappings
                //
                int maxLength;
                string attrMapping = GetAttributeMapping(config, "attributeMapUsername", out maxLength);
                if (attrMapping != null)
                {
                    attributeMapUsername = attrMapping;
                    if (maxLength != -1)
                    {
                        if (maxLength < maxUsernameLength)
                            maxUsernameLength = maxLength;
                        if (maxLength < maxUsernameLengthForCreation)
                            maxUsernameLengthForCreation = maxLength;
                    }
                }
                attributesInUse.Add(attributeMapUsername, null);
                if (StringUtil.EqualsIgnoreCase(attributeMapUsername, "sAMAccountName"))
                {
                    usernameIsSAMAccountName = true;
                    usernameIsUPN = false;
                }

                attrMapping = GetAttributeMapping(config, "attributeMapEmail", out maxLength);
                if (attrMapping != null)
                {
                    attributeMapEmail = attrMapping;
                    if (maxLength != -1 && maxLength < maxEmailLength)
                        maxEmailLength = maxLength;
                }
                attributesInUse.Add(attributeMapEmail, null);

                //
                // get max length of "comment" attribute
                //
                maxLength = GetRangeUpperForSchemaAttribute("comment");
                if (maxLength != -1 && maxLength < maxCommentLength)
                    maxCommentLength = maxLength;

                //
                // enablePasswordReset and requiresQuestionAndAnswer should match
                //
                if (enablePasswordReset)
                {
                    //
                    // AD membership provider does not support password reset without question and answer
                    //
                    if (!requiresQuestionAndAnswer)
                        throw new ProviderException(SR.GetString(SR.ADMembership_PasswordReset_without_question_not_supported));

                    //
                    // Other password reset related attributes
                    //
                    maxInvalidPasswordAttempts = SecUtility.GetIntValue(config, "maxInvalidPasswordAttempts", 5, false, 0);
                    passwordAttemptWindow = SecUtility.GetIntValue(config, "passwordAttemptWindow", 10, false, 0);
                    passwordAnswerAttemptLockoutDuration = SecUtility.GetIntValue(config, "passwordAnswerAttemptLockoutDuration", 30, false, 0);

                    //
                    // some more schema mappings that must be specified for Password Reset
                    //
                    attributeMapFailedPasswordAnswerCount = GetAttributeMapping(config, "attributeMapFailedPasswordAnswerCount", out maxLength /* ignored */);
                    if (attributeMapFailedPasswordAnswerCount != null)
                        attributesInUse.Add(attributeMapFailedPasswordAnswerCount, null);

                    attributeMapFailedPasswordAnswerTime = GetAttributeMapping(config, "attributeMapFailedPasswordAnswerTime", out maxLength /* ignored */);
                    if (attributeMapFailedPasswordAnswerTime != null)
                        attributesInUse.Add(attributeMapFailedPasswordAnswerTime, null);

                    attributeMapFailedPasswordAnswerLockoutTime = GetAttributeMapping(config, "attributeMapFailedPasswordAnswerLockoutTime", out maxLength /* ignored */);
                    if (attributeMapFailedPasswordAnswerLockoutTime != null)
                        attributesInUse.Add(attributeMapFailedPasswordAnswerLockoutTime, null);

                    if (attributeMapFailedPasswordAnswerCount == null || attributeMapFailedPasswordAnswerTime == null ||
                            attributeMapFailedPasswordAnswerLockoutTime == null)
                        throw new ProviderException(SR.GetString(SR.ADMembership_BadPasswordAnswerMappings_not_specified));
                }

                //
                // Password Q&A mappings
                //
                attributeMapPasswordQuestion = GetAttributeMapping(config, "attributeMapPasswordQuestion", out maxLength);
                if (attributeMapPasswordQuestion != null)
                {
                    if (maxLength != -1 && maxLength < maxPasswordQuestionLength)
                        maxPasswordQuestionLength = maxLength;

                    attributesInUse.Add(attributeMapPasswordQuestion, null);
                }

                attributeMapPasswordAnswer = GetAttributeMapping(config, "attributeMapPasswordAnswer", out maxLength);
                if (attributeMapPasswordAnswer != null)
                {
                    if (maxLength != -1 && maxLength < maxPasswordAnswerLength)
                        maxPasswordAnswerLength = maxLength;

                    attributesInUse.Add(attributeMapPasswordAnswer, null);
                }

                if (requiresQuestionAndAnswer)
                {
                    //
                    // We also need to check that the password question and answer attributes are mapped
                    //
                    if (attributeMapPasswordQuestion == null || attributeMapPasswordAnswer == null)
                        throw new ProviderException(SR.GetString(SR.ADMembership_PasswordQuestionAnswerMapping_not_specified));
                }

                //
                // the auth type to be used for validation is determined as follows:
                // if directory is ADAM: authType = AuthType.Basic
                // if directory is AD: authType is based on connectionProtection (None, SSL: AuthType.Basic; SignAndSeal: AuthType.Negotiate)
                //
                if (directoryInfo.DirectoryType == DirectoryType.ADAM)
                    authTypeForValidation = AuthType.Basic;
                else
                    authTypeForValidation = directoryInfo.GetLdapAuthenticationTypes(directoryInfo.ConnectionProtection, CredentialsType.NonWindows);

                if (directoryInfo.DirectoryType == DirectoryType.AD)
                {
                    //
                    // if password reset is enabled we should perform all operations on a single server
                    //
                    if (enablePasswordReset)
                        directoryInfo.SelectServer();

                    //
                    // if the username is mapped to upn we need to do  forest wide search to check the uniqueness of the upn.
                    // and if the username is mapped to samAccountName then we need to append the domain name in the username for reliable validation
                    //
                    directoryInfo.InitializeDomainAndForestName();

                }
            }

            //
            // Create a new common ldap connection for validation
            //
            connection = directoryInfo.CreateNewLdapConnection(authTypeForValidation);

            temp = config["passwordCompatMode"];
            if (!string.IsNullOrEmpty(temp))
                _LegacyPasswordCompatibilityMode = (MembershipPasswordCompatibilityMode) Enum.Parse(typeof(MembershipPasswordCompatibilityMode), temp);

            config.Remove("name");
            config.Remove("applicationName");
            config.Remove("connectionStringName");
            config.Remove("requiresUniqueEmail");
            config.Remove("enablePasswordReset");
            config.Remove("requiresQuestionAndAnswer");
            config.Remove("attributeMapPasswordQuestion");
            config.Remove("attributeMapPasswordAnswer");
            config.Remove("attributeMapUsername");
            config.Remove("attributeMapEmail");
            config.Remove("connectionProtection");
            config.Remove("connectionUsername");
            config.Remove("connectionPassword");
            config.Remove("clientSearchTimeout");
            config.Remove("serverSearchTimeout");
            config.Remove("enableSearchMethods");
            config.Remove("maxInvalidPasswordAttempts");
            config.Remove("passwordAttemptWindow");
            config.Remove("passwordAnswerAttemptLockoutDuration");
            config.Remove("attributeMapFailedPasswordAnswerCount");
            config.Remove("attributeMapFailedPasswordAnswerTime");
            config.Remove("attributeMapFailedPasswordAnswerLockoutTime");
            config.Remove("minRequiredPasswordLength");
            config.Remove("minRequiredNonalphanumericCharacters");
            config.Remove("passwordStrengthRegularExpression");
            config.Remove("passwordCompatMode");

            if (config.Count > 0)
            {
                string attribUnrecognized = config.GetKey(0);
                if (!String.IsNullOrEmpty(attribUnrecognized))
                    throw new ProviderException(SR.GetString(SR.Provider_unrecognized_attribute, attribUnrecognized));
            }

            initialized = true;
        }