Inheritance: System.Data.Common.DbConnectionOptions
 internal ServerInfo(SqlConnectionString userOptions, string serverName)
 {
     this.UserServerName = serverName ?? string.Empty;
     this.UserProtocol = userOptions.NetworkLibrary;
     this.ResolvedDatabaseName = userOptions.InitialCatalog;
     this.PreRoutingServerName = null;
 }
        private System.Security.PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner) {
            string keywordToReplace;

            // RULES FOR CONSTRUCTING THE CONNECTION STRING TO DEMAND ON:
            //
            // 1) If no Failover Partner was specified in the original string:
            //
            //          Server=actualFailoverPartner
            //
            // 2) If Failover Partner was specified in the original string:
            //
            //          Server=originalValue; Failover Partner=actualFailoverPartner
            //
            // NOTE: in all cases, when we get a failover partner name from 
            //       the server, we will use that name over what was specified  
            //       in the original connection string.
            
            if (null == userConnectionOptions[SqlConnectionString.KEY.FailoverPartner]) {
                keywordToReplace = SqlConnectionString.KEY.Data_Source;
            }
            else {
                keywordToReplace = SqlConnectionString.KEY.FailoverPartner;
            }
            
            string failoverConnectionString = userConnectionOptions.ExpandKeyword(keywordToReplace, actualFailoverPartner);
            return (new SqlConnectionString(failoverConnectionString)).CreatePermissionSet();
        }
Ejemplo n.º 3
0
        // This c-tor is used to create SSE and user instance connection strings when user instance is set to true
        // BUG (VSTFDevDiv) 479687: Using TransactionScope with Linq2SQL against user instances fails with "connection has been broken" message
        internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance) : base(connectionOptions)
        {
            _integratedSecurity = connectionOptions._integratedSecurity;
            _encrypt            = connectionOptions._encrypt;

            _mars = connectionOptions._mars;
            _persistSecurityInfo = connectionOptions._persistSecurityInfo;
            _pooling             = connectionOptions._pooling;
            _replication         = connectionOptions._replication;
            _userInstance        = userInstance;
            _connectTimeout      = connectionOptions._connectTimeout;
            _loadBalanceTimeout  = connectionOptions._loadBalanceTimeout;
            _maxPoolSize         = connectionOptions._maxPoolSize;
            _minPoolSize         = connectionOptions._minPoolSize;
            _multiSubnetFailover = connectionOptions._multiSubnetFailover;
            _packetSize          = connectionOptions._packetSize;
            _applicationName     = connectionOptions._applicationName;
            _attachDBFileName    = connectionOptions._attachDBFileName;
            _currentLanguage     = connectionOptions._currentLanguage;
            _dataSource          = dataSource;
            _localDBInstance     = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource);
            _failoverPartner     = connectionOptions._failoverPartner;
            _initialCatalog      = connectionOptions._initialCatalog;
            _password            = connectionOptions._password;
            _userID               = connectionOptions._userID;
            _workstationId        = connectionOptions._workstationId;
            _typeSystemVersion    = connectionOptions._typeSystemVersion;
            _applicationIntent    = connectionOptions._applicationIntent;
            _connectRetryCount    = connectionOptions._connectRetryCount;
            _connectRetryInterval = connectionOptions._connectRetryInterval;

            ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
        }
 internal SqlClientPermission(SqlConnectionString constr) : base(constr)
 {
     if ((constr == null) || constr.IsEmpty)
     {
         base.Add(ADP.StrEmpty, ADP.StrEmpty, KeyRestrictionBehavior.AllowOnly);
     }
 }
Ejemplo n.º 5
0
 internal SqlClientPermission(SqlConnectionString constr) : base(constr)
 {
     if ((constr == null) || constr.IsEmpty)
     {
         base.Add(ADP.StrEmpty, ADP.StrEmpty, KeyRestrictionBehavior.AllowOnly);
     }
 }
 internal ServerInfo(SqlConnectionString userOptions, string serverName)
 {
     this.UserServerName       = serverName ?? string.Empty;
     this.UserProtocol         = userOptions.NetworkLibrary;
     this.ResolvedDatabaseName = userOptions.InitialCatalog;
     this.PreRoutingServerName = null;
 }
        static internal SqlConnectionString ParseString(string connectionString) {
            SqlConnectionString constr = null;
            if (!ADP.IsEmpty(connectionString)) {

                constr = (DBConnectionString.CacheQuery(connectionString, _sqlClientParseCache) as SqlConnectionString);
                if (null == constr) {
#if USECRYPTO
                    string encrypted = null/*Crypto.EncryptString(connectionString)*/;
                    string hashvalue = (null == encrypted) ? Crypto.ComputeHash(connectionString) : encrypted;
                    constr = (DBConnectionString.CacheQuery(hashvalue, _sqlClientParseCache) as SqlConnectionString);
                    if (null == constr) {
                        constr = new SqlConnectionString(connectionString, encrypted);
#else
                        constr = new SqlConnectionString(connectionString);
#endif
                        if (constr.ShouldCache()) {
#if USECRYPTO
                            if (!constr.IsEncrypted) {
                                hashvalue = connectionString;
                            }
                            CacheAdd(hashvalue, constr, ref _sqlClientParseCache);
#else
                            CacheAdd(connectionString, constr, ref _sqlClientParseCache);
#endif
                        }
#if USECRYPTO
                    }
#endif
                }
            }
            return constr;
        }
Ejemplo n.º 8
0
        protected override DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions(DbConnectionOptions connectionOptions)
        {
            SqlConnectionString opt = (SqlConnectionString)connectionOptions;

            DbConnectionPoolGroupOptions poolingOptions = null;

            if (opt.Pooling)
            {    // never pool context connections.
                int connectionTimeout = opt.ConnectTimeout;

                if ((0 < connectionTimeout) && (connectionTimeout < int.MaxValue / 1000))
                {
                    connectionTimeout *= 1000;
                }
                else if (connectionTimeout >= int.MaxValue / 1000)
                {
                    connectionTimeout = int.MaxValue;
                }

                poolingOptions = new DbConnectionPoolGroupOptions(
                    opt.IntegratedSecurity,
                    opt.MinPoolSize,
                    opt.MaxPoolSize,
                    connectionTimeout,
                    opt.LoadBalanceTimeout,
                    opt.Enlist);
            }
            return(poolingOptions);
        }
Ejemplo n.º 9
0
        override protected DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions(DbConnectionOptions connectionOptions)
        {
            SqlConnectionString opt = (SqlConnectionString)connectionOptions;

            DbConnectionPoolGroupOptions poolingOptions = null;

            if (!opt.ContextConnection && opt.Pooling)      // never pool context connections.
            {
                int connectionTimeout = opt.ConnectTimeout;

                if ((0 < connectionTimeout) && (connectionTimeout < Int32.MaxValue / 1000))
                {
                    connectionTimeout *= 1000;
                }
                else if (connectionTimeout >= Int32.MaxValue / 1000)
                {
                    connectionTimeout = Int32.MaxValue;
                }

                poolingOptions = new DbConnectionPoolGroupOptions(
                    opt.IntegratedSecurity || opt.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated,
                    opt.MinPoolSize,
                    opt.MaxPoolSize,
                    connectionTimeout,
                    opt.LoadBalanceTimeout,
                    opt.Enlist);
            }
            return(poolingOptions);
        }
Ejemplo n.º 10
0
        public void Close()
        {
            // this method will actually close the internal connection and dipose it, this
            // should only be called by a non-pooled sqlconnection, or by the object pooler
            // when it deems an object should be destroyed

            // it's possible to have a connection finalizer, internal connection finalizer,
            // and the object pool destructor calling this method at the same time, so
            // we need to provide some synchronization
            if (_fConnectionOpen)
            {
                if (Interlocked.CompareExchange(ref _lock, 1, 0) == 0)
                {
                    if (_fConnectionOpen)
                    {
                        if (_fIsPooled)
                        {
                            // PerfCounters - on close of pooled connection, decrement count
                            SQL.DecrementPooledConnectionCount();
                        }

                        try {
                            try {
                                _parser.Disconnect();

                                // UNDONE: GC.SuppressFinalize causes a permission demand?
                                //GC.SuppressFinalize(_parser);
                            }
                            finally { // _connectionWeakRef=
                                // close will always close, even if exception is thrown
                                // remember to null out any object references
                                _connectionWeakRef = null;
                                _connectionOptions = null;
                                _parser            = null;
                                _loginAck          = null;
                                _fConnectionOpen   = false;  // mark internal connection as closed
                                _fUsableState      = false;  // mark internal connection as unusable
                                _pool              = null;
                                _dtcAddress        = null;
                                _transactionGuid   = Guid.Empty;
                                _transactionExport = null;

                                // always release the lock
                                //Interlocked.CompareExchange(ref _lock, 0, 1);
                                _lock = 0;
                            }
                        }
                        catch { // MDAC 80973
                            throw;
                        }
                    }
                    else
                    {
                        // release lock in case where connection already closed
                        //Interlocked.CompareExchange(ref _lock, 0, 1);
                        _lock = 0;
                    }
                }
            }
        }
Ejemplo n.º 11
0
        // this constructor is called by the implicit object pooler
        public SqlInternalConnection(SqlConnectionString connectionOptions, ConnectionPool pool, bool fCheckLifetime, TimeSpan lifetime,
                                     bool fResetConnection, string originalDatabase, string originalLanguage)
        {
            // clone the hashtable, since this is pooled - should not use same reference
            _connectionOptions = connectionOptions.Clone();

            _fIsPooled        = true;
            _pool             = pool;
            _fCheckLifetime   = fCheckLifetime;
            _lifetime         = lifetime;
            _fResetConnection = fResetConnection;
            _originalDatabase = originalDatabase;
            _originalLanguage = originalLanguage;

            this.OpenAndLogin();

            // PerfCounters
            SQL.IncrementPooledConnectionCount();
            SQL.PossibleIncrementPeakPoolConnectionCount();

            // let activate handle distributed transaction enlistment

            // obtain the time of construction, if fCheckLifetime
            if (_fCheckLifetime)
            {
                _createTime = DateTime.UtcNow;
            }
        }
Ejemplo n.º 12
0
        protected override DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous)
        {
            Debug.Assert(!string.IsNullOrEmpty(connectionString), "empty connectionString");
            SqlConnectionString result = new SqlConnectionString(connectionString);

            return(result);
        }
        private System.Security.PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner)
        {
            string keywordToReplace;

            // RULES FOR CONSTRUCTING THE CONNECTION STRING TO DEMAND ON:
            //
            // 1) If no Failover Partner was specified in the original string:
            //
            //          Server=actualFailoverPartner
            //
            // 2) If Failover Partner was specified in the original string:
            //
            //          Server=originalValue; Failover Partner=actualFailoverPartner
            //
            // NOTE: in all cases, when we get a failover partner name from
            //       the server, we will use that name over what was specified
            //       in the original connection string.

            if (null == userConnectionOptions[SqlConnectionString.KEY.FailoverPartner])
            {
                keywordToReplace = SqlConnectionString.KEY.Data_Source;
            }
            else
            {
                keywordToReplace = SqlConnectionString.KEY.FailoverPartner;
            }

            string failoverConnectionString = userConnectionOptions.ExpandKeyword(keywordToReplace, actualFailoverPartner);

            return((new SqlConnectionString(failoverConnectionString)).CreatePermissionSet());
        }
        private SqlConnectionString(SqlConnectionString value) : base(value, false) { // Clone
            _permission = value._permission;

            _integratedSecurity = value._integratedSecurity;
            _connectionReset = value._connectionReset;
            _enlist = value._enlist;
            _encrypt = value._encrypt;
            _persistSecurityInfo = value._persistSecurityInfo;
            _pooling = value._pooling;

            _connectionLifeTime = value._connectionLifeTime;
            _connectTimeout = value._connectTimeout;
            _maxPoolSize = value._maxPoolSize;
            _minPoolSize = value._minPoolSize;
            _packetSize = value._packetSize;

            _applicationName = value._applicationName;
            _attachDBFileName = value._attachDBFileName;
            _currentLanguage = value._currentLanguage;
            _dataSource = value._dataSource;
            _initialCatalog = value._initialCatalog;
            _networkLibrary = value._networkLibrary;
            _userID = value._userID;
            _password = value._password;
            _workstationId = value._workstationId;
        }
 internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions)
 {
     this._failoverPartner = connectionOptions.FailoverPartner;
     if (ADP.IsEmpty(this._failoverPartner))
     {
         this._failoverPartner = null;
     }
 }
Ejemplo n.º 16
0
 internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions)
 {
     this._failoverPartner = connectionOptions.FailoverPartner;
     if (ADP.IsEmpty(this._failoverPartner))
     {
         this._failoverPartner = null;
     }
 }
Ejemplo n.º 17
0
        // This method will be called once connection string is set or changed.
        private void CacheConnectionStringProperties()
        {
            SqlConnectionString connString = ConnectionOptions as SqlConnectionString;

            if (connString != null)
            {
                _connectRetryCount = connString.ConnectRetryCount;
            }
        }
        protected override DbConnectionInternal CreateConnection(DbConnectionOptions options, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
        {
            string instanceName;
            SqlConnectionString str = (SqlConnectionString)options;

            if (str.ContextConnection)
            {
                return(this.GetContextConnection(str, poolGroupProviderInfo, owningConnection));
            }
            bool redirectedUserInstance      = false;
            DbConnectionPoolIdentity current = null;

            if (str.IntegratedSecurity)
            {
                if (pool != null)
                {
                    current = pool.Identity;
                }
                else
                {
                    current = DbConnectionPoolIdentity.GetCurrent();
                }
            }
            if (!str.UserInstance)
            {
                goto Label_00F1;
            }
            redirectedUserInstance = true;
            if ((pool == null) || ((pool != null) && (pool.Count <= 0)))
            {
                using (SqlInternalConnectionTds tds = null)
                {
                    SqlConnectionString connectionOptions = new SqlConnectionString(str, str.DataSource, true, false);
                    tds          = new SqlInternalConnectionTds(current, connectionOptions, null, "", null, false);
                    instanceName = tds.InstanceName;
                    if (!instanceName.StartsWith(@"\\.\", StringComparison.Ordinal))
                    {
                        throw SQL.NonLocalSSEInstance();
                    }
                    if (pool != null)
                    {
                        SqlConnectionPoolProviderInfo info2 = (SqlConnectionPoolProviderInfo)pool.ProviderInfo;
                        info2.InstanceName = instanceName;
                    }
                    goto Label_00DB;
                }
            }
            SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo)pool.ProviderInfo;

            instanceName = providerInfo.InstanceName;
Label_00DB:
            str = new SqlConnectionString(str, instanceName, false, null);
            poolGroupProviderInfo = null;
Label_00F1:
            return(new SqlInternalConnectionTds(current, str, poolGroupProviderInfo, "", (SqlConnection)owningConnection, redirectedUserInstance));
        }
        internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions) {
            // This is for the case where the user specified the failover partner
            // in the connection string and we have not yet connected to get the 
            // env change.
            _failoverPartner = connectionOptions.FailoverPartner;

            if (ADP.IsEmpty(_failoverPartner)) {
                _failoverPartner = null;
            }
        }
Ejemplo n.º 20
0
        // Does this connection uses old style of clear userID or Password in connection string?
        private bool UsesClearUserIdOrPassword(SqlConnectionString opt)
        {
            bool result = false;

            if (null != opt)
            {
                result = (!ADP.IsEmpty(opt.UserID) || !ADP.IsEmpty(opt.Password));
            }
            return(result);
        }
Ejemplo n.º 21
0
        private bool TryOpen(TaskCompletionSource <DbConnectionInternal> retry)
        {
            SqlConnectionString connectionOptions = (SqlConnectionString)ConnectionOptions;

            // Fail Fast in case an application is trying to enlist the SqlConnection in a Transaction Scope.
            if (connectionOptions.Enlist && ADP.GetCurrentTransaction() != null)
            {
                throw ADP.AmbientTransactionIsNotSupported();
            }

            _applyTransientFaultHandling = (retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);

            if (ForceNewConnection)
            {
                if (!InnerConnection.TryReplaceConnection(this, ConnectionFactory, retry, UserConnectionOptions))
                {
                    return(false);
                }
            }
            else
            {
                if (!InnerConnection.TryOpenConnection(this, ConnectionFactory, retry, UserConnectionOptions))
                {
                    return(false);
                }
            }
            // does not require GC.KeepAlive(this) because of OnStateChange

            var tdsInnerConnection = (SqlInternalConnectionTds)InnerConnection;

            Debug.Assert(tdsInnerConnection.Parser != null, "Where's the parser?");

            if (!tdsInnerConnection.ConnectionOptions.Pooling)
            {
                // For non-pooled connections, we need to make sure that the finalizer does actually run to avoid leaking SNI handles
                GC.ReRegisterForFinalize(this);
            }

            // The _statistics can change with StatisticsEnabled. Copying to a local variable before checking for a null value.
            SqlStatistics statistics = _statistics;

            if (StatisticsEnabled ||
                (s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterExecuteCommand) && statistics != null))
            {
                ADP.TimerCurrent(out _statistics._openTimestamp);
                tdsInnerConnection.Parser.Statistics = _statistics;
            }
            else
            {
                tdsInnerConnection.Parser.Statistics = null;
                _statistics = null; // in case of previous Open/Close/reset_CollectStats sequence
            }

            return(true);
        }
 internal SqlInternalConnectionSmi(SqlConnectionString connectionOptions, SmiContext smiContext) : base(connectionOptions)
 {
     this._smiContext = smiContext;
     this._smiContext.OutOfScope += new EventHandler(this.OnOutOfScope);
     this._smiConnection = this._smiContext.ContextConnection;
     this._smiEventSink = new EventSink(this);
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionSmi.ctor|ADV> %d#, constructed new SMI internal connection\n", base.ObjectID);
     }
 }
Ejemplo n.º 23
0
 internal SqlInternalConnectionSmi(SqlConnectionString connectionOptions, SmiContext smiContext) : base(connectionOptions)
 {
     this._smiContext             = smiContext;
     this._smiContext.OutOfScope += new EventHandler(this.OnOutOfScope);
     this._smiConnection          = this._smiContext.ContextConnection;
     this._smiEventSink           = new EventSink(this);
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionSmi.ctor|ADV> %d#, constructed new SMI internal connection\n", base.ObjectID);
     }
 }
        internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions)
        {
            // This is for the case where the user specified the failover partner
            // in the connection string and we have not yet connected to get the
            // env change.
            _failoverPartner = connectionOptions.FailoverPartner;

            if (ADP.IsEmpty(_failoverPartner))
            {
                _failoverPartner = null;
            }
        }
Ejemplo n.º 25
0
        // This c-tor is used to create SSE and user instance connection strings when user instance is set to true
        //
        internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance, bool?setEnlistValue) : base(connectionOptions)
        {
            _integratedSecurity = connectionOptions._integratedSecurity;
            _connectionReset    = connectionOptions._connectionReset;
            _contextConnection  = connectionOptions._contextConnection;
            _encrypt            = connectionOptions._encrypt;

            if (setEnlistValue.HasValue)
            {
                _enlist = setEnlistValue.Value;
            }
            else
            {
                _enlist = connectionOptions._enlist;
            }

            _mars = connectionOptions._mars;
            _persistSecurityInfo            = connectionOptions._persistSecurityInfo;
            _pooling                        = connectionOptions._pooling;
            _replication                    = connectionOptions._replication;
            _userInstance                   = userInstance;
            _connectTimeout                 = connectionOptions._connectTimeout;
            _loadBalanceTimeout             = connectionOptions._loadBalanceTimeout;
            _poolBlockingPeriod             = connectionOptions._poolBlockingPeriod;
            _maxPoolSize                    = connectionOptions._maxPoolSize;
            _minPoolSize                    = connectionOptions._minPoolSize;
            _multiSubnetFailover            = connectionOptions._multiSubnetFailover;
            _transparentNetworkIPResolution = connectionOptions._transparentNetworkIPResolution;
            _packetSize                     = connectionOptions._packetSize;
            _applicationName                = connectionOptions._applicationName;
            _attachDBFileName               = connectionOptions._attachDBFileName;
            _currentLanguage                = connectionOptions._currentLanguage;
            _dataSource                     = dataSource;
            _localDBInstance                = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource);
            _failoverPartner                = connectionOptions._failoverPartner;
            _initialCatalog                 = connectionOptions._initialCatalog;
            _password                       = connectionOptions._password;
            _userID                    = connectionOptions._userID;
            _networkLibrary            = connectionOptions._networkLibrary;
            _workstationId             = connectionOptions._workstationId;
            _expandedAttachDBFilename  = connectionOptions._expandedAttachDBFilename;
            _typeSystemVersion         = connectionOptions._typeSystemVersion;
            _typeSystemAssemblyVersion = connectionOptions._typeSystemAssemblyVersion;
            _transactionBinding        = connectionOptions._transactionBinding;
            _applicationIntent         = connectionOptions._applicationIntent;
            _connectRetryCount         = connectionOptions._connectRetryCount;
            _connectRetryInterval      = connectionOptions._connectRetryInterval;
            _authType                  = connectionOptions._authType;
            _columnEncryptionSetting   = connectionOptions._columnEncryptionSetting;
            _enclaveAttestationUrl     = connectionOptions._enclaveAttestationUrl;

            ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
        }
 private PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner)
 {
     string str;
     if (userConnectionOptions["failover partner"] == null)
     {
         str = "data source";
     }
     else
     {
         str = "failover partner";
     }
     return new SqlConnectionString(userConnectionOptions.ExpandKeyword(str, actualFailoverPartner)).CreatePermissionSet();
 }
Ejemplo n.º 27
0
        private PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner)
        {
            string str;

            if (userConnectionOptions["failover partner"] == null)
            {
                str = "data source";
            }
            else
            {
                str = "failover partner";
            }
            return(new SqlConnectionString(userConnectionOptions.ExpandKeyword(str, actualFailoverPartner)).CreatePermissionSet());
        }
Ejemplo n.º 28
0
        internal static SqlConnectionString FindSqlConnectionOptions(SqlConnectionPoolKey key)
        {
            SqlConnectionString connectionOptions = (SqlConnectionString)SingletonInstance.FindConnectionOptions(key);

            if (null == connectionOptions)
            {
                connectionOptions = new SqlConnectionString(key.ConnectionString);
            }
            if (connectionOptions.IsEmpty)
            {
                throw ADP.NoConnectionString();
            }
            return(connectionOptions);
        }
        internal static SqlConnectionString FindSqlConnectionOptions(string connectionString)
        {
            SqlConnectionString str = (SqlConnectionString)SingletonInstance.FindConnectionOptions(connectionString);

            if (str == null)
            {
                str = new SqlConnectionString(connectionString);
            }
            if (str.IsEmpty)
            {
                throw ADP.NoConnectionString();
            }
            return(str);
        }
 internal ServerInfo(SqlConnectionString userOptions, RoutingInfo routing, string preRoutingServerName)
 {
     if ((routing == null) || (routing.ServerName == null))
     {
         this.UserServerName = string.Empty;
     }
     else
     {
         this.UserServerName = string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[] { routing.ServerName, routing.Port });
     }
     this.PreRoutingServerName = preRoutingServerName;
     this.UserProtocol = "tcp";
     this.SetDerivedNames(this.UserProtocol, this.UserServerName);
     this.ResolvedDatabaseName = userOptions.InitialCatalog;
 }
        /// <include file='doc\SqlClientPermission.uex' path='docs/doc[@for="SqlClientPermission.Add"]/*' />
        override public void Add(string connectionString, string restrictions, KeyRestrictionBehavior behavior)
        {
            switch (behavior)
            {
            case KeyRestrictionBehavior.PreventUsage:
            case KeyRestrictionBehavior.AllowOnly:
                break;

            default:
                throw ADP.Argument("value");
            }
            DBConnectionString entry = new SqlConnectionString(connectionString, restrictions, behavior); // MDAC 85142

            base.AddPermissionEntry(entry);
        }
 internal ServerInfo(SqlConnectionString userOptions, RoutingInfo routing, string preRoutingServerName)
 {
     if ((routing == null) || (routing.ServerName == null))
     {
         this.UserServerName = string.Empty;
     }
     else
     {
         this.UserServerName = string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[] { routing.ServerName, routing.Port });
     }
     this.PreRoutingServerName = preRoutingServerName;
     this.UserProtocol         = "tcp";
     this.SetDerivedNames(this.UserProtocol, this.UserServerName);
     this.ResolvedDatabaseName = userOptions.InitialCatalog;
 }
Ejemplo n.º 33
0
        private TransactionWrapper _transaction;              // cache the ITransaction in the case of manual enlistment

        // this constructor is called by SqlConnection, and is not implicitly pooled
        public SqlInternalConnection(SqlConnection connection, SqlConnectionString connectionOptions)
        {
            _connectionWeakRef = new WeakReference(connection);
            // use the same hashtable reference since non-pooled
            _connectionOptions = connectionOptions; // cloned by SqlConnection
            _fIsPooled         = false;

            this.OpenAndLogin();

            // for non-pooled connections, enlist in a distributed transaction
            // if present - and user specified to enlist
            if (_connectionOptions.Enlist)
            {
                this.EnlistDistributedTransaction();
            }
        }
        private SqlInternalConnectionSmi GetContextConnection(SqlConnectionString options, object providerInfo, DbConnection owningConnection)
        {
            SmiContext currentContext             = SmiContextFactory.Instance.GetCurrentContext();
            SqlInternalConnectionSmi contextValue = (SqlInternalConnectionSmi)currentContext.GetContextValue(0);

            if ((contextValue == null) || contextValue.IsConnectionDoomed)
            {
                if (contextValue != null)
                {
                    contextValue.Dispose();
                }
                contextValue = new SqlInternalConnectionSmi(options, currentContext);
                currentContext.SetContextValue(0, contextValue);
            }
            contextValue.Activate();
            return(contextValue);
        }
Ejemplo n.º 35
0
 private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnection owningObject)
 {
     if (serverInfo.ExtendedServerName == null)
     {
         string userServerName = serverInfo.UserServerName;
         string userProtocol   = serverInfo.UserProtocol;
         if (aliasLookup)
         {
             TdsParserStaticMethods.AliasRegistryLookup(ref userServerName, ref userProtocol);
             if ((owningObject != null) && ((SqlConnectionString)owningObject.UserConnectionOptions).EnforceLocalHost)
             {
                 SqlConnectionString.VerifyLocalHostAndFixup(ref userServerName, true, true);
             }
         }
         serverInfo.SetDerivedNames(userProtocol, userServerName);
     }
 }
        internal SqlInternalConnectionSmi(SqlConnectionString connectionOptions, SmiContext smiContext) : base(connectionOptions)
        {
            Debug.Assert(null != smiContext, "null smiContext?");

            _smiContext             = smiContext;
            _smiContext.OutOfScope += new EventHandler(OnOutOfScope);

            _smiConnection = _smiContext.ContextConnection;
            Debug.Assert(null != _smiConnection, "null SmiContext.ContextConnection?");

            _smiEventSink = new EventSink(this);

            if (Bid.AdvancedOn)
            {
                Bid.Trace("<sc.SqlInternalConnectionSmi.ctor|ADV> %d#, constructed new SMI internal connection\n", ObjectID);
            }
        }
Ejemplo n.º 37
0
 public static void ChangePassword(string connectionString, string newPassword)
 {
     IntPtr ptr;
     Bid.ScopeEnter(out ptr, "<sc.SqlConnection.ChangePassword|API>");
     try
     {
         if (ADP.IsEmpty(connectionString))
         {
             throw SQL.ChangePasswordArgumentMissing("connectionString");
         }
         if (ADP.IsEmpty(newPassword))
         {
             throw SQL.ChangePasswordArgumentMissing("newPassword");
         }
         if (0x80 < newPassword.Length)
         {
             throw ADP.InvalidArgumentLength("newPassword", 0x80);
         }
         SqlConnectionString connectionOptions = SqlConnectionFactory.FindSqlConnectionOptions(connectionString);
         if (connectionOptions.IntegratedSecurity)
         {
             throw SQL.ChangePasswordConflictsWithSSPI();
         }
         if (!ADP.IsEmpty(connectionOptions.AttachDBFilename))
         {
             throw SQL.ChangePasswordUseOfUnallowedKey("attachdbfilename");
         }
         if (connectionOptions.ContextConnection)
         {
             throw SQL.ChangePasswordUseOfUnallowedKey("context connection");
         }
         connectionOptions.CreatePermissionSet().Demand();
         using (SqlInternalConnectionTds tds = new SqlInternalConnectionTds(null, connectionOptions, null, newPassword, null, false))
         {
             if (!tds.IsYukonOrNewer)
             {
                 throw SQL.ChangePasswordRequiresYukon();
             }
         }
         SqlConnectionFactory.SingletonInstance.ClearPool(connectionString);
     }
     finally
     {
         Bid.ScopeLeave(ref ptr);
     }
 }
Ejemplo n.º 38
0
        private bool TryOpen(TaskCompletionSource <DbConnectionInternal> retry)
        {
            SqlConnectionString connectionOptions = (SqlConnectionString)ConnectionOptions;

            _applyTransientFaultHandling = (retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0);

            if (ForceNewConnection)
            {
                if (!InnerConnection.TryReplaceConnection(this, ConnectionFactory, retry, UserConnectionOptions))
                {
                    return(false);
                }
            }
            else
            {
                if (!InnerConnection.TryOpenConnection(this, ConnectionFactory, retry, UserConnectionOptions))
                {
                    return(false);
                }
            }
            // does not require GC.KeepAlive(this) because of OnStateChange

            var tdsInnerConnection = (SqlInternalConnectionTds)InnerConnection;

            Debug.Assert(tdsInnerConnection.Parser != null, "Where's the parser?");

            if (!tdsInnerConnection.ConnectionOptions.Pooling)
            {
                // For non-pooled connections, we need to make sure that the finalizer does actually run to avoid leaking SNI handles
                GC.ReRegisterForFinalize(this);
            }

            if (StatisticsEnabled ||
                s_diagnosticListener.IsEnabled(SqlClientDiagnosticListenerExtensions.SqlAfterExecuteCommand))
            {
                ADP.TimerCurrent(out _statistics._openTimestamp);
                tdsInnerConnection.Parser.Statistics = _statistics;
            }
            else
            {
                tdsInnerConnection.Parser.Statistics = null;
                _statistics = null; // in case of previous Open/Close/reset_CollectStats sequence
            }

            return(true);
        }
 internal SqlInternalConnectionTds(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, object providerInfo, string newPassword, SqlConnection owningObject, bool redirectedUserInstance) : base(connectionOptions)
 {
     this._instanceName = string.Empty;
     if (connectionOptions.UserInstance && InOutOfProcHelper.InProc)
     {
         throw SQL.UserInstanceNotAvailableInProc();
     }
     this._identity = identity;
     this._poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo) providerInfo;
     this._fResetConnection = connectionOptions.ConnectionReset;
     if (this._fResetConnection)
     {
         this._originalDatabase = connectionOptions.InitialCatalog;
         this._originalLanguage = connectionOptions.CurrentLanguage;
     }
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         TimeoutTimer timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout);
         this.OpenLoginEnlist(owningObject, timeout, connectionOptions, newPassword, redirectedUserInstance);
     }
     catch (OutOfMemoryException)
     {
         base.DoomThisConnection();
         throw;
     }
     catch (StackOverflowException)
     {
         base.DoomThisConnection();
         throw;
     }
     catch (ThreadAbortException)
     {
         base.DoomThisConnection();
         throw;
     }
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionTds.ctor|ADV> %d#, constructed new TDS internal connection\n", base.ObjectID);
     }
 }
 internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner)
 {
     if (this.UseFailoverPartner != actualUseFailoverPartner)
     {
         Bid.Trace("<sc.SqlConnectionPoolGroupProviderInfo|INFO> Failover detected. failover partner='%ls'. Clearing PoolGroup\n", actualFailoverPartner);
         base.PoolGroup.Clear();
         this._useFailoverPartner = actualUseFailoverPartner;
     }
     if (!this._useFailoverPartner && (this._failoverPartner != actualFailoverPartner))
     {
         PermissionSet set = this.CreateFailoverPermission(userConnectionOptions, actualFailoverPartner);
         lock (this)
         {
             if (this._failoverPartner != actualFailoverPartner)
             {
                 this._failoverPartner = actualFailoverPartner;
                 this._failoverPermissionSet = set;
             }
         }
     }
 }
        internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner)
        {
            if (UseFailoverPartner != actualUseFailoverPartner)
            {
                base.PoolGroup.Clear();
                _useFailoverPartner = actualUseFailoverPartner;
            }
            // Only construct a new permission set when we're connecting to the
            // primary data source, not the failover partner.
            if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner)
            {
                // NOTE: we optimisitically generate the permission set to keep 
                //       lock short, but we only do this when we get a new
                //       failover partner.

                lock (this)
                {
                    if (_failoverPartner != actualFailoverPartner)
                    {
                        _failoverPartner = actualFailoverPartner;
                    }
                }
            }
        }
Ejemplo n.º 42
0
        // although the new password is generally not used it must be passed to the c'tor
        // the new Login7 packet will always write out the new password (or a length of zero and no bytes if not present)
        //
        internal SqlInternalConnectionTds(
                DbConnectionPoolIdentity identity,
                SqlConnectionString connectionOptions,
                object providerInfo,
                bool redirectedUserInstance,
                SqlConnectionString userConnectionOptions = null, // NOTE: userConnectionOptions may be different to connectionOptions if the connection string has been expanded (see SqlConnectionString.Expand)
                SessionData reconnectSessionData = null) : base(connectionOptions)
        {
#if DEBUG
            if (reconnectSessionData != null)
            {
                reconnectSessionData._debugReconnectDataApplied = true;
            }
#endif
            Debug.Assert(reconnectSessionData == null || connectionOptions.ConnectRetryCount > 0, "Reconnect data supplied with CR turned off");

            if (connectionOptions.ConnectRetryCount > 0)
            {
                _recoverySessionData = reconnectSessionData;
                if (reconnectSessionData == null)
                {
                    _currentSessionData = new SessionData();
                }
                else
                {
                    _currentSessionData = new SessionData(_recoverySessionData);
                    _originalDatabase = _recoverySessionData._initialDatabase;
                    _originalLanguage = _recoverySessionData._initialLanguage;
                }
            }


            _identity = identity;

            _poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo)providerInfo;
            _fResetConnection = connectionOptions.ConnectionReset;
            if (_fResetConnection && _recoverySessionData == null)
            {
                _originalDatabase = connectionOptions.InitialCatalog;
                _originalLanguage = connectionOptions.CurrentLanguage;
            }

            _timeoutErrorInternal = new SqlConnectionTimeoutErrorInternal();

            _parserLock.Wait(canReleaseFromAnyThread: false);
            ThreadHasParserLockForClose = true;   // In case of error, let ourselves know that we already own the parser lock
            try
            {
                var timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout);
                OpenLoginEnlist(timeout, connectionOptions, redirectedUserInstance);
            }
            finally
            {
                ThreadHasParserLockForClose = false;
                _parserLock.Release();
            }
        }
        // although the new password is generally not used it must be passed to the c'tor
        // the new Login7 packet will always write out the new password (or a length of zero and no bytes if not present)
        //
        internal SqlInternalConnectionTds(
                DbConnectionPoolIdentity    identity, 
                SqlConnectionString         connectionOptions,
                SqlCredential               credential,
                object                      providerInfo, 
                string                      newPassword,
                SecureString                newSecurePassword,
                bool                        redirectedUserInstance,
                SqlConnectionString         userConnectionOptions = null, // NOTE: userConnectionOptions may be different to connectionOptions if the connection string has been expanded (see SqlConnectionString.Expand)
                SessionData                 reconnectSessionData = null,
                DbConnectionPool            pool = null,
                string                      accessToken = null,
                bool applyTransientFaultHandling = false
                ) : base(connectionOptions) {

#if DEBUG
            if (reconnectSessionData != null) {
                reconnectSessionData._debugReconnectDataApplied = true;
            }
            try { // use this to help validate this object is only created after the following permission has been previously demanded in the current codepath
                if (userConnectionOptions != null) {
                    // As mentioned above, userConnectionOptions may be different to connectionOptions, so we need to demand on the correct connection string
                    userConnectionOptions.DemandPermission();
                }
                else {
                    connectionOptions.DemandPermission();
                }
            }
            catch(System.Security.SecurityException) {
                System.Diagnostics.Debug.Assert(false, "unexpected SecurityException for current codepath");
                throw;
            }
#endif
            Debug.Assert(reconnectSessionData == null || connectionOptions.ConnectRetryCount > 0, "Reconnect data supplied with CR turned off");

            _dbConnectionPool = pool;
  
            if (connectionOptions.ConnectRetryCount > 0) {
                _recoverySessionData = reconnectSessionData;          
                if (reconnectSessionData == null) {
                    _currentSessionData = new SessionData();
                }
                else {
                    _currentSessionData = new SessionData(_recoverySessionData);
                    _originalDatabase = _recoverySessionData._initialDatabase;
                    _originalLanguage = _recoverySessionData._initialLanguage;
                }
            }
          
            if (connectionOptions.UserInstance && InOutOfProcHelper.InProc) {
                throw SQL.UserInstanceNotAvailableInProc();
            }

            if (accessToken != null) {
                _accessTokenInBytes = System.Text.Encoding.Unicode.GetBytes(accessToken);
            }

            _identity = identity;
            Debug.Assert(newSecurePassword != null || newPassword != null, "cannot have both new secure change password and string based change password to be null");
            Debug.Assert(credential == null || (String.IsNullOrEmpty(connectionOptions.UserID) && String.IsNullOrEmpty(connectionOptions.Password)), "cannot mix the new secure password system and the connection string based password");

            Debug.Assert(credential == null || !connectionOptions.IntegratedSecurity, "Cannot use SqlCredential and Integrated Security");
            Debug.Assert(credential == null || !connectionOptions.ContextConnection, "Cannot use SqlCredential with context connection");

            _poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo)providerInfo;
            _fResetConnection = connectionOptions.ConnectionReset;
            if (_fResetConnection && _recoverySessionData == null) {
                _originalDatabase = connectionOptions.InitialCatalog;
                _originalLanguage = connectionOptions.CurrentLanguage;
            }

            timeoutErrorInternal = new SqlConnectionTimeoutErrorInternal();
            _credential = credential;

            _parserLock.Wait(canReleaseFromAnyThread:false);
            ThreadHasParserLockForClose = true;   // In case of error, let ourselves know that we already own the parser lock
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
#if DEBUG
                TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection();

                RuntimeHelpers.PrepareConstrainedRegions();
                try {
                    tdsReliabilitySection.Start();
#else
                {
#endif //DEBUG
                    _timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout);

                    // If transient fault handling is enabled then we can retry the login upto the ConnectRetryCount.
                    int connectionEstablishCount = applyTransientFaultHandling ? connectionOptions.ConnectRetryCount + 1 : 1;
                    int transientRetryIntervalInMilliSeconds = connectionOptions.ConnectRetryInterval * 1000; // Max value of transientRetryInterval is 60*1000 ms. The max value allowed for ConnectRetryInterval is 60
                    for (int i = 0; i < connectionEstablishCount; i++)
                    {
                        try
                        {
                            OpenLoginEnlist(_timeout, connectionOptions, credential, newPassword, newSecurePassword, redirectedUserInstance);
                            break;
                        }
                        catch (SqlException sqlex)
                        {
                            if (i + 1 == connectionEstablishCount 
                                || !applyTransientFaultHandling
                                || _timeout.IsExpired
                                || _timeout.MillisecondsRemaining < transientRetryIntervalInMilliSeconds
                                || !IsTransientError(sqlex))
                            {
                                throw sqlex;
                            }
                            else
                            {
                                Thread.Sleep(transientRetryIntervalInMilliSeconds);
                            }
                        }
                    }
                }
#if DEBUG
                finally {
                    tdsReliabilitySection.Stop();
                }
#endif //DEBUG
            }
            catch (System.OutOfMemoryException) {
                DoomThisConnection();
                throw;
            }
            catch (System.StackOverflowException) {
                DoomThisConnection();
                throw;
            }
            catch (System.Threading.ThreadAbortException) {
                DoomThisConnection();
                throw;
            }
            finally {
                ThreadHasParserLockForClose = false;
                _parserLock.Release();
            }
            if (Bid.AdvancedOn) {
                Bid.Trace("<sc.SqlInternalConnectionTds.ctor|ADV> %d#, constructed new TDS internal connection\n", ObjectID);
            }
        }
        // Initialize server info from connection options, but override DataSource with given server name
        internal ServerInfo(SqlConnectionString userOptions, RoutingInfo routing, string preRoutingServerName) {
            //-----------------
            // Preconditions
            Debug.Assert(null != userOptions && null!=routing);

            //-----------------
            //Method body
            Debug.Assert(routing.ServerName != null, "server name should never be null");
            if (routing == null || routing.ServerName == null) {
                UserServerName = string.Empty; // ensure user server name is not null
            }
            else {
                UserServerName = string.Format(CultureInfo.InvariantCulture, "{0},{1}", routing.ServerName, routing.Port);
            }
            PreRoutingServerName = preRoutingServerName;
            UserProtocol = TdsEnums.TCP;
            SetDerivedNames(UserProtocol, UserServerName);
            ResolvedDatabaseName = userOptions.InitialCatalog;
        }
Ejemplo n.º 45
0
        // This c-tor is used to create SSE and user instance connection strings when user instance is set to true
        // 
        internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance, bool? setEnlistValue) : base(connectionOptions) {
            _integratedSecurity       = connectionOptions._integratedSecurity;
            _connectionReset          = connectionOptions._connectionReset;
            _contextConnection        = connectionOptions._contextConnection;
            _encrypt                  = connectionOptions._encrypt;

            if (setEnlistValue.HasValue) {
                _enlist = setEnlistValue.Value;
            }
            else {
                _enlist = connectionOptions._enlist;
            }
            
            _mars                     = connectionOptions._mars;
            _persistSecurityInfo      = connectionOptions._persistSecurityInfo;
            _pooling                  = connectionOptions._pooling;
            _replication              = connectionOptions._replication;
            _userInstance             = userInstance;
            _connectTimeout           = connectionOptions._connectTimeout;
            _loadBalanceTimeout       = connectionOptions._loadBalanceTimeout;
            _maxPoolSize              = connectionOptions._maxPoolSize;
            _minPoolSize              = connectionOptions._minPoolSize;
            _multiSubnetFailover      = connectionOptions._multiSubnetFailover;
            _packetSize               = connectionOptions._packetSize;
            _applicationName          = connectionOptions._applicationName;
            _attachDBFileName         = connectionOptions._attachDBFileName;
            _currentLanguage          = connectionOptions._currentLanguage;
            _dataSource               = dataSource;
            _localDBInstance          = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource);
            _failoverPartner          = connectionOptions._failoverPartner;
            _initialCatalog           = connectionOptions._initialCatalog;
            _password                 = connectionOptions._password;
            _userID                   = connectionOptions._userID;
            _networkLibrary           = connectionOptions._networkLibrary;
            _workstationId            = connectionOptions._workstationId;
            _expandedAttachDBFilename = connectionOptions._expandedAttachDBFilename;
            _typeSystemVersion        = connectionOptions._typeSystemVersion;
            _typeSystemAssemblyVersion =connectionOptions._typeSystemAssemblyVersion;
            _transactionBinding       = connectionOptions._transactionBinding;
            _applicationIntent        = connectionOptions._applicationIntent;
            _connectRetryCount        = connectionOptions._connectRetryCount;
            _connectRetryInterval     = connectionOptions._connectRetryInterval;
            _authType                 = connectionOptions._authType;
            _columnEncryptionSetting = connectionOptions._columnEncryptionSetting;
            ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
        }
        override protected DbConnectionInternal CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) {
            SqlConnectionString opt = (SqlConnectionString)options;
            SqlConnectionPoolKey key = (SqlConnectionPoolKey) poolKey;
            SqlInternalConnection result = null;
            SessionData recoverySessionData = null;

            SqlConnectionString userOpt = null;
            if (userOptions != null) {
                userOpt = (SqlConnectionString)userOptions;
            }
            else if (owningConnection != null) {
                userOpt = (SqlConnectionString)(((SqlConnection)owningConnection).UserConnectionOptions);                
            }

            if (owningConnection != null) {
                recoverySessionData = ((SqlConnection)owningConnection)._recoverySessionData;
            }

            if (opt.ContextConnection) {
                result = GetContextConnection(opt, poolGroupProviderInfo);
            }
            else {
                bool redirectedUserInstance       = false;
                DbConnectionPoolIdentity identity = null;

                // Pass DbConnectionPoolIdentity to SqlInternalConnectionTds if using integrated security.
                // Used by notifications.
                if (opt.IntegratedSecurity) {
                    if (pool != null) {
                        identity = pool.Identity;
                    }
                    else {
                        identity = DbConnectionPoolIdentity.GetCurrent();
                    }
                }

                // FOLLOWING IF BLOCK IS ENTIRELY FOR SSE USER INSTANCES
                // If "user instance=true" is in the connection string, we're using SSE user instances
                if (opt.UserInstance) {
                    // opt.DataSource is used to create the SSE connection
                    redirectedUserInstance = true;
                    string instanceName;

                    if ( (null == pool) || 
                         (null != pool && pool.Count <= 0) ) { // Non-pooled or pooled and no connections in the pool.

                        SqlInternalConnectionTds sseConnection = null;
                        try {
                            // What about a failure - throw?  YES!
                            // 



                            SqlConnectionString sseopt = new SqlConnectionString(opt, opt.DataSource, true /* user instance=true */, false /* set Enlist = false */);
                            sseConnection = new SqlInternalConnectionTds(identity, sseopt, key.Credential, null, "", null, false);
                            // NOTE: Retrieve <UserInstanceName> here. This user instance name will be used below to connect to the Sql Express User Instance.
                            instanceName = sseConnection.InstanceName;

                            if (!instanceName.StartsWith("\\\\.\\", StringComparison.Ordinal)) {
                                throw SQL.NonLocalSSEInstance();
                            }

                            if (null != pool) { // Pooled connection - cache result
                                SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo) pool.ProviderInfo;
                                // No lock since we are already in creation mutex
                                providerInfo.InstanceName = instanceName;
                            }
                        }
                        finally {
                            if (null != sseConnection) {
                                sseConnection.Dispose();
                            }
                        }
                    }
                    else { // Cached info from pool.
                        SqlConnectionPoolProviderInfo providerInfo = (SqlConnectionPoolProviderInfo) pool.ProviderInfo;
                        // No lock since we are already in creation mutex
                        instanceName = providerInfo.InstanceName;
                    }

                    // NOTE: Here connection option opt is cloned to set 'instanceName=<UserInstanceName>' that was
                    //       retrieved from the previous SSE connection. For this UserInstance connection 'Enlist=True'.
                    // options immutable - stored in global hash - don't modify
                    opt = new SqlConnectionString(opt, instanceName, false /* user instance=false */, null /* do not modify the Enlist value */);
                    poolGroupProviderInfo = null; // null so we do not pass to constructor below...
                }
                result = new SqlInternalConnectionTds(identity, opt, key.Credential, poolGroupProviderInfo, "", null, redirectedUserInstance, userOpt, recoverySessionData);            
            }
            return result;
        }
 internal static SqlConnectionString FindSqlConnectionOptions(SqlConnectionPoolKey key) {
     SqlConnectionString connectionOptions = (SqlConnectionString )SingletonInstance.FindConnectionOptions(key);
     if (null == connectionOptions) {
         connectionOptions = new SqlConnectionString(key.ConnectionString);
     }
     if (connectionOptions.IsEmpty) {
         throw ADP.NoConnectionString();
     }
     return connectionOptions;
 }
Ejemplo n.º 48
0
        // although the new password is generally not used it must be passed to the c'tor
        // the new Login7 packet will always write out the new password (or a length of zero and no bytes if not present)
        //
        internal SqlInternalConnectionTds(
                DbConnectionPoolIdentity identity,
                SqlConnectionString connectionOptions,
                object providerInfo,
                bool redirectedUserInstance,
                SqlConnectionString userConnectionOptions = null, // NOTE: userConnectionOptions may be different to connectionOptions if the connection string has been expanded (see SqlConnectionString.Expand)
                SessionData reconnectSessionData = null,
                bool applyTransientFaultHandling = false) : base(connectionOptions)
        {
#if DEBUG
            if (reconnectSessionData != null)
            {
                reconnectSessionData._debugReconnectDataApplied = true;
            }
#endif
            Debug.Assert(reconnectSessionData == null || connectionOptions.ConnectRetryCount > 0, "Reconnect data supplied with CR turned off");

            if (connectionOptions.ConnectRetryCount > 0)
            {
                _recoverySessionData = reconnectSessionData;
                if (reconnectSessionData == null)
                {
                    _currentSessionData = new SessionData();
                }
                else
                {
                    _currentSessionData = new SessionData(_recoverySessionData);
                    _originalDatabase = _recoverySessionData._initialDatabase;
                    _originalLanguage = _recoverySessionData._initialLanguage;
                }
            }


            _identity = identity;

            _poolGroupProviderInfo = (SqlConnectionPoolGroupProviderInfo)providerInfo;
            _fResetConnection = connectionOptions.ConnectionReset;
            if (_fResetConnection && _recoverySessionData == null)
            {
                _originalDatabase = connectionOptions.InitialCatalog;
                _originalLanguage = connectionOptions.CurrentLanguage;
            }

            _timeoutErrorInternal = new SqlConnectionTimeoutErrorInternal();

            _parserLock.Wait(canReleaseFromAnyThread: false);
            ThreadHasParserLockForClose = true;   // In case of error, let ourselves know that we already own the parser lock
            try
            {
                var timeout = TimeoutTimer.StartSecondsTimeout(connectionOptions.ConnectTimeout);

                // If transient fault handling is enabled then we can retry the login upto the ConnectRetryCount.
                int connectionEstablishCount = applyTransientFaultHandling ? connectionOptions.ConnectRetryCount + 1 : 1;
                int transientRetryIntervalInMilliSeconds = connectionOptions.ConnectRetryInterval * 1000; // Max value of transientRetryInterval is 60*1000 ms. The max value allowed for ConnectRetryInterval is 60
                for (int i = 0; i < connectionEstablishCount; i++)
                {
                    try
                    {
                        OpenLoginEnlist(timeout, connectionOptions, redirectedUserInstance);
                        break;
                    }
                    catch (SqlException sqlex)
                    {
                        if (i + 1 == connectionEstablishCount
                            || !applyTransientFaultHandling
                            || timeout.IsExpired
                            || timeout.MillisecondsRemaining < transientRetryIntervalInMilliSeconds
                            || !IsTransientError(sqlex))
                        {
                            throw sqlex;
                        }
                        else
                        {
                            Thread.Sleep(transientRetryIntervalInMilliSeconds);
                        }
                    }
                }
            }
            finally
            {
                ThreadHasParserLockForClose = false;
                _parserLock.Release();
            }
        }
Ejemplo n.º 49
0
        private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnectionString options)
        {
            if (serverInfo.ExtendedServerName == null)
            {
                string host = serverInfo.UserServerName;
                string protocol = serverInfo.UserProtocol;


                serverInfo.SetDerivedNames(protocol, host);
            }
        }
Ejemplo n.º 50
0
 internal SqlInternalConnection(SqlConnectionString connectionOptions) : base()
 {
     Debug.Assert(null != connectionOptions, "null connectionOptions?");
     _connectionOptions = connectionOptions;
 }
 protected override DbConnectionOptions CreateConnectionOptions(string connectionString, DbConnectionOptions previous) {
     Debug.Assert(!ADP.IsEmpty(connectionString), "empty connectionString");
     SqlConnectionString result = new SqlConnectionString(connectionString);
     return result;
 }
    private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnectionString options) {
        if (serverInfo.ExtendedServerName == null) {
            string host = serverInfo.UserServerName;
            string protocol = serverInfo.UserProtocol;

            if (aliasLookup) { // We skip this for UserInstances...
                // Perform registry lookup to see if host is an alias.  It will appropriately set host and protocol, if an Alias.
                // Check if it was already resolved, during CR reconnection _currentSessionData values will be copied from
                // _reconnectSessonData of the previous connection
                if (_currentSessionData != null && !string.IsNullOrEmpty(host)) {
                    Tuple<string, string> hostPortPair;
                    if (_currentSessionData._resolvedAliases.TryGetValue(host, out hostPortPair)) {
                        host = hostPortPair.Item1;
                        protocol = hostPortPair.Item2;
                    }
                    else {
                        TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol);
                        _currentSessionData._resolvedAliases.Add(serverInfo.UserServerName, new Tuple<string, string>(host, protocol));
                    }
                }
                else {
                    TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol);
                }

                //
                if (options.EnforceLocalHost) {
                    // verify LocalHost for |DataDirectory| usage
                    SqlConnectionString.VerifyLocalHostAndFixup(ref host, true, true /*fix-up to "."*/);
                }
            }

            serverInfo.SetDerivedNames(protocol, host);
        }
    }
        private SqlInternalConnectionSmi GetContextConnection(SqlConnectionString options, object providerInfo) {
            SmiContext smiContext = SmiContextFactory.Instance.GetCurrentContext();

            SqlInternalConnectionSmi result = (SqlInternalConnectionSmi)smiContext.GetContextValue((int)SmiContextFactory.ContextKey.Connection);

            // context connections are automatically re-useable if they exist unless they've been doomed.
            if (null == result || result.IsConnectionDoomed) {
                if (null != result) {
                    result.Dispose();   // A doomed connection is a messy thing.  Dispose of it promptly in nearest receptacle.
                }

                result = new SqlInternalConnectionSmi(options, smiContext);
                smiContext.SetContextValue((int)SmiContextFactory.ContextKey.Connection, result);
            }

            result.Activate();

            return result;
        }
 // Initialize server info from connection options, 
 internal ServerInfo(SqlConnectionString userOptions) : this(userOptions, userOptions.DataSource) {}
        private void OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential,
                    string newPassword, SecureString newSecurePassword, bool redirectedUserInstance) {
            bool useFailoverPartner; // should we use primary or secondary first
            ServerInfo dataSource = new ServerInfo(connectionOptions);
            string failoverPartner;

            if (null != PoolGroupProviderInfo) {
                useFailoverPartner = PoolGroupProviderInfo.UseFailoverPartner;
                failoverPartner = PoolGroupProviderInfo.FailoverPartner;
            }
            else {
                // Only ChangePassword or SSE User Instance comes through this code path.
                useFailoverPartner = false;
                failoverPartner = ConnectionOptions.FailoverPartner; 
            }

            timeoutErrorInternal.SetInternalSourceType(useFailoverPartner ? SqlConnectionInternalSourceType.Failover : SqlConnectionInternalSourceType.Principle);

            bool hasFailoverPartner = !ADP.IsEmpty(failoverPartner);

            // Open the connection and Login
            try {
                timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
                if (hasFailoverPartner) {
                    timeoutErrorInternal.SetFailoverScenario(true); // this is a failover scenario
                    LoginWithFailover(
                                useFailoverPartner, 
                                dataSource, 
                                failoverPartner, 
                                newPassword,
                                newSecurePassword,
                                redirectedUserInstance, 
                                connectionOptions,
                                credential,
                                timeout);
                }
                else {
                    timeoutErrorInternal.SetFailoverScenario(false); // not a failover scenario
                    LoginNoFailover(dataSource, newPassword, newSecurePassword, redirectedUserInstance, 
                            connectionOptions, credential, timeout);
                }
                timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin);
            }
            catch (Exception e) {
                // 
                if (ADP.IsCatchableExceptionType(e)) {
                    LoginFailure();
                }
                throw;
            }
            timeoutErrorInternal.SetAllCompleteMarker();

#if DEBUG
            _parser._physicalStateObj.InvalidateDebugOnlyCopyOfSniContext();
#endif
        }
        // Initialize server info from connection options, but override DataSource with given server name
        internal ServerInfo (SqlConnectionString userOptions, string serverName) {
            //-----------------
            // Preconditions
            Debug.Assert(null != userOptions);

            //-----------------
            //Method body
             
            Debug.Assert(serverName != null, "server name should never be null");
            UserServerName  = (serverName ?? string.Empty); // ensure user server name is not null

            UserProtocol = userOptions.NetworkLibrary;
            ResolvedDatabaseName = userOptions.InitialCatalog;
            PreRoutingServerName = null;
        }
        internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner) {
            if (UseFailoverPartner != actualUseFailoverPartner) {
                // 
                Bid.Trace("<sc.SqlConnectionPoolGroupProviderInfo|INFO> Failover detected. failover partner='%ls'. Clearing PoolGroup\n", actualFailoverPartner);
                base.PoolGroup.Clear();
                _useFailoverPartner = actualUseFailoverPartner;
            }
            // Only construct a new permission set when we're connecting to the
            // primary data source, not the failover partner.
            if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner) {
                // NOTE: we optimisitically generate the permission set to keep 
                //       lock short, but we only do this when we get a new
                //       failover partner.
                // 

                System.Security.PermissionSet failoverPermissionSet = CreateFailoverPermission(userConnectionOptions, actualFailoverPartner);

                lock (this) {
                    if (_failoverPartner != actualFailoverPartner) {
                        _failoverPartner = actualFailoverPartner;
                        _failoverPermissionSet = failoverPermissionSet;
                    }
                }
            }
        }
    // Attempt to login to a host that does not have a failover partner
    //
    //  Will repeatedly attempt to connect, but back off between each attempt so as not to clog the network.
    //  Back off period increases for first few failures: 100ms, 200ms, 400ms, 800ms, then 1000ms for subsequent attempts
    //
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //  DEVNOTE: The logic in this method is paralleled by the logic in LoginWithFailover.
    //           Changes to either one should be examined to see if they need to be reflected in the other
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    private void LoginNoFailover(ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, bool redirectedUserInstance, 
                SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) {

        Debug.Assert(object.ReferenceEquals(connectionOptions, this.ConnectionOptions), "ConnectionOptions argument and property must be the same"); // consider removing the argument
        int routingAttempts = 0;
        ServerInfo originalServerInfo = serverInfo; // serverInfo may end up pointing to new object due to routing, original object is used to set CurrentDatasource

        if (Bid.AdvancedOn) {
            Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, host=%ls\n", ObjectID, serverInfo.UserServerName);
        }
        int  sleepInterval = 100;  //milliseconds to sleep (back off) between attempts.

        ResolveExtendedServerName(serverInfo, !redirectedUserInstance, connectionOptions);

        long timeoutUnitInterval = 0;
        Boolean isParallel = connectionOptions.MultiSubnetFailover || connectionOptions.TransparentNetworkIPResolution;

        if(isParallel) {
            // Determine unit interval
            if (timeout.IsInfinite) {
                timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * (1000L * ADP.DefaultConnectionTimeout)));
            }
            else {
                timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining));
            }
        }
        // Only three ways out of this loop:
        //  1) Successfully connected
        //  2) Parser threw exception while main timer was expired
        //  3) Parser threw logon failure-related exception 
        //  4) Parser threw exception in post-initial connect code,
        //      such as pre-login handshake or during actual logon. (parser state != Closed)
        //
        //  Of these methods, only #1 exits normally. This preserves the call stack on the exception 
        //  back into the parser for the error cases.
        int attemptNumber = 0;
        TimeoutTimer intervalTimer = null;
        TimeoutTimer firstTransparentAttemptTimeout = TimeoutTimer.StartMillisecondsTimeout(ADP.FirstTransparentAttemptTimeout);
        TimeoutTimer attemptOneLoginTimeout = timeout;
        while(true) {

            if(isParallel) {
                attemptNumber++;
                // Set timeout for this attempt, but don't exceed original timer                
                long nextTimeoutInterval = checked(timeoutUnitInterval * attemptNumber);
                long milliseconds = timeout.MillisecondsRemaining;
                if (nextTimeoutInterval > milliseconds) {
                    nextTimeoutInterval = milliseconds;
                }
                intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval);
            }

            // Re-allocate parser each time to make sure state is known
            // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created
            if (_parser != null)
                _parser.Disconnect();
 
            _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous);
            Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext));

            try {
                // 


                Boolean isFirstTransparentAttempt =  connectionOptions.TransparentNetworkIPResolution && attemptNumber == 1;

                if(isFirstTransparentAttempt) {
                    attemptOneLoginTimeout = firstTransparentAttemptTimeout;
                }
                else {
                    if(isParallel) {
                        attemptOneLoginTimeout = intervalTimer;
                    }
                }
                
                AttemptOneLogin(    serverInfo, 
                                    newPassword,
                                    newSecurePassword,
                                    !isParallel,    // ignore timeout for SniOpen call unless MSF , and TNIR
                                    attemptOneLoginTimeout,
                                    isFirstTransparentAttempt:isFirstTransparentAttempt);
                
                if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner) {
                    // connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used.
                    throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
                }

                if (_routingInfo != null) {
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover> Routed to %ls", serverInfo.ExtendedServerName);

                    if (routingAttempts > 0) {
                        throw SQL.ROR_RecursiveRoutingNotSupported(this);
                    }

                    if (timeout.IsExpired) {
                        throw SQL.ROR_TimeoutAfterRoutingInfo(this);
                    }                    

                    serverInfo = new ServerInfo(ConnectionOptions, _routingInfo, serverInfo.ResolvedServerName);
                    timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.RoutingDestination);
                    _originalClientConnectionId = _clientConnectionId;
                    _routingDestination = serverInfo.UserServerName;

                    // restore properties that could be changed by the environment tokens
                    _currentPacketSize = ConnectionOptions.PacketSize;
                    _currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
                    CurrentDatabase = _originalDatabase = ConnectionOptions.InitialCatalog;
                    _currentFailoverPartner = null;
                    _instanceName = String.Empty;

                    routingAttempts++;

                    continue; // repeat the loop, but skip code reserved for failed connections (after the catch)
                }
                else {
                    break; // leave the while loop -- we've successfully connected
                }
            }
            catch (SqlException sqlex) {
                if (null == _parser
                    || TdsParserState.Closed != _parser.State
                    || IsDoNotRetryConnectError(sqlex)
                    || timeout.IsExpired) {       // no more time to try again
                    throw;  // Caller will call LoginFailure()
                }

                // Check sleep interval to make sure we won't exceed the timeout
                //  Do this in the catch block so we can re-throw the current exception
                if (timeout.MillisecondsRemaining <= sleepInterval) {
                    throw;
                }

                // 
            }

            // We only get here when we failed to connect, but are going to re-try

            // Switch to failover logic if the server provided a partner
            if (null != ServerProvidedFailOverPartner) {
                if (connectionOptions.MultiSubnetFailover) {
                    // connection failed: do not allow failover to server-provided failover partner if MultiSubnetFailover is set
                    throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
                }
                Debug.Assert(ConnectionOptions.ApplicationIntent != ApplicationIntent.ReadOnly, "FAILOVER+AppIntent=RO: Should already fail (at LOGSHIPNODE in OnEnvChange)");

                timeoutErrorInternal.ResetAndRestartPhase();
                timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
                timeoutErrorInternal.SetFailoverScenario(true); // this is a failover scenario
                LoginWithFailover(
                            true,   // start by using failover partner, since we already failed to connect to the primary
                            serverInfo,
                            ServerProvidedFailOverPartner,
                            newPassword,
                            newSecurePassword,
                            redirectedUserInstance,
                            connectionOptions,
                            credential,
                            timeout);
                return; // LoginWithFailover successfully connected and handled entire connection setup
            }

            // Sleep for a bit to prevent clogging the network with requests, 
            //  then update sleep interval for next iteration (max 1 second interval)
            if (Bid.AdvancedOn) {
                Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval);
            }
            Thread.Sleep(sleepInterval);
            sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000;
        }

        if (null != PoolGroupProviderInfo) {
            // We must wait for CompleteLogin to finish for to have the
            // env change from the server to know its designated failover 
            // partner; save this information in _currentFailoverPartner.
            PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, ServerProvidedFailOverPartner);
        }
        CurrentDataSource = originalServerInfo.UserServerName;
    }
Ejemplo n.º 59
0
        // This c-tor is used to create SSE and user instance connection strings when user instance is set to true
        // BUG (VSTFDevDiv) 479687: Using TransactionScope with Linq2SQL against user instances fails with "connection has been broken" message
        internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance) : base(connectionOptions)
        {
            _integratedSecurity = connectionOptions._integratedSecurity;
            _encrypt = connectionOptions._encrypt;

            _mars = connectionOptions._mars;
            _persistSecurityInfo = connectionOptions._persistSecurityInfo;
            _pooling = connectionOptions._pooling;
            _replication = connectionOptions._replication;
            _userInstance = userInstance;
            _connectTimeout = connectionOptions._connectTimeout;
            _loadBalanceTimeout = connectionOptions._loadBalanceTimeout;
            _maxPoolSize = connectionOptions._maxPoolSize;
            _minPoolSize = connectionOptions._minPoolSize;
            _multiSubnetFailover = connectionOptions._multiSubnetFailover;
            _packetSize = connectionOptions._packetSize;
            _applicationName = connectionOptions._applicationName;
            _attachDBFileName = connectionOptions._attachDBFileName;
            _currentLanguage = connectionOptions._currentLanguage;
            _dataSource = dataSource;
            _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource);
            _failoverPartner = connectionOptions._failoverPartner;
            _initialCatalog = connectionOptions._initialCatalog;
            _password = connectionOptions._password;
            _userID = connectionOptions._userID;
            _workstationId = connectionOptions._workstationId;
            _typeSystemVersion = connectionOptions._typeSystemVersion;
            _applicationIntent = connectionOptions._applicationIntent;
            _connectRetryCount = connectionOptions._connectRetryCount;
            _connectRetryInterval = connectionOptions._connectRetryInterval;

            ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
        }
    // Attempt to login to a host that has a failover partner
    //
    // Connection & timeout sequence is
    //      First target, timeout = interval * 1
    //      second target, timeout = interval * 1
    //      sleep for 100ms
    //      First target, timeout = interval * 2
    //      Second target, timeout = interval * 2
    //      sleep for 200ms
    //      First Target, timeout = interval * 3
    //      etc.
    //
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //  DEVNOTE: The logic in this method is paralleled by the logic in LoginNoFailover.
    //           Changes to either one should be examined to see if they need to be reflected in the other
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    private void LoginWithFailover(
            bool                useFailoverHost, 
            ServerInfo          primaryServerInfo, 
            string              failoverHost, 
            string              newPassword,
            SecureString        newSecurePassword,
            bool                redirectedUserInstance, 
            SqlConnectionString connectionOptions,
            SqlCredential       credential,
            TimeoutTimer        timeout
        ) {

        Debug.Assert(!connectionOptions.MultiSubnetFailover, "MultiSubnetFailover should not be set if failover partner is used");

        if (Bid.AdvancedOn) {
            Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", ObjectID, useFailoverHost);
            Bid.PutStr(primaryServerInfo.UserServerName);
            Bid.PutStr(", failover=");
            Bid.PutStr(failoverHost);
            Bid.PutStr("\n");
        }
        int  sleepInterval = 100;  //milliseconds to sleep (back off) between attempts.
        long timeoutUnitInterval;

        string     protocol = ConnectionOptions.NetworkLibrary;
        ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost);

        ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions);
        if (null == ServerProvidedFailOverPartner) {// No point in resolving the failover partner when we're going to override it below
            // Don't resolve aliases if failover == primary // 
            ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions);
        }

        // Determine unit interval
        if (timeout.IsInfinite) {
            timeoutUnitInterval = checked((long) ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout));
        }
        else {
            timeoutUnitInterval = checked((long) (ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining));
        }

        // Initialize loop variables
        bool failoverDemandDone = false; // have we demanded for partner information yet (as necessary)?
        int attemptNumber = 0;

        // Only three ways out of this loop:
        //  1) Successfully connected
        //  2) Parser threw exception while main timer was expired
        //  3) Parser threw logon failure-related exception (LOGON_FAILED, PASSWORD_EXPIRED, etc)
        //
        //  Of these methods, only #1 exits normally. This preserves the call stack on the exception 
        //  back into the parser for the error cases.
        while (true) {
            // Set timeout for this attempt, but don't exceed original timer
            long nextTimeoutInterval = checked(timeoutUnitInterval * ((attemptNumber / 2) + 1));
            long milliseconds = timeout.MillisecondsRemaining;
            if (nextTimeoutInterval > milliseconds) {
                nextTimeoutInterval = milliseconds;
            }

            TimeoutTimer intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval);

            // Re-allocate parser each time to make sure state is known
            // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created
            if (_parser != null)
                _parser.Disconnect();

            _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous);
            Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext));

            ServerInfo currentServerInfo;
            if (useFailoverHost) {
                if (!failoverDemandDone) {
                    FailoverPermissionDemand();
                    failoverDemandDone = true;
                }

                // Primary server may give us a different failover partner than the connection string indicates.  Update it
                if (null != ServerProvidedFailOverPartner && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner) {
                    if (Bid.AdvancedOn) {
                        Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", ObjectID, ServerProvidedFailOverPartner);
                    }
                    failoverServerInfo.SetDerivedNames(protocol, ServerProvidedFailOverPartner);
                }
                currentServerInfo = failoverServerInfo;
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
            }
            else {
                currentServerInfo = primaryServerInfo;
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Principle);
            }

            try {
                // Attempt login.  Use timerInterval for attempt timeout unless infinite timeout was requested.
                AttemptOneLogin(
                        currentServerInfo,
                        newPassword,
                        newSecurePassword,
                        false,          // Use timeout in SniOpen
                        intervalTimer,
                        withFailover:true
                        );

                if (_routingInfo != null) {
                    // We are in login with failover scenation and server sent routing information
                    // If it is read-only routing - we did not supply AppIntent=RO (it should be checked before)
                    // If it is something else, not known yet (future server) - this client is not designed to support this.                    
                    // In any case, server should not have sent the routing info.
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", _routingInfo.ServerName);
                    throw SQL.ROR_UnexpectedRoutingInfo(this);
                }

                break; // leave the while loop -- we've successfully connected
            }
            catch (SqlException sqlex) {
                if (IsDoNotRetryConnectError(sqlex)
                        || timeout.IsExpired) 
                {       // no more time to try again
                    throw;  // Caller will call LoginFailure()
                }

                if (IsConnectionDoomed) {
                    throw;
                }

                if (1 == attemptNumber % 2) {
                    // Check sleep interval to make sure we won't exceed the original timeout
                    //  Do this in the catch block so we can re-throw the current exception
                    if (timeout.MillisecondsRemaining <= sleepInterval) {
                        throw;
                    }
                }

                // 
            }

            // We only get here when we failed to connect, but are going to re-try

            // After trying to connect to both servers fails, sleep for a bit to prevent clogging 
            //  the network with requests, then update sleep interval for next iteration (max 1 second interval)
            if (1 == attemptNumber % 2) {
                if (Bid.AdvancedOn) {
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval);
                }
                Thread.Sleep(sleepInterval);
                sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000;
            }

            // Update attempt number and target host
            attemptNumber++;
            useFailoverHost = !useFailoverHost;
        }

        // If we get here, connection/login succeeded!  Just a few more checks & record-keeping

        // if connected to failover host, but said host doesn't have DbMirroring set up, throw an error
        if (useFailoverHost && null == ServerProvidedFailOverPartner) {
            throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase);
        }

        if (null != PoolGroupProviderInfo) {
            // We must wait for CompleteLogin to finish for to have the
            // env change from the server to know its designated failover 
            // partner; save this information in _currentFailoverPartner.
            PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
        }
        CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
    }