Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / SqlClient / SqlConnection.cs / 1305376 / SqlConnection.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //----------------------------------------------------------------------------- [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Data.DataSetExtensions, PublicKey="+AssemblyRef.EcmaPublicKeyFull)] // DevDiv Bugs 92166 [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Data.Entity, PublicKey="+AssemblyRef.EcmaPublicKeyFull)] // SQLPT 300000492 namespace System.Data.SqlClient { using System; using System.Collections; using System.Configuration.Assemblies; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Data.ProviderBase; using System.Data.Sql; using System.Data.SqlTypes; using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Runtime.Serialization.Formatters; using System.Text; using System.Threading; using System.Security; using System.Security.Permissions; using System.Reflection; using System.Runtime.Versioning; using Microsoft.SqlServer.Server; [DefaultEvent("InfoMessage")] public sealed partial class SqlConnection: DbConnection, ICloneable { static private readonly object EventInfoMessage = new object(); private SqlDebugContext _sdc; // SQL Debugging support private bool _AsycCommandInProgress; // SQLStatistics support internal SqlStatistics _statistics; private bool _collectstats; private bool _fireInfoMessageEventOnUserErrors; // False by default public SqlConnection(string connectionString) : this() { ConnectionString = connectionString; } private SqlConnection(SqlConnection connection) { // Clone GC.SuppressFinalize(this); CopyFrom(connection); } // // PUBLIC PROPERTIES // // used to start/stop collection of statistics data and do verify the current state // // devnote: start/stop should not performed using a property since it requires execution of code // // start statistics // set the internal flag (_statisticsEnabled) to true. // Create a new SqlStatistics object if not already there. // connect the parser to the object. // if there is no parser at this time we need to connect it after creation. // [ DefaultValue(false), ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.SqlConnection_StatisticsEnabled), ] public bool StatisticsEnabled { get { return (_collectstats); } set { if (IsContextConnection) { if (value) { throw SQL.NotAvailableOnContextConnection(); } } else { if (value) { // start if (ConnectionState.Open == State) { if (null == _statistics) { _statistics = new SqlStatistics(); ADP.TimerCurrent(out _statistics._openTimestamp); } // set statistics on the parser // update timestamp; Debug.Assert(Parser != null, "Where's the parser?"); Parser.Statistics = _statistics; } } else { // stop if (null != _statistics) { if (ConnectionState.Open == State) { // remove statistics from parser // update timestamp; TdsParser parser = Parser; Debug.Assert(parser != null, "Where's the parser?"); parser.Statistics = null; ADP.TimerCurrent(out _statistics._closeTimestamp); } } } this._collectstats = value; } } } internal bool AsycCommandInProgress { get { return (_AsycCommandInProgress); } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] set { _AsycCommandInProgress = value; } } internal bool IsContextConnection { get { SqlConnectionString opt = (SqlConnectionString)ConnectionOptions; bool result = false; if (null != opt) { result = (opt.ContextConnection); } return result; } } internal SqlConnectionString.TransactionBindingEnum TransactionBinding { get { return ((SqlConnectionString)ConnectionOptions).TransactionBinding; } } internal SqlConnectionString.TypeSystem TypeSystem { get { return ((SqlConnectionString)ConnectionOptions).TypeSystemVersion; } } override protected DbProviderFactory DbProviderFactory { get { return SqlClientFactory.Instance; } } [ DefaultValue(""), #pragma warning disable 618 // ignore obsolete warning about RecommendedAsConfigurable to use SettingsBindableAttribute RecommendedAsConfigurable(true), #pragma warning restore 618 SettingsBindableAttribute(true), RefreshProperties(RefreshProperties.All), ResCategoryAttribute(Res.DataCategory_Data), Editor("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing), ResDescriptionAttribute(Res.SqlConnection_ConnectionString), ] override public string ConnectionString { get { return ConnectionString_Get(); } set { ConnectionString_Set(value); } } [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescriptionAttribute(Res.SqlConnection_ConnectionTimeout), ] override public int ConnectionTimeout { get { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; return ((null != constr) ? constr.ConnectTimeout : SqlConnectionString.DEFAULT.Connect_Timeout); } } [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescriptionAttribute(Res.SqlConnection_Database), ] override public string Database { // if the connection is open, we need to ask the inner connection what it's // current catalog is because it may have gotten changed, otherwise we can // just return what the connection string had. get { SqlInternalConnection innerConnection = (InnerConnection as SqlInternalConnection); string result; if (null != innerConnection) { result = innerConnection.CurrentDatabase; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; result = ((null != constr) ? constr.InitialCatalog : SqlConnectionString.DEFAULT.Initial_Catalog); } return result; } } [ Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescriptionAttribute(Res.SqlConnection_DataSource), ] override public string DataSource { get { SqlInternalConnection innerConnection = (InnerConnection as SqlInternalConnection); string result; if (null != innerConnection) { result = innerConnection.CurrentDataSource; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; result = ((null != constr) ? constr.DataSource : SqlConnectionString.DEFAULT.Data_Source); } return result; } } [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.SqlConnection_PacketSize), ] public int PacketSize { // if the connection is open, we need to ask the inner connection what it's // current packet size is because it may have gotten changed, otherwise we // can just return what the connection string had. get { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); int result; if (null != innerConnection) { result = innerConnection.PacketSize; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; result = ((null != constr) ? constr.PacketSize : SqlConnectionString.DEFAULT.Packet_Size); } return result; } } [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescriptionAttribute(Res.SqlConnection_ServerVersion), ] override public string ServerVersion { get { return GetOpenConnection().ServerVersion; } } internal SqlStatistics Statistics { get { return _statistics; } } [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.SqlConnection_WorkstationId), ] public string WorkstationId { get { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } // If not supplied by the user, the default value is the MachineName // Note: In Longhorn you'll be able to rename a machine without // rebooting. Therefore, don't cache this machine name. SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; string result = ((null != constr) ? constr.WorkstationId : null); if (null == result) { // getting machine name requires Environment.Permission // user must have that permission in order to retrieve this result = Environment.MachineName; } return result; } } // // PUBLIC EVENTS // [ ResCategoryAttribute(Res.DataCategory_InfoMessage), ResDescriptionAttribute(Res.DbConnection_InfoMessage), ] public event SqlInfoMessageEventHandler InfoMessage { add { Events.AddHandler(EventInfoMessage, value); } remove { Events.RemoveHandler(EventInfoMessage, value); } } public bool FireInfoMessageEventOnUserErrors { get { return _fireInfoMessageEventOnUserErrors; } set { _fireInfoMessageEventOnUserErrors = value; } } // // PUBLIC METHODS // new public SqlTransaction BeginTransaction() { // this is just a delegate. The actual method tracks executiontime return BeginTransaction(IsolationLevel.Unspecified, null); } new public SqlTransaction BeginTransaction(IsolationLevel iso) { // this is just a delegate. The actual method tracks executiontime return BeginTransaction(iso, null); } public SqlTransaction BeginTransaction(string transactionName) { // Use transaction names only on the outermost pair of nested // BEGIN...COMMIT or BEGIN...ROLLBACK statements. Transaction names // are ignored for nested BEGIN's. The only way to rollback a nested // transaction is to have a save point from a SAVE TRANSACTION call. return BeginTransaction(IsolationLevel.Unspecified, transactionName); } public SqlTransaction BeginTransaction(IsolationLevel iso, string transactionName) { SqlStatistics statistics = null; IntPtr hscp; string xactName = ADP.IsEmpty(transactionName)? "None" : transactionName; Bid.ScopeEnter(out hscp, "%d#, iso=%d{ds.IsolationLevel}, transactionName='%ls'\n", ObjectID, (int)iso, xactName); try { statistics = SqlStatistics.StartTimer(Statistics); // NOTE: we used to throw an exception if the transaction name was empty // (see MDAC 50292) but that was incorrect because we have a BeginTransaction // method that doesn't have a transactionName argument. SqlTransaction transaction = GetOpenConnection().BeginSqlTransaction(iso, transactionName); // SQLBU 503873 The GetOpenConnection line above doesn't keep a ref on the outer connection (this), // and it could be collected before the inner connection can hook it to the transaction, resulting in // a transaction with a null connection property. Use GC.KeepAlive to ensure this doesn't happen. GC.KeepAlive(this); return transaction; } finally { Bid.ScopeLeave(ref hscp); SqlStatistics.StopTimer(statistics); } } override public void ChangeDatabase(string database) { SqlStatistics statistics = null; SNIHandle bestEffortCleanupTarget = null; RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(this); statistics = SqlStatistics.StartTimer(Statistics); InnerConnection.ChangeDatabase(database); } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException e) { Abort(e); throw; } catch (System.StackOverflowException e) { Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { Abort(e); SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } finally { SqlStatistics.StopTimer(statistics); } } static public void ClearAllPools() { (new SqlClientPermission(PermissionState.Unrestricted)).Demand(); SqlConnectionFactory.SingletonInstance.ClearAllPools(); } static public void ClearPool(SqlConnection connection) { ADP.CheckArgumentNull(connection, "connection"); DbConnectionOptions connectionOptions = connection.UserConnectionOptions; if (null != connectionOptions) { connectionOptions.DemandPermission(); if (connection.IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } SqlConnectionFactory.SingletonInstance.ClearPool(connection); } } object ICloneable.Clone() { SqlConnection clone = new SqlConnection(this); Bid.Trace(" %d#, clone=%d#\n", ObjectID, clone.ObjectID); return clone; } override public void Close() { IntPtr hscp; Bid.ScopeEnter(out hscp, " %d#" , ObjectID); try { SqlStatistics statistics = null; SNIHandle bestEffortCleanupTarget = null; RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(this); statistics = SqlStatistics.StartTimer(Statistics); // The lock here is to protect against the command.cancel / connection.close race condition // The SqlInternalConnectionTds is set to OpenBusy during close, once this happens the cast below will fail and // the command will no longer be cancelable. It might be desirable to be able to cancel the close opperation, but this is // outside of the scope of Whidbey RTM. See (SqlCommand::Cancel) for other lock. lock (InnerConnection) { InnerConnection.CloseConnection(this, ConnectionFactory); } // does not require GC.KeepAlive(this) because of OnStateChange if (null != Statistics) { ADP.TimerCurrent(out _statistics._closeTimestamp); } } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException e) { Abort(e); throw; } catch (System.StackOverflowException e) { Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { Abort(e); SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } finally { SqlStatistics.StopTimer(statistics); } } finally { SqlDebugContext sdc = _sdc; _sdc = null; Bid.ScopeLeave(ref hscp); if (sdc != null) { sdc.Dispose(); } } } new public SqlCommand CreateCommand() { return new SqlCommand(null, this); } private void DisposeMe(bool disposing) { // MDAC 65459 } public void EnlistDistributedTransaction(System.EnterpriseServices.ITransaction transaction) { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } EnlistDistributedTransactionHelper(transaction); } override public void Open() { IntPtr hscp; Bid.ScopeEnter(out hscp, " %d#", ObjectID) ; try { if (StatisticsEnabled) { if (null == _statistics) { _statistics = new SqlStatistics(); } else { _statistics.ContinueOnNewConnection(); } } SNIHandle bestEffortCleanupTarget = null; SqlStatistics statistics = null; RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG statistics = SqlStatistics.StartTimer(Statistics); InnerConnection.OpenConnection(this, ConnectionFactory); // does not require GC.KeepAlive(this) because of OnStateChange // GetBestEffortCleanup must happen AFTER OpenConnection to get the correct target. bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(this); SqlInternalConnectionSmi innerConnection = (InnerConnection as SqlInternalConnectionSmi); if (null != innerConnection) { innerConnection.AutomaticEnlistment(); } else { Debug.Assert(Parser != null, "Where's the parser?"); if (StatisticsEnabled) { ADP.TimerCurrent(out _statistics._openTimestamp); Parser.Statistics = _statistics; } else { Parser.Statistics = null; _statistics = null; // in case of previous Open/Close/reset_CollectStats sequence } CompleteOpen(); } } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException e) { Abort(e); throw; } catch (System.StackOverflowException e) { Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { Abort(e); SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } finally { SqlStatistics.StopTimer(statistics); } } finally { Bid.ScopeLeave(ref hscp) ; } } // // INTERNAL PROPERTIES // internal bool HasLocalTransaction { get { return GetOpenConnection().HasLocalTransaction; } } internal bool HasLocalTransactionFromAPI { get { return GetOpenConnection().HasLocalTransactionFromAPI; } } internal bool IsShiloh { get { return GetOpenConnection().IsShiloh; } } internal bool IsYukonOrNewer { get { return GetOpenConnection().IsYukonOrNewer; } } internal bool IsKatmaiOrNewer { get { return GetOpenConnection().IsKatmaiOrNewer; } } internal TdsParser Parser { get { SqlInternalConnectionTds tdsConnection = (GetOpenConnection() as SqlInternalConnectionTds); if (null == tdsConnection) { throw SQL.NotAvailableOnContextConnection(); } return tdsConnection.Parser; } } internal bool Asynchronous { get { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; return ((null != constr) ? constr.Asynchronous : SqlConnectionString.DEFAULT.Asynchronous); } } // // INTERNAL METHODS // internal void AddPreparedCommand(SqlCommand cmd) { GetOpenConnection().AddPreparedCommand(cmd); } internal void ValidateConnectionForExecute(string method, SqlCommand command) { SqlInternalConnection innerConnection = GetOpenConnection(method); innerConnection.ValidateConnectionForExecute(command); } // Surround name in brackets and then escape any end bracket to protect against SQL Injection. // NOTE: if the user escapes it themselves it will not work, but this was the case in V1 as well // as native OleDb and Odbc. static internal string FixupDatabaseTransactionName(string name) { if (!ADP.IsEmpty(name)) { return SqlServerEscapeHelper.EscapeIdentifier(name); } else { return name; } } internal void OnError(SqlException exception, bool breakConnection) { Debug.Assert(exception != null && exception.Errors.Count != 0, "SqlConnection: OnError called with null or empty exception!"); // Bug fix - MDAC 49022 - connection open after failure... Problem was parser was passing // Open as a state - because the parser's connection to the netlib was open. We would // then set the connection state to the parser's state - which is not correct. The only // time the connection state should change to what is passed in to this function is if // the parser is broken, then we should be closed. Changed to passing in // TdsParserState, not ConnectionState. // fixed by [....] if (breakConnection && (ConnectionState.Open == State)) { Bid.Trace(" %d#, Connection broken.\n", ObjectID) ; this.Close(); } if (exception.Class >= TdsEnums.MIN_ERROR_CLASS) { // It is an error, and should be thrown. Class of TdsEnums.MIN_ERROR_CLASS or above is an error, // below TdsEnums.MIN_ERROR_CLASS denotes an info message. throw exception; } else { // If it is a class < TdsEnums.MIN_ERROR_CLASS, it is a warning collection - so pass to handler this.OnInfoMessage(new SqlInfoMessageEventArgs(exception)); } } internal void RemovePreparedCommand(SqlCommand cmd) { GetOpenConnection().RemovePreparedCommand(cmd); } // // PRIVATE METHODS // // SxS: using Debugger.IsAttached // [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] private void CompleteOpen() { Debug.Assert(ConnectionState.Open == State, "CompleteOpen not open"); // be sure to mark as open so SqlDebugCheck can issue Query // check to see if we need to hook up sql-debugging if a debugger is attached // We only need this check for Shiloh and earlier servers. if (!GetOpenConnection().IsYukonOrNewer && System.Diagnostics.Debugger.IsAttached) { bool debugCheck = false; try { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); // MDAC 66682, 69017 debugCheck = true; } catch (SecurityException e) { ADP.TraceExceptionWithoutRethrow(e); } if (debugCheck) { // if we don't have Unmanaged code permission, don't check for debugging // but let the connection be opened while under the debugger CheckSQLDebugOnConnect(); } } } internal SqlInternalConnection GetOpenConnection() { SqlInternalConnection innerConnection = (InnerConnection as SqlInternalConnection); if (null == innerConnection) { throw ADP.ClosedConnectionError(); } return innerConnection; } internal SqlInternalConnection GetOpenConnection(string method) { DbConnectionInternal innerConnection = InnerConnection; SqlInternalConnection innerSqlConnection = (innerConnection as SqlInternalConnection); if (null == innerSqlConnection) { throw ADP.OpenConnectionRequired(method, innerConnection.State); } return innerSqlConnection; } internal SqlInternalConnectionTds GetOpenTdsConnection() { SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); if (null == innerConnection) { throw ADP.ClosedConnectionError(); } return innerConnection; } internal SqlInternalConnectionTds GetOpenTdsConnection(string method) { SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); if (null == innerConnection) { throw ADP.OpenConnectionRequired(method, innerConnection.State); } return innerConnection; } internal void OnInfoMessage(SqlInfoMessageEventArgs imevent) { if (Bid.TraceOn) { Debug.Assert(null != imevent, "null SqlInfoMessageEventArgs"); Bid.Trace(" %d#, Message='%ls'\n", ObjectID, ((null != imevent) ? imevent.Message : "")); } SqlInfoMessageEventHandler handler = (SqlInfoMessageEventHandler)Events[EventInfoMessage]; if (null != handler) { try { handler(this, imevent); } catch (Exception e) { // MDAC 53175 if (!ADP.IsCatchableOrSecurityExceptionType(e)) { throw; } ADP.TraceExceptionWithoutRethrow(e); } } } // // SQL DEBUGGING SUPPORT // // this only happens once per connection // SxS: using named file mapping APIs // [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private void CheckSQLDebugOnConnect() { IntPtr hFileMap; uint pid = (uint)SafeNativeMethods.GetCurrentProcessId(); string mapFileName; // If Win2k or later, prepend "Global\\" to enable this to work through TerminalServices. if (ADP.IsPlatformNT5) { mapFileName = "Global\\" + TdsEnums.SDCI_MAPFILENAME; } else { mapFileName = TdsEnums.SDCI_MAPFILENAME; } mapFileName = mapFileName + pid.ToString(CultureInfo.InvariantCulture); hFileMap = NativeMethods.OpenFileMappingA(0x4/*FILE_MAP_READ*/, false, mapFileName); if (ADP.PtrZero != hFileMap) { IntPtr pMemMap = NativeMethods.MapViewOfFile(hFileMap, 0x4/*FILE_MAP_READ*/, 0, 0, IntPtr.Zero); if (ADP.PtrZero != pMemMap) { SqlDebugContext sdc = new SqlDebugContext(); sdc.hMemMap = hFileMap; sdc.pMemMap = pMemMap; sdc.pid = pid; // optimization: if we only have to refresh memory-mapped data at connection open time // optimization: then call here instead of in CheckSQLDebug() which gets called // optimization: at command execution time // RefreshMemoryMappedData(sdc); // delaying setting out global state until after we issue this first SQLDebug command so that // we don't reentrantly call into CheckSQLDebug CheckSQLDebug(sdc); // now set our global state _sdc = sdc; } } } // This overload is called by the Command object when executing stored procedures. Note that // if SQLDebug has never been called, it is a noop. internal void CheckSQLDebug() { if (null != _sdc) CheckSQLDebug(_sdc); } // SxS: using GetCurrentThreadId [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] // MDAC 66682, 69017 private void CheckSQLDebug(SqlDebugContext sdc) { // check to see if debugging has been activated Debug.Assert(null != sdc, "SQL Debug: invalid null debugging context!"); #pragma warning disable 618 uint tid = (uint)AppDomain.GetCurrentThreadId(); // Sql Debugging doesn't need fiber support; #pragma warning restore 618 RefreshMemoryMappedData(sdc); // // If we get here, the debugger must be hooked up. if (!sdc.active) { if (sdc.fOption/*TdsEnums.SQLDEBUG_ON*/) { // turn on sdc.active = true; sdc.tid = tid; try { IssueSQLDebug(TdsEnums.SQLDEBUG_ON, sdc.machineName, sdc.pid, sdc.dbgpid, sdc.sdiDllName, sdc.data); sdc.tid = 0; // reset so that the first successful time through, we notify the server of the context switch } catch { sdc.active = false; throw; } } } // be sure to pick up thread context switch, especially the first time through if (sdc.active) { if (!sdc.fOption/*TdsEnums.SQLDEBUG_OFF*/) { // turn off and free the memory sdc.Dispose(); // okay if we throw out here, no state to clean up IssueSQLDebug(TdsEnums.SQLDEBUG_OFF, null, 0, 0, null, null); } else { // notify server of context change if (sdc.tid != tid) { sdc.tid = tid; try { IssueSQLDebug(TdsEnums.SQLDEBUG_CONTEXT, null, sdc.pid, sdc.tid, null, null); } catch { sdc.tid = 0; throw; } } } } } private void IssueSQLDebug(uint option, string machineName, uint pid, uint id, string sdiDllName, byte[] data) { if (GetOpenConnection().IsYukonOrNewer) { // return; } // SqlCommand c = new SqlCommand(TdsEnums.SP_SDIDEBUG, this); c.CommandType = CommandType.StoredProcedure; // context param SqlParameter p = new SqlParameter(null, SqlDbType.VarChar, TdsEnums.SQLDEBUG_MODE_NAMES[option].Length); p.Value = TdsEnums.SQLDEBUG_MODE_NAMES[option]; c.Parameters.Add(p); if (option == TdsEnums.SQLDEBUG_ON) { // debug dll name p = new SqlParameter(null, SqlDbType.VarChar, sdiDllName.Length); p.Value = sdiDllName; c.Parameters.Add(p); // debug machine name p = new SqlParameter(null, SqlDbType.VarChar, machineName.Length); p.Value = machineName; c.Parameters.Add(p); } if (option != TdsEnums.SQLDEBUG_OFF) { // client pid p = new SqlParameter(null, SqlDbType.Int); p.Value = pid; c.Parameters.Add(p); // dbgpid or tid p = new SqlParameter(null, SqlDbType.Int); p.Value = id; c.Parameters.Add(p); } if (option == TdsEnums.SQLDEBUG_ON) { // debug data p = new SqlParameter(null, SqlDbType.VarBinary, (null != data) ? data.Length : 0); p.Value = data; c.Parameters.Add(p); } c.ExecuteNonQuery(); } public static void ChangePassword(string connectionString, string newPassword) { IntPtr hscp; Bid.ScopeEnter(out hscp, " ") ; try { if (ADP.IsEmpty(connectionString)) { throw SQL.ChangePasswordArgumentMissing("connectionString"); } if (ADP.IsEmpty(newPassword)) { throw SQL.ChangePasswordArgumentMissing("newPassword"); } if (TdsEnums.MAXLEN_NEWPASSWORD < newPassword.Length) { throw ADP.InvalidArgumentLength("newPassword", TdsEnums.MAXLEN_NEWPASSWORD); } SqlConnectionString connectionOptions = SqlConnectionFactory.FindSqlConnectionOptions(connectionString); if (connectionOptions.IntegratedSecurity) { throw SQL.ChangePasswordConflictsWithSSPI(); } if (! ADP.IsEmpty(connectionOptions.AttachDBFilename)) { throw SQL.ChangePasswordUseOfUnallowedKey(SqlConnectionString.KEY.AttachDBFilename); } if (connectionOptions.ContextConnection) { throw SQL.ChangePasswordUseOfUnallowedKey(SqlConnectionString.KEY.Context_Connection); } System.Security.PermissionSet permissionSet = connectionOptions.CreatePermissionSet(); permissionSet.Demand(); // note: This is the only case where we directly construt the internal connection, passing in the new password. // Normally we would simply create a regular connectoin and open it but there is no other way to pass the // new password down to the constructor. Also it would have an unwanted impact on the connection pool // using (SqlInternalConnectionTds con = new SqlInternalConnectionTds(null, connectionOptions, null, newPassword, (SqlConnection)null, false)) { if (!con.IsYukonOrNewer) { throw SQL.ChangePasswordRequiresYukon(); } } SqlConnectionFactory.SingletonInstance.ClearPool(connectionString); } finally { Bid.ScopeLeave(ref hscp) ; } } // updates our context with any changes made to the memory-mapped data by an external process static private void RefreshMemoryMappedData(SqlDebugContext sdc) { Debug.Assert(ADP.PtrZero != sdc.pMemMap, "SQL Debug: invalid null value for pMemMap!"); // copy memory mapped file contents into managed types MEMMAP memMap = (MEMMAP)Marshal.PtrToStructure(sdc.pMemMap, typeof(MEMMAP)); sdc.dbgpid = memMap.dbgpid; sdc.fOption = (memMap.fOption == 1) ? true : false; // xlate ansi byte[] -> managed strings Encoding cp = System.Text.Encoding.GetEncoding(TdsEnums.DEFAULT_ENGLISH_CODE_PAGE_VALUE); sdc.machineName = cp.GetString(memMap.rgbMachineName, 0, memMap.rgbMachineName.Length); sdc.sdiDllName = cp.GetString(memMap.rgbDllName, 0, memMap.rgbDllName.Length); // just get data reference sdc.data = memMap.rgbData; } public void ResetStatistics() { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } if (null != Statistics) { Statistics.Reset(); if (ConnectionState.Open == State) { // update timestamp; ADP.TimerCurrent(out _statistics._openTimestamp); } } } public IDictionary RetrieveStatistics() { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } if (null != Statistics) { UpdateStatistics(); return Statistics.GetHashtable(); } else { return new SqlStatistics().GetHashtable(); } } private void UpdateStatistics() { if (ConnectionState.Open == State) { // update timestamp ADP.TimerCurrent(out _statistics._closeTimestamp); } // delegate the rest of the work to the SqlStatistics class Statistics.UpdateStatistics(); } // // UDT SUPPORT // // internal static void CheckGetExtendedUDTInfo(SqlMetaDataPriv metaData, bool fThrow) { if (metaData.udtType == null) { // If null, we have not obtained extended info. Debug.Assert(!ADP.IsEmpty(metaData.udtAssemblyQualifiedName), "Unexpected state on GetUDTInfo"); // 2nd argument determines whether exception from Assembly.Load is thrown. metaData.udtType = Type.GetType(metaData.udtAssemblyQualifiedName, fThrow); if (fThrow && metaData.udtType == null) { // throw SQL.UDTUnexpectedResult(metaData.udtAssemblyQualifiedName); } } } internal object GetUdtValue(object value, SqlMetaDataPriv metaData, bool returnDBNull) { if (returnDBNull && ADP.IsNull(value)) { return DBNull.Value; } object o = null; // Since the serializer doesn't handle nulls... if (ADP.IsNull(value)) { Type t = metaData.udtType; Debug.Assert(t != null, "Unexpected null of udtType on GetUdtValue!"); o = t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new Object[]{}, CultureInfo.InvariantCulture); Debug.Assert(o != null); return o; } else { MemoryStream stm = new MemoryStream((byte[]) value); o = SerializationHelperSql9.Deserialize(stm, metaData.udtType); Debug.Assert(o != null, "object could NOT be created"); return o; } } internal byte[] GetBytes(object o) { Microsoft.SqlServer.Server.Format format = Microsoft.SqlServer.Server.Format.Native; int maxSize = 0; return GetBytes(o, out format, out maxSize); } internal byte[] GetBytes(object o, out Microsoft.SqlServer.Server.Format format, out int maxSize) { SqlUdtInfo attr = AssemblyCache.GetInfoFromType(o.GetType()); maxSize = attr.MaxByteSize; format = attr.SerializationFormat; if (maxSize < -1 || maxSize >= UInt16.MaxValue) { // Do we need this? Is this the right place? throw new InvalidOperationException(o.GetType() + ": invalid Size"); } byte[] retval; using (MemoryStream stm = new MemoryStream(maxSize < 0 ? 0 : maxSize)) { SerializationHelperSql9.Serialize(stm, o); retval = stm.ToArray(); } return retval; } } // SqlConnection // [ ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("afef65ad-4577-447a-a148-83acadd3d4b9"), ] [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")] public sealed class SQLDebugging: ISQLDebug { // Security stuff const int STANDARD_RIGHTS_REQUIRED = (0x000F0000); const int DELETE = (0x00010000); const int READ_CONTROL = (0x00020000); const int WRITE_DAC = (0x00040000); const int WRITE_OWNER = (0x00080000); const int SYNCHRONIZE = (0x00100000); const int FILE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x000001FF); const uint GENERIC_READ = (0x80000000); const uint GENERIC_WRITE = (0x40000000); const uint GENERIC_EXECUTE = (0x20000000); const uint GENERIC_ALL = (0x10000000); const int SECURITY_DESCRIPTOR_REVISION = (1); const int ACL_REVISION = (2); const int SECURITY_AUTHENTICATED_USER_RID = (0x0000000B); const int SECURITY_LOCAL_SYSTEM_RID = (0x00000012); const int SECURITY_BUILTIN_DOMAIN_RID = (0x00000020); const int SECURITY_WORLD_RID = (0x00000000); const byte SECURITY_NT_AUTHORITY = 5; const int DOMAIN_GROUP_RID_ADMINS = (0x00000200); const int DOMAIN_ALIAS_RID_ADMINS = (0x00000220); const int sizeofSECURITY_ATTRIBUTES = 12; // sizeof(SECURITY_ATTRIBUTES); const int sizeofSECURITY_DESCRIPTOR = 20; // sizeof(SECURITY_DESCRIPTOR); const int sizeofACCESS_ALLOWED_ACE = 12; // sizeof(ACCESS_ALLOWED_ACE); const int sizeofACCESS_DENIED_ACE = 12; // sizeof(ACCESS_DENIED_ACE); const int sizeofSID_IDENTIFIER_AUTHORITY = 6; // sizeof(SID_IDENTIFIER_AUTHORITY) const int sizeofACL = 8; // sizeof(ACL); private IntPtr CreateSD(ref IntPtr pDacl) { IntPtr pSecurityDescriptor = IntPtr.Zero; IntPtr pUserSid = IntPtr.Zero; IntPtr pAdminSid = IntPtr.Zero; IntPtr pNtAuthority = IntPtr.Zero; int cbAcl = 0; bool status = false; pNtAuthority = Marshal.AllocHGlobal(sizeofSID_IDENTIFIER_AUTHORITY); if (pNtAuthority == IntPtr.Zero) goto cleanup; Marshal.WriteInt32(pNtAuthority, 0, 0); Marshal.WriteByte(pNtAuthority, 4, 0); Marshal.WriteByte(pNtAuthority, 5, SECURITY_NT_AUTHORITY); status = NativeMethods.AllocateAndInitializeSid( pNtAuthority, (byte)1, SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0, ref pUserSid); if (!status || pUserSid == IntPtr.Zero) { goto cleanup; } status = NativeMethods.AllocateAndInitializeSid( pNtAuthority, (byte)2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, ref pAdminSid); if (!status || pAdminSid == IntPtr.Zero) { goto cleanup; } status = false; pSecurityDescriptor = Marshal.AllocHGlobal(sizeofSECURITY_DESCRIPTOR); if (pSecurityDescriptor == IntPtr.Zero) { goto cleanup; } for (int i = 0; i < sizeofSECURITY_DESCRIPTOR; i++) Marshal.WriteByte(pSecurityDescriptor, i, (byte)0); cbAcl = sizeofACL + (2 * (sizeofACCESS_ALLOWED_ACE)) + sizeofACCESS_DENIED_ACE + NativeMethods.GetLengthSid(pUserSid) + NativeMethods.GetLengthSid(pAdminSid); pDacl = Marshal.AllocHGlobal(cbAcl); if (pDacl == IntPtr.Zero) { goto cleanup; } // rights must be added in a certain order. Namely, deny access first, then add access if (NativeMethods.InitializeAcl(pDacl, cbAcl, ACL_REVISION)) if (NativeMethods.AddAccessDeniedAce(pDacl, ACL_REVISION, WRITE_DAC, pUserSid)) if (NativeMethods.AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_READ, pUserSid)) if (NativeMethods.AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_ALL, pAdminSid)) if (NativeMethods.InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) if (NativeMethods.SetSecurityDescriptorDacl(pSecurityDescriptor, true, pDacl, false)) { status = true; } cleanup : if (pNtAuthority != IntPtr.Zero) { Marshal.FreeHGlobal(pNtAuthority); } if (pAdminSid != IntPtr.Zero) NativeMethods.FreeSid(pAdminSid); if (pUserSid != IntPtr.Zero) NativeMethods.FreeSid(pUserSid); if (status) return pSecurityDescriptor; else { if (pSecurityDescriptor != IntPtr.Zero) { Marshal.FreeHGlobal(pSecurityDescriptor); } } return IntPtr.Zero; } // SxS: using file mapping API (CreateFileMapping) // [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] bool ISQLDebug.SQLDebug(int dwpidDebugger, int dwpidDebuggee, [MarshalAs(UnmanagedType.LPStr)] string pszMachineName, [MarshalAs(UnmanagedType.LPStr)] string pszSDIDLLName, int dwOption, int cbData, byte[] rgbData) { bool result = false; IntPtr hFileMap = IntPtr.Zero; IntPtr pMemMap = IntPtr.Zero; IntPtr pSecurityDescriptor = IntPtr.Zero; IntPtr pSecurityAttributes = IntPtr.Zero; IntPtr pDacl = IntPtr.Zero; // validate the structure if (null == pszMachineName || null == pszSDIDLLName) return false; if (pszMachineName.Length > TdsEnums.SDCI_MAX_MACHINENAME || pszSDIDLLName.Length > TdsEnums.SDCI_MAX_DLLNAME) return false; // note that these are ansi strings Encoding cp = System.Text.Encoding.GetEncoding(TdsEnums.DEFAULT_ENGLISH_CODE_PAGE_VALUE); byte[] rgbMachineName = cp.GetBytes(pszMachineName); byte[] rgbSDIDLLName = cp.GetBytes(pszSDIDLLName); if (null != rgbData && cbData > TdsEnums.SDCI_MAX_DATA) return false; string mapFileName; // If Win2k or later, prepend "Global\\" to enable this to work through TerminalServices. if (ADP.IsPlatformNT5) { mapFileName = "Global\\" + TdsEnums.SDCI_MAPFILENAME; } else { mapFileName = TdsEnums.SDCI_MAPFILENAME; } mapFileName = mapFileName + dwpidDebuggee.ToString(CultureInfo.InvariantCulture); // Create Security Descriptor pSecurityDescriptor = CreateSD(ref pDacl); pSecurityAttributes = Marshal.AllocHGlobal(sizeofSECURITY_ATTRIBUTES); if ((pSecurityDescriptor == IntPtr.Zero) || (pSecurityAttributes == IntPtr.Zero)) return false; Marshal.WriteInt32(pSecurityAttributes, 0, sizeofSECURITY_ATTRIBUTES); // nLength = sizeof(SECURITY_ATTRIBUTES) Marshal.WriteIntPtr(pSecurityAttributes, 4, pSecurityDescriptor); // lpSecurityDescriptor = pSecurityDescriptor Marshal.WriteInt32(pSecurityAttributes, 8, 0); // bInheritHandle = FALSE hFileMap = NativeMethods.CreateFileMappingA( ADP.InvalidPtr/*INVALID_HANDLE_VALUE*/, pSecurityAttributes, 0x4/*PAGE_READWRITE*/, 0, Marshal.SizeOf(typeof(MEMMAP)), mapFileName); if (IntPtr.Zero == hFileMap) { goto cleanup; } pMemMap = NativeMethods.MapViewOfFile(hFileMap, 0x6/*FILE_MAP_READ|FILE_MAP_WRITE*/, 0, 0, IntPtr.Zero); if (IntPtr.Zero == pMemMap) { goto cleanup; } // copy data to memory-mapped file // layout of MEMMAP structure is: // uint dbgpid // uint fOption // byte[32] machineName // byte[16] sdiDllName // uint dbData // byte[255] vData int offset = 0; Marshal.WriteInt32(pMemMap, offset, (int)dwpidDebugger); offset += 4; Marshal.WriteInt32(pMemMap, offset, (int)dwOption); offset += 4; Marshal.Copy(rgbMachineName, 0, ADP.IntPtrOffset(pMemMap, offset), rgbMachineName.Length); offset += TdsEnums.SDCI_MAX_MACHINENAME; Marshal.Copy(rgbSDIDLLName, 0, ADP.IntPtrOffset(pMemMap, offset), rgbSDIDLLName.Length); offset += TdsEnums.SDCI_MAX_DLLNAME; Marshal.WriteInt32(pMemMap, offset, (int)cbData); offset += 4; if (null != rgbData) { Marshal.Copy(rgbData, 0, ADP.IntPtrOffset(pMemMap, offset), (int)cbData); } NativeMethods.UnmapViewOfFile(pMemMap); result = true; cleanup : if (result == false) { if (hFileMap != IntPtr.Zero) NativeMethods.CloseHandle(hFileMap); } if (pSecurityAttributes != IntPtr.Zero) Marshal.FreeHGlobal(pSecurityAttributes); if (pSecurityDescriptor != IntPtr.Zero) Marshal.FreeHGlobal(pSecurityDescriptor); if (pDacl != IntPtr.Zero) Marshal.FreeHGlobal(pDacl); return result; } } // this is a private interface to com+ users // do not change this guid [ ComImport, ComVisible(true), Guid("6cb925bf-c3c0-45b3-9f44-5dd67c7b7fe8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), BestFitMapping(false, ThrowOnUnmappableChar = true), ] interface ISQLDebug { [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")] bool SQLDebug( int dwpidDebugger, int dwpidDebuggee, [MarshalAs(UnmanagedType.LPStr)] string pszMachineName, [MarshalAs(UnmanagedType.LPStr)] string pszSDIDLLName, int dwOption, int cbData, byte[] rgbData); } sealed class SqlDebugContext: IDisposable { // context data internal uint pid = 0; internal uint tid = 0; internal bool active = false; // memory-mapped data internal IntPtr pMemMap = ADP.PtrZero; internal IntPtr hMemMap = ADP.PtrZero; internal uint dbgpid = 0; internal bool fOption = false; internal string machineName = null; internal string sdiDllName = null; internal byte[] data = null; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // using CloseHandle and UnmapViewOfFile - no exposure [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private void Dispose(bool disposing) { if (disposing) { // Nothing to do here ; } if (pMemMap != IntPtr.Zero) { NativeMethods.UnmapViewOfFile(pMemMap); pMemMap = IntPtr.Zero; } if (hMemMap != IntPtr.Zero) { NativeMethods.CloseHandle(hMemMap); hMemMap = IntPtr.Zero; } active = false; } ~SqlDebugContext() { Dispose(false); } } // native interop memory mapped structure for sdi debugging [StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)] internal struct MEMMAP { [MarshalAs(UnmanagedType.U4)] internal uint dbgpid; // id of debugger [MarshalAs(UnmanagedType.U4)] internal uint fOption; // 1 - start debugging, 0 - stop debugging [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] internal byte[] rgbMachineName; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] internal byte[] rgbDllName; [MarshalAs(UnmanagedType.U4)] internal uint cbData; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)] internal byte[] rgbData; } } // System.Data.SqlClient namespace // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //----------------------------------------------------------------------------- [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Data.DataSetExtensions, PublicKey="+AssemblyRef.EcmaPublicKeyFull)] // DevDiv Bugs 92166 [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Data.Entity, PublicKey="+AssemblyRef.EcmaPublicKeyFull)] // SQLPT 300000492 namespace System.Data.SqlClient { using System; using System.Collections; using System.Configuration.Assemblies; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Data.ProviderBase; using System.Data.Sql; using System.Data.SqlTypes; using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Runtime.Serialization.Formatters; using System.Text; using System.Threading; using System.Security; using System.Security.Permissions; using System.Reflection; using System.Runtime.Versioning; using Microsoft.SqlServer.Server; [DefaultEvent("InfoMessage")] public sealed partial class SqlConnection: DbConnection, ICloneable { static private readonly object EventInfoMessage = new object(); private SqlDebugContext _sdc; // SQL Debugging support private bool _AsycCommandInProgress; // SQLStatistics support internal SqlStatistics _statistics; private bool _collectstats; private bool _fireInfoMessageEventOnUserErrors; // False by default public SqlConnection(string connectionString) : this() { ConnectionString = connectionString; } private SqlConnection(SqlConnection connection) { // Clone GC.SuppressFinalize(this); CopyFrom(connection); } // // PUBLIC PROPERTIES // // used to start/stop collection of statistics data and do verify the current state // // devnote: start/stop should not performed using a property since it requires execution of code // // start statistics // set the internal flag (_statisticsEnabled) to true. // Create a new SqlStatistics object if not already there. // connect the parser to the object. // if there is no parser at this time we need to connect it after creation. // [ DefaultValue(false), ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.SqlConnection_StatisticsEnabled), ] public bool StatisticsEnabled { get { return (_collectstats); } set { if (IsContextConnection) { if (value) { throw SQL.NotAvailableOnContextConnection(); } } else { if (value) { // start if (ConnectionState.Open == State) { if (null == _statistics) { _statistics = new SqlStatistics(); ADP.TimerCurrent(out _statistics._openTimestamp); } // set statistics on the parser // update timestamp; Debug.Assert(Parser != null, "Where's the parser?"); Parser.Statistics = _statistics; } } else { // stop if (null != _statistics) { if (ConnectionState.Open == State) { // remove statistics from parser // update timestamp; TdsParser parser = Parser; Debug.Assert(parser != null, "Where's the parser?"); parser.Statistics = null; ADP.TimerCurrent(out _statistics._closeTimestamp); } } } this._collectstats = value; } } } internal bool AsycCommandInProgress { get { return (_AsycCommandInProgress); } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] set { _AsycCommandInProgress = value; } } internal bool IsContextConnection { get { SqlConnectionString opt = (SqlConnectionString)ConnectionOptions; bool result = false; if (null != opt) { result = (opt.ContextConnection); } return result; } } internal SqlConnectionString.TransactionBindingEnum TransactionBinding { get { return ((SqlConnectionString)ConnectionOptions).TransactionBinding; } } internal SqlConnectionString.TypeSystem TypeSystem { get { return ((SqlConnectionString)ConnectionOptions).TypeSystemVersion; } } override protected DbProviderFactory DbProviderFactory { get { return SqlClientFactory.Instance; } } [ DefaultValue(""), #pragma warning disable 618 // ignore obsolete warning about RecommendedAsConfigurable to use SettingsBindableAttribute RecommendedAsConfigurable(true), #pragma warning restore 618 SettingsBindableAttribute(true), RefreshProperties(RefreshProperties.All), ResCategoryAttribute(Res.DataCategory_Data), Editor("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing), ResDescriptionAttribute(Res.SqlConnection_ConnectionString), ] override public string ConnectionString { get { return ConnectionString_Get(); } set { ConnectionString_Set(value); } } [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescriptionAttribute(Res.SqlConnection_ConnectionTimeout), ] override public int ConnectionTimeout { get { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; return ((null != constr) ? constr.ConnectTimeout : SqlConnectionString.DEFAULT.Connect_Timeout); } } [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescriptionAttribute(Res.SqlConnection_Database), ] override public string Database { // if the connection is open, we need to ask the inner connection what it's // current catalog is because it may have gotten changed, otherwise we can // just return what the connection string had. get { SqlInternalConnection innerConnection = (InnerConnection as SqlInternalConnection); string result; if (null != innerConnection) { result = innerConnection.CurrentDatabase; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; result = ((null != constr) ? constr.InitialCatalog : SqlConnectionString.DEFAULT.Initial_Catalog); } return result; } } [ Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescriptionAttribute(Res.SqlConnection_DataSource), ] override public string DataSource { get { SqlInternalConnection innerConnection = (InnerConnection as SqlInternalConnection); string result; if (null != innerConnection) { result = innerConnection.CurrentDataSource; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; result = ((null != constr) ? constr.DataSource : SqlConnectionString.DEFAULT.Data_Source); } return result; } } [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.SqlConnection_PacketSize), ] public int PacketSize { // if the connection is open, we need to ask the inner connection what it's // current packet size is because it may have gotten changed, otherwise we // can just return what the connection string had. get { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); int result; if (null != innerConnection) { result = innerConnection.PacketSize; } else { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; result = ((null != constr) ? constr.PacketSize : SqlConnectionString.DEFAULT.Packet_Size); } return result; } } [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResDescriptionAttribute(Res.SqlConnection_ServerVersion), ] override public string ServerVersion { get { return GetOpenConnection().ServerVersion; } } internal SqlStatistics Statistics { get { return _statistics; } } [ DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.SqlConnection_WorkstationId), ] public string WorkstationId { get { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } // If not supplied by the user, the default value is the MachineName // Note: In Longhorn you'll be able to rename a machine without // rebooting. Therefore, don't cache this machine name. SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; string result = ((null != constr) ? constr.WorkstationId : null); if (null == result) { // getting machine name requires Environment.Permission // user must have that permission in order to retrieve this result = Environment.MachineName; } return result; } } // // PUBLIC EVENTS // [ ResCategoryAttribute(Res.DataCategory_InfoMessage), ResDescriptionAttribute(Res.DbConnection_InfoMessage), ] public event SqlInfoMessageEventHandler InfoMessage { add { Events.AddHandler(EventInfoMessage, value); } remove { Events.RemoveHandler(EventInfoMessage, value); } } public bool FireInfoMessageEventOnUserErrors { get { return _fireInfoMessageEventOnUserErrors; } set { _fireInfoMessageEventOnUserErrors = value; } } // // PUBLIC METHODS // new public SqlTransaction BeginTransaction() { // this is just a delegate. The actual method tracks executiontime return BeginTransaction(IsolationLevel.Unspecified, null); } new public SqlTransaction BeginTransaction(IsolationLevel iso) { // this is just a delegate. The actual method tracks executiontime return BeginTransaction(iso, null); } public SqlTransaction BeginTransaction(string transactionName) { // Use transaction names only on the outermost pair of nested // BEGIN...COMMIT or BEGIN...ROLLBACK statements. Transaction names // are ignored for nested BEGIN's. The only way to rollback a nested // transaction is to have a save point from a SAVE TRANSACTION call. return BeginTransaction(IsolationLevel.Unspecified, transactionName); } public SqlTransaction BeginTransaction(IsolationLevel iso, string transactionName) { SqlStatistics statistics = null; IntPtr hscp; string xactName = ADP.IsEmpty(transactionName)? "None" : transactionName; Bid.ScopeEnter(out hscp, "%d#, iso=%d{ds.IsolationLevel}, transactionName='%ls'\n", ObjectID, (int)iso, xactName); try { statistics = SqlStatistics.StartTimer(Statistics); // NOTE: we used to throw an exception if the transaction name was empty // (see MDAC 50292) but that was incorrect because we have a BeginTransaction // method that doesn't have a transactionName argument. SqlTransaction transaction = GetOpenConnection().BeginSqlTransaction(iso, transactionName); // SQLBU 503873 The GetOpenConnection line above doesn't keep a ref on the outer connection (this), // and it could be collected before the inner connection can hook it to the transaction, resulting in // a transaction with a null connection property. Use GC.KeepAlive to ensure this doesn't happen. GC.KeepAlive(this); return transaction; } finally { Bid.ScopeLeave(ref hscp); SqlStatistics.StopTimer(statistics); } } override public void ChangeDatabase(string database) { SqlStatistics statistics = null; SNIHandle bestEffortCleanupTarget = null; RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(this); statistics = SqlStatistics.StartTimer(Statistics); InnerConnection.ChangeDatabase(database); } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException e) { Abort(e); throw; } catch (System.StackOverflowException e) { Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { Abort(e); SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } finally { SqlStatistics.StopTimer(statistics); } } static public void ClearAllPools() { (new SqlClientPermission(PermissionState.Unrestricted)).Demand(); SqlConnectionFactory.SingletonInstance.ClearAllPools(); } static public void ClearPool(SqlConnection connection) { ADP.CheckArgumentNull(connection, "connection"); DbConnectionOptions connectionOptions = connection.UserConnectionOptions; if (null != connectionOptions) { connectionOptions.DemandPermission(); if (connection.IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } SqlConnectionFactory.SingletonInstance.ClearPool(connection); } } object ICloneable.Clone() { SqlConnection clone = new SqlConnection(this); Bid.Trace(" %d#, clone=%d#\n", ObjectID, clone.ObjectID); return clone; } override public void Close() { IntPtr hscp; Bid.ScopeEnter(out hscp, " %d#" , ObjectID); try { SqlStatistics statistics = null; SNIHandle bestEffortCleanupTarget = null; RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(this); statistics = SqlStatistics.StartTimer(Statistics); // The lock here is to protect against the command.cancel / connection.close race condition // The SqlInternalConnectionTds is set to OpenBusy during close, once this happens the cast below will fail and // the command will no longer be cancelable. It might be desirable to be able to cancel the close opperation, but this is // outside of the scope of Whidbey RTM. See (SqlCommand::Cancel) for other lock. lock (InnerConnection) { InnerConnection.CloseConnection(this, ConnectionFactory); } // does not require GC.KeepAlive(this) because of OnStateChange if (null != Statistics) { ADP.TimerCurrent(out _statistics._closeTimestamp); } } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException e) { Abort(e); throw; } catch (System.StackOverflowException e) { Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { Abort(e); SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } finally { SqlStatistics.StopTimer(statistics); } } finally { SqlDebugContext sdc = _sdc; _sdc = null; Bid.ScopeLeave(ref hscp); if (sdc != null) { sdc.Dispose(); } } } new public SqlCommand CreateCommand() { return new SqlCommand(null, this); } private void DisposeMe(bool disposing) { // MDAC 65459 } public void EnlistDistributedTransaction(System.EnterpriseServices.ITransaction transaction) { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } EnlistDistributedTransactionHelper(transaction); } override public void Open() { IntPtr hscp; Bid.ScopeEnter(out hscp, " %d#", ObjectID) ; try { if (StatisticsEnabled) { if (null == _statistics) { _statistics = new SqlStatistics(); } else { _statistics.ContinueOnNewConnection(); } } SNIHandle bestEffortCleanupTarget = null; SqlStatistics statistics = null; RuntimeHelpers.PrepareConstrainedRegions(); try { #if DEBUG TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); RuntimeHelpers.PrepareConstrainedRegions(); try { tdsReliabilitySection.Start(); #else { #endif //DEBUG statistics = SqlStatistics.StartTimer(Statistics); InnerConnection.OpenConnection(this, ConnectionFactory); // does not require GC.KeepAlive(this) because of OnStateChange // GetBestEffortCleanup must happen AFTER OpenConnection to get the correct target. bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(this); SqlInternalConnectionSmi innerConnection = (InnerConnection as SqlInternalConnectionSmi); if (null != innerConnection) { innerConnection.AutomaticEnlistment(); } else { Debug.Assert(Parser != null, "Where's the parser?"); if (StatisticsEnabled) { ADP.TimerCurrent(out _statistics._openTimestamp); Parser.Statistics = _statistics; } else { Parser.Statistics = null; _statistics = null; // in case of previous Open/Close/reset_CollectStats sequence } CompleteOpen(); } } #if DEBUG finally { tdsReliabilitySection.Stop(); } #endif //DEBUG } catch (System.OutOfMemoryException e) { Abort(e); throw; } catch (System.StackOverflowException e) { Abort(e); throw; } catch (System.Threading.ThreadAbortException e) { Abort(e); SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); throw; } finally { SqlStatistics.StopTimer(statistics); } } finally { Bid.ScopeLeave(ref hscp) ; } } // // INTERNAL PROPERTIES // internal bool HasLocalTransaction { get { return GetOpenConnection().HasLocalTransaction; } } internal bool HasLocalTransactionFromAPI { get { return GetOpenConnection().HasLocalTransactionFromAPI; } } internal bool IsShiloh { get { return GetOpenConnection().IsShiloh; } } internal bool IsYukonOrNewer { get { return GetOpenConnection().IsYukonOrNewer; } } internal bool IsKatmaiOrNewer { get { return GetOpenConnection().IsKatmaiOrNewer; } } internal TdsParser Parser { get { SqlInternalConnectionTds tdsConnection = (GetOpenConnection() as SqlInternalConnectionTds); if (null == tdsConnection) { throw SQL.NotAvailableOnContextConnection(); } return tdsConnection.Parser; } } internal bool Asynchronous { get { SqlConnectionString constr = (SqlConnectionString)ConnectionOptions; return ((null != constr) ? constr.Asynchronous : SqlConnectionString.DEFAULT.Asynchronous); } } // // INTERNAL METHODS // internal void AddPreparedCommand(SqlCommand cmd) { GetOpenConnection().AddPreparedCommand(cmd); } internal void ValidateConnectionForExecute(string method, SqlCommand command) { SqlInternalConnection innerConnection = GetOpenConnection(method); innerConnection.ValidateConnectionForExecute(command); } // Surround name in brackets and then escape any end bracket to protect against SQL Injection. // NOTE: if the user escapes it themselves it will not work, but this was the case in V1 as well // as native OleDb and Odbc. static internal string FixupDatabaseTransactionName(string name) { if (!ADP.IsEmpty(name)) { return SqlServerEscapeHelper.EscapeIdentifier(name); } else { return name; } } internal void OnError(SqlException exception, bool breakConnection) { Debug.Assert(exception != null && exception.Errors.Count != 0, "SqlConnection: OnError called with null or empty exception!"); // Bug fix - MDAC 49022 - connection open after failure... Problem was parser was passing // Open as a state - because the parser's connection to the netlib was open. We would // then set the connection state to the parser's state - which is not correct. The only // time the connection state should change to what is passed in to this function is if // the parser is broken, then we should be closed. Changed to passing in // TdsParserState, not ConnectionState. // fixed by [....] if (breakConnection && (ConnectionState.Open == State)) { Bid.Trace(" %d#, Connection broken.\n", ObjectID) ; this.Close(); } if (exception.Class >= TdsEnums.MIN_ERROR_CLASS) { // It is an error, and should be thrown. Class of TdsEnums.MIN_ERROR_CLASS or above is an error, // below TdsEnums.MIN_ERROR_CLASS denotes an info message. throw exception; } else { // If it is a class < TdsEnums.MIN_ERROR_CLASS, it is a warning collection - so pass to handler this.OnInfoMessage(new SqlInfoMessageEventArgs(exception)); } } internal void RemovePreparedCommand(SqlCommand cmd) { GetOpenConnection().RemovePreparedCommand(cmd); } // // PRIVATE METHODS // // SxS: using Debugger.IsAttached // [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] private void CompleteOpen() { Debug.Assert(ConnectionState.Open == State, "CompleteOpen not open"); // be sure to mark as open so SqlDebugCheck can issue Query // check to see if we need to hook up sql-debugging if a debugger is attached // We only need this check for Shiloh and earlier servers. if (!GetOpenConnection().IsYukonOrNewer && System.Diagnostics.Debugger.IsAttached) { bool debugCheck = false; try { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); // MDAC 66682, 69017 debugCheck = true; } catch (SecurityException e) { ADP.TraceExceptionWithoutRethrow(e); } if (debugCheck) { // if we don't have Unmanaged code permission, don't check for debugging // but let the connection be opened while under the debugger CheckSQLDebugOnConnect(); } } } internal SqlInternalConnection GetOpenConnection() { SqlInternalConnection innerConnection = (InnerConnection as SqlInternalConnection); if (null == innerConnection) { throw ADP.ClosedConnectionError(); } return innerConnection; } internal SqlInternalConnection GetOpenConnection(string method) { DbConnectionInternal innerConnection = InnerConnection; SqlInternalConnection innerSqlConnection = (innerConnection as SqlInternalConnection); if (null == innerSqlConnection) { throw ADP.OpenConnectionRequired(method, innerConnection.State); } return innerSqlConnection; } internal SqlInternalConnectionTds GetOpenTdsConnection() { SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); if (null == innerConnection) { throw ADP.ClosedConnectionError(); } return innerConnection; } internal SqlInternalConnectionTds GetOpenTdsConnection(string method) { SqlInternalConnectionTds innerConnection = (InnerConnection as SqlInternalConnectionTds); if (null == innerConnection) { throw ADP.OpenConnectionRequired(method, innerConnection.State); } return innerConnection; } internal void OnInfoMessage(SqlInfoMessageEventArgs imevent) { if (Bid.TraceOn) { Debug.Assert(null != imevent, "null SqlInfoMessageEventArgs"); Bid.Trace(" %d#, Message='%ls'\n", ObjectID, ((null != imevent) ? imevent.Message : "")); } SqlInfoMessageEventHandler handler = (SqlInfoMessageEventHandler)Events[EventInfoMessage]; if (null != handler) { try { handler(this, imevent); } catch (Exception e) { // MDAC 53175 if (!ADP.IsCatchableOrSecurityExceptionType(e)) { throw; } ADP.TraceExceptionWithoutRethrow(e); } } } // // SQL DEBUGGING SUPPORT // // this only happens once per connection // SxS: using named file mapping APIs // [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private void CheckSQLDebugOnConnect() { IntPtr hFileMap; uint pid = (uint)SafeNativeMethods.GetCurrentProcessId(); string mapFileName; // If Win2k or later, prepend "Global\\" to enable this to work through TerminalServices. if (ADP.IsPlatformNT5) { mapFileName = "Global\\" + TdsEnums.SDCI_MAPFILENAME; } else { mapFileName = TdsEnums.SDCI_MAPFILENAME; } mapFileName = mapFileName + pid.ToString(CultureInfo.InvariantCulture); hFileMap = NativeMethods.OpenFileMappingA(0x4/*FILE_MAP_READ*/, false, mapFileName); if (ADP.PtrZero != hFileMap) { IntPtr pMemMap = NativeMethods.MapViewOfFile(hFileMap, 0x4/*FILE_MAP_READ*/, 0, 0, IntPtr.Zero); if (ADP.PtrZero != pMemMap) { SqlDebugContext sdc = new SqlDebugContext(); sdc.hMemMap = hFileMap; sdc.pMemMap = pMemMap; sdc.pid = pid; // optimization: if we only have to refresh memory-mapped data at connection open time // optimization: then call here instead of in CheckSQLDebug() which gets called // optimization: at command execution time // RefreshMemoryMappedData(sdc); // delaying setting out global state until after we issue this first SQLDebug command so that // we don't reentrantly call into CheckSQLDebug CheckSQLDebug(sdc); // now set our global state _sdc = sdc; } } } // This overload is called by the Command object when executing stored procedures. Note that // if SQLDebug has never been called, it is a noop. internal void CheckSQLDebug() { if (null != _sdc) CheckSQLDebug(_sdc); } // SxS: using GetCurrentThreadId [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] // MDAC 66682, 69017 private void CheckSQLDebug(SqlDebugContext sdc) { // check to see if debugging has been activated Debug.Assert(null != sdc, "SQL Debug: invalid null debugging context!"); #pragma warning disable 618 uint tid = (uint)AppDomain.GetCurrentThreadId(); // Sql Debugging doesn't need fiber support; #pragma warning restore 618 RefreshMemoryMappedData(sdc); // // If we get here, the debugger must be hooked up. if (!sdc.active) { if (sdc.fOption/*TdsEnums.SQLDEBUG_ON*/) { // turn on sdc.active = true; sdc.tid = tid; try { IssueSQLDebug(TdsEnums.SQLDEBUG_ON, sdc.machineName, sdc.pid, sdc.dbgpid, sdc.sdiDllName, sdc.data); sdc.tid = 0; // reset so that the first successful time through, we notify the server of the context switch } catch { sdc.active = false; throw; } } } // be sure to pick up thread context switch, especially the first time through if (sdc.active) { if (!sdc.fOption/*TdsEnums.SQLDEBUG_OFF*/) { // turn off and free the memory sdc.Dispose(); // okay if we throw out here, no state to clean up IssueSQLDebug(TdsEnums.SQLDEBUG_OFF, null, 0, 0, null, null); } else { // notify server of context change if (sdc.tid != tid) { sdc.tid = tid; try { IssueSQLDebug(TdsEnums.SQLDEBUG_CONTEXT, null, sdc.pid, sdc.tid, null, null); } catch { sdc.tid = 0; throw; } } } } } private void IssueSQLDebug(uint option, string machineName, uint pid, uint id, string sdiDllName, byte[] data) { if (GetOpenConnection().IsYukonOrNewer) { // return; } // SqlCommand c = new SqlCommand(TdsEnums.SP_SDIDEBUG, this); c.CommandType = CommandType.StoredProcedure; // context param SqlParameter p = new SqlParameter(null, SqlDbType.VarChar, TdsEnums.SQLDEBUG_MODE_NAMES[option].Length); p.Value = TdsEnums.SQLDEBUG_MODE_NAMES[option]; c.Parameters.Add(p); if (option == TdsEnums.SQLDEBUG_ON) { // debug dll name p = new SqlParameter(null, SqlDbType.VarChar, sdiDllName.Length); p.Value = sdiDllName; c.Parameters.Add(p); // debug machine name p = new SqlParameter(null, SqlDbType.VarChar, machineName.Length); p.Value = machineName; c.Parameters.Add(p); } if (option != TdsEnums.SQLDEBUG_OFF) { // client pid p = new SqlParameter(null, SqlDbType.Int); p.Value = pid; c.Parameters.Add(p); // dbgpid or tid p = new SqlParameter(null, SqlDbType.Int); p.Value = id; c.Parameters.Add(p); } if (option == TdsEnums.SQLDEBUG_ON) { // debug data p = new SqlParameter(null, SqlDbType.VarBinary, (null != data) ? data.Length : 0); p.Value = data; c.Parameters.Add(p); } c.ExecuteNonQuery(); } public static void ChangePassword(string connectionString, string newPassword) { IntPtr hscp; Bid.ScopeEnter(out hscp, " ") ; try { if (ADP.IsEmpty(connectionString)) { throw SQL.ChangePasswordArgumentMissing("connectionString"); } if (ADP.IsEmpty(newPassword)) { throw SQL.ChangePasswordArgumentMissing("newPassword"); } if (TdsEnums.MAXLEN_NEWPASSWORD < newPassword.Length) { throw ADP.InvalidArgumentLength("newPassword", TdsEnums.MAXLEN_NEWPASSWORD); } SqlConnectionString connectionOptions = SqlConnectionFactory.FindSqlConnectionOptions(connectionString); if (connectionOptions.IntegratedSecurity) { throw SQL.ChangePasswordConflictsWithSSPI(); } if (! ADP.IsEmpty(connectionOptions.AttachDBFilename)) { throw SQL.ChangePasswordUseOfUnallowedKey(SqlConnectionString.KEY.AttachDBFilename); } if (connectionOptions.ContextConnection) { throw SQL.ChangePasswordUseOfUnallowedKey(SqlConnectionString.KEY.Context_Connection); } System.Security.PermissionSet permissionSet = connectionOptions.CreatePermissionSet(); permissionSet.Demand(); // note: This is the only case where we directly construt the internal connection, passing in the new password. // Normally we would simply create a regular connectoin and open it but there is no other way to pass the // new password down to the constructor. Also it would have an unwanted impact on the connection pool // using (SqlInternalConnectionTds con = new SqlInternalConnectionTds(null, connectionOptions, null, newPassword, (SqlConnection)null, false)) { if (!con.IsYukonOrNewer) { throw SQL.ChangePasswordRequiresYukon(); } } SqlConnectionFactory.SingletonInstance.ClearPool(connectionString); } finally { Bid.ScopeLeave(ref hscp) ; } } // updates our context with any changes made to the memory-mapped data by an external process static private void RefreshMemoryMappedData(SqlDebugContext sdc) { Debug.Assert(ADP.PtrZero != sdc.pMemMap, "SQL Debug: invalid null value for pMemMap!"); // copy memory mapped file contents into managed types MEMMAP memMap = (MEMMAP)Marshal.PtrToStructure(sdc.pMemMap, typeof(MEMMAP)); sdc.dbgpid = memMap.dbgpid; sdc.fOption = (memMap.fOption == 1) ? true : false; // xlate ansi byte[] -> managed strings Encoding cp = System.Text.Encoding.GetEncoding(TdsEnums.DEFAULT_ENGLISH_CODE_PAGE_VALUE); sdc.machineName = cp.GetString(memMap.rgbMachineName, 0, memMap.rgbMachineName.Length); sdc.sdiDllName = cp.GetString(memMap.rgbDllName, 0, memMap.rgbDllName.Length); // just get data reference sdc.data = memMap.rgbData; } public void ResetStatistics() { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } if (null != Statistics) { Statistics.Reset(); if (ConnectionState.Open == State) { // update timestamp; ADP.TimerCurrent(out _statistics._openTimestamp); } } } public IDictionary RetrieveStatistics() { if (IsContextConnection) { throw SQL.NotAvailableOnContextConnection(); } if (null != Statistics) { UpdateStatistics(); return Statistics.GetHashtable(); } else { return new SqlStatistics().GetHashtable(); } } private void UpdateStatistics() { if (ConnectionState.Open == State) { // update timestamp ADP.TimerCurrent(out _statistics._closeTimestamp); } // delegate the rest of the work to the SqlStatistics class Statistics.UpdateStatistics(); } // // UDT SUPPORT // // internal static void CheckGetExtendedUDTInfo(SqlMetaDataPriv metaData, bool fThrow) { if (metaData.udtType == null) { // If null, we have not obtained extended info. Debug.Assert(!ADP.IsEmpty(metaData.udtAssemblyQualifiedName), "Unexpected state on GetUDTInfo"); // 2nd argument determines whether exception from Assembly.Load is thrown. metaData.udtType = Type.GetType(metaData.udtAssemblyQualifiedName, fThrow); if (fThrow && metaData.udtType == null) { // throw SQL.UDTUnexpectedResult(metaData.udtAssemblyQualifiedName); } } } internal object GetUdtValue(object value, SqlMetaDataPriv metaData, bool returnDBNull) { if (returnDBNull && ADP.IsNull(value)) { return DBNull.Value; } object o = null; // Since the serializer doesn't handle nulls... if (ADP.IsNull(value)) { Type t = metaData.udtType; Debug.Assert(t != null, "Unexpected null of udtType on GetUdtValue!"); o = t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new Object[]{}, CultureInfo.InvariantCulture); Debug.Assert(o != null); return o; } else { MemoryStream stm = new MemoryStream((byte[]) value); o = SerializationHelperSql9.Deserialize(stm, metaData.udtType); Debug.Assert(o != null, "object could NOT be created"); return o; } } internal byte[] GetBytes(object o) { Microsoft.SqlServer.Server.Format format = Microsoft.SqlServer.Server.Format.Native; int maxSize = 0; return GetBytes(o, out format, out maxSize); } internal byte[] GetBytes(object o, out Microsoft.SqlServer.Server.Format format, out int maxSize) { SqlUdtInfo attr = AssemblyCache.GetInfoFromType(o.GetType()); maxSize = attr.MaxByteSize; format = attr.SerializationFormat; if (maxSize < -1 || maxSize >= UInt16.MaxValue) { // Do we need this? Is this the right place? throw new InvalidOperationException(o.GetType() + ": invalid Size"); } byte[] retval; using (MemoryStream stm = new MemoryStream(maxSize < 0 ? 0 : maxSize)) { SerializationHelperSql9.Serialize(stm, o); retval = stm.ToArray(); } return retval; } } // SqlConnection // [ ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("afef65ad-4577-447a-a148-83acadd3d4b9"), ] [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")] public sealed class SQLDebugging: ISQLDebug { // Security stuff const int STANDARD_RIGHTS_REQUIRED = (0x000F0000); const int DELETE = (0x00010000); const int READ_CONTROL = (0x00020000); const int WRITE_DAC = (0x00040000); const int WRITE_OWNER = (0x00080000); const int SYNCHRONIZE = (0x00100000); const int FILE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x000001FF); const uint GENERIC_READ = (0x80000000); const uint GENERIC_WRITE = (0x40000000); const uint GENERIC_EXECUTE = (0x20000000); const uint GENERIC_ALL = (0x10000000); const int SECURITY_DESCRIPTOR_REVISION = (1); const int ACL_REVISION = (2); const int SECURITY_AUTHENTICATED_USER_RID = (0x0000000B); const int SECURITY_LOCAL_SYSTEM_RID = (0x00000012); const int SECURITY_BUILTIN_DOMAIN_RID = (0x00000020); const int SECURITY_WORLD_RID = (0x00000000); const byte SECURITY_NT_AUTHORITY = 5; const int DOMAIN_GROUP_RID_ADMINS = (0x00000200); const int DOMAIN_ALIAS_RID_ADMINS = (0x00000220); const int sizeofSECURITY_ATTRIBUTES = 12; // sizeof(SECURITY_ATTRIBUTES); const int sizeofSECURITY_DESCRIPTOR = 20; // sizeof(SECURITY_DESCRIPTOR); const int sizeofACCESS_ALLOWED_ACE = 12; // sizeof(ACCESS_ALLOWED_ACE); const int sizeofACCESS_DENIED_ACE = 12; // sizeof(ACCESS_DENIED_ACE); const int sizeofSID_IDENTIFIER_AUTHORITY = 6; // sizeof(SID_IDENTIFIER_AUTHORITY) const int sizeofACL = 8; // sizeof(ACL); private IntPtr CreateSD(ref IntPtr pDacl) { IntPtr pSecurityDescriptor = IntPtr.Zero; IntPtr pUserSid = IntPtr.Zero; IntPtr pAdminSid = IntPtr.Zero; IntPtr pNtAuthority = IntPtr.Zero; int cbAcl = 0; bool status = false; pNtAuthority = Marshal.AllocHGlobal(sizeofSID_IDENTIFIER_AUTHORITY); if (pNtAuthority == IntPtr.Zero) goto cleanup; Marshal.WriteInt32(pNtAuthority, 0, 0); Marshal.WriteByte(pNtAuthority, 4, 0); Marshal.WriteByte(pNtAuthority, 5, SECURITY_NT_AUTHORITY); status = NativeMethods.AllocateAndInitializeSid( pNtAuthority, (byte)1, SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0, ref pUserSid); if (!status || pUserSid == IntPtr.Zero) { goto cleanup; } status = NativeMethods.AllocateAndInitializeSid( pNtAuthority, (byte)2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, ref pAdminSid); if (!status || pAdminSid == IntPtr.Zero) { goto cleanup; } status = false; pSecurityDescriptor = Marshal.AllocHGlobal(sizeofSECURITY_DESCRIPTOR); if (pSecurityDescriptor == IntPtr.Zero) { goto cleanup; } for (int i = 0; i < sizeofSECURITY_DESCRIPTOR; i++) Marshal.WriteByte(pSecurityDescriptor, i, (byte)0); cbAcl = sizeofACL + (2 * (sizeofACCESS_ALLOWED_ACE)) + sizeofACCESS_DENIED_ACE + NativeMethods.GetLengthSid(pUserSid) + NativeMethods.GetLengthSid(pAdminSid); pDacl = Marshal.AllocHGlobal(cbAcl); if (pDacl == IntPtr.Zero) { goto cleanup; } // rights must be added in a certain order. Namely, deny access first, then add access if (NativeMethods.InitializeAcl(pDacl, cbAcl, ACL_REVISION)) if (NativeMethods.AddAccessDeniedAce(pDacl, ACL_REVISION, WRITE_DAC, pUserSid)) if (NativeMethods.AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_READ, pUserSid)) if (NativeMethods.AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_ALL, pAdminSid)) if (NativeMethods.InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) if (NativeMethods.SetSecurityDescriptorDacl(pSecurityDescriptor, true, pDacl, false)) { status = true; } cleanup : if (pNtAuthority != IntPtr.Zero) { Marshal.FreeHGlobal(pNtAuthority); } if (pAdminSid != IntPtr.Zero) NativeMethods.FreeSid(pAdminSid); if (pUserSid != IntPtr.Zero) NativeMethods.FreeSid(pUserSid); if (status) return pSecurityDescriptor; else { if (pSecurityDescriptor != IntPtr.Zero) { Marshal.FreeHGlobal(pSecurityDescriptor); } } return IntPtr.Zero; } // SxS: using file mapping API (CreateFileMapping) // [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] bool ISQLDebug.SQLDebug(int dwpidDebugger, int dwpidDebuggee, [MarshalAs(UnmanagedType.LPStr)] string pszMachineName, [MarshalAs(UnmanagedType.LPStr)] string pszSDIDLLName, int dwOption, int cbData, byte[] rgbData) { bool result = false; IntPtr hFileMap = IntPtr.Zero; IntPtr pMemMap = IntPtr.Zero; IntPtr pSecurityDescriptor = IntPtr.Zero; IntPtr pSecurityAttributes = IntPtr.Zero; IntPtr pDacl = IntPtr.Zero; // validate the structure if (null == pszMachineName || null == pszSDIDLLName) return false; if (pszMachineName.Length > TdsEnums.SDCI_MAX_MACHINENAME || pszSDIDLLName.Length > TdsEnums.SDCI_MAX_DLLNAME) return false; // note that these are ansi strings Encoding cp = System.Text.Encoding.GetEncoding(TdsEnums.DEFAULT_ENGLISH_CODE_PAGE_VALUE); byte[] rgbMachineName = cp.GetBytes(pszMachineName); byte[] rgbSDIDLLName = cp.GetBytes(pszSDIDLLName); if (null != rgbData && cbData > TdsEnums.SDCI_MAX_DATA) return false; string mapFileName; // If Win2k or later, prepend "Global\\" to enable this to work through TerminalServices. if (ADP.IsPlatformNT5) { mapFileName = "Global\\" + TdsEnums.SDCI_MAPFILENAME; } else { mapFileName = TdsEnums.SDCI_MAPFILENAME; } mapFileName = mapFileName + dwpidDebuggee.ToString(CultureInfo.InvariantCulture); // Create Security Descriptor pSecurityDescriptor = CreateSD(ref pDacl); pSecurityAttributes = Marshal.AllocHGlobal(sizeofSECURITY_ATTRIBUTES); if ((pSecurityDescriptor == IntPtr.Zero) || (pSecurityAttributes == IntPtr.Zero)) return false; Marshal.WriteInt32(pSecurityAttributes, 0, sizeofSECURITY_ATTRIBUTES); // nLength = sizeof(SECURITY_ATTRIBUTES) Marshal.WriteIntPtr(pSecurityAttributes, 4, pSecurityDescriptor); // lpSecurityDescriptor = pSecurityDescriptor Marshal.WriteInt32(pSecurityAttributes, 8, 0); // bInheritHandle = FALSE hFileMap = NativeMethods.CreateFileMappingA( ADP.InvalidPtr/*INVALID_HANDLE_VALUE*/, pSecurityAttributes, 0x4/*PAGE_READWRITE*/, 0, Marshal.SizeOf(typeof(MEMMAP)), mapFileName); if (IntPtr.Zero == hFileMap) { goto cleanup; } pMemMap = NativeMethods.MapViewOfFile(hFileMap, 0x6/*FILE_MAP_READ|FILE_MAP_WRITE*/, 0, 0, IntPtr.Zero); if (IntPtr.Zero == pMemMap) { goto cleanup; } // copy data to memory-mapped file // layout of MEMMAP structure is: // uint dbgpid // uint fOption // byte[32] machineName // byte[16] sdiDllName // uint dbData // byte[255] vData int offset = 0; Marshal.WriteInt32(pMemMap, offset, (int)dwpidDebugger); offset += 4; Marshal.WriteInt32(pMemMap, offset, (int)dwOption); offset += 4; Marshal.Copy(rgbMachineName, 0, ADP.IntPtrOffset(pMemMap, offset), rgbMachineName.Length); offset += TdsEnums.SDCI_MAX_MACHINENAME; Marshal.Copy(rgbSDIDLLName, 0, ADP.IntPtrOffset(pMemMap, offset), rgbSDIDLLName.Length); offset += TdsEnums.SDCI_MAX_DLLNAME; Marshal.WriteInt32(pMemMap, offset, (int)cbData); offset += 4; if (null != rgbData) { Marshal.Copy(rgbData, 0, ADP.IntPtrOffset(pMemMap, offset), (int)cbData); } NativeMethods.UnmapViewOfFile(pMemMap); result = true; cleanup : if (result == false) { if (hFileMap != IntPtr.Zero) NativeMethods.CloseHandle(hFileMap); } if (pSecurityAttributes != IntPtr.Zero) Marshal.FreeHGlobal(pSecurityAttributes); if (pSecurityDescriptor != IntPtr.Zero) Marshal.FreeHGlobal(pSecurityDescriptor); if (pDacl != IntPtr.Zero) Marshal.FreeHGlobal(pDacl); return result; } } // this is a private interface to com+ users // do not change this guid [ ComImport, ComVisible(true), Guid("6cb925bf-c3c0-45b3-9f44-5dd67c7b7fe8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), BestFitMapping(false, ThrowOnUnmappableChar = true), ] interface ISQLDebug { [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name = "FullTrust")] bool SQLDebug( int dwpidDebugger, int dwpidDebuggee, [MarshalAs(UnmanagedType.LPStr)] string pszMachineName, [MarshalAs(UnmanagedType.LPStr)] string pszSDIDLLName, int dwOption, int cbData, byte[] rgbData); } sealed class SqlDebugContext: IDisposable { // context data internal uint pid = 0; internal uint tid = 0; internal bool active = false; // memory-mapped data internal IntPtr pMemMap = ADP.PtrZero; internal IntPtr hMemMap = ADP.PtrZero; internal uint dbgpid = 0; internal bool fOption = false; internal string machineName = null; internal string sdiDllName = null; internal byte[] data = null; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // using CloseHandle and UnmapViewOfFile - no exposure [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private void Dispose(bool disposing) { if (disposing) { // Nothing to do here ; } if (pMemMap != IntPtr.Zero) { NativeMethods.UnmapViewOfFile(pMemMap); pMemMap = IntPtr.Zero; } if (hMemMap != IntPtr.Zero) { NativeMethods.CloseHandle(hMemMap); hMemMap = IntPtr.Zero; } active = false; } ~SqlDebugContext() { Dispose(false); } } // native interop memory mapped structure for sdi debugging [StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)] internal struct MEMMAP { [MarshalAs(UnmanagedType.U4)] internal uint dbgpid; // id of debugger [MarshalAs(UnmanagedType.U4)] internal uint fOption; // 1 - start debugging, 0 - stop debugging [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] internal byte[] rgbMachineName; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] internal byte[] rgbDllName; [MarshalAs(UnmanagedType.U4)] internal uint cbData; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)] internal byte[] rgbData; } } // System.Data.SqlClient namespace // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EditingMode.cs
- MTConfigUtil.cs
- TextFormatterContext.cs
- ToolBarOverflowPanel.cs
- BufferModesCollection.cs
- newinstructionaction.cs
- TabletDevice.cs
- ContextStack.cs
- TextEndOfLine.cs
- URI.cs
- LiteralText.cs
- ViewStateException.cs
- CodeChecksumPragma.cs
- TraceListeners.cs
- HebrewNumber.cs
- ElementUtil.cs
- CuspData.cs
- TemplateLookupAction.cs
- LowerCaseStringConverter.cs
- NetworkCredential.cs
- URLAttribute.cs
- peersecuritysettings.cs
- PngBitmapDecoder.cs
- PkcsMisc.cs
- __Filters.cs
- TextEffect.cs
- ListViewPagedDataSource.cs
- RuntimeHandles.cs
- BlurEffect.cs
- ScrollPattern.cs
- SqlCacheDependencySection.cs
- OrderedHashRepartitionEnumerator.cs
- FrameworkRichTextComposition.cs
- BinarySerializer.cs
- MenuTracker.cs
- SelectedCellsCollection.cs
- CrossContextChannel.cs
- SoapWriter.cs
- AppDomainUnloadedException.cs
- SqlTypeSystemProvider.cs
- HttpHandlersSection.cs
- RawTextInputReport.cs
- __Filters.cs
- BitmapInitialize.cs
- StringCollection.cs
- RoleManagerEventArgs.cs
- Helpers.cs
- BatchWriter.cs
- _AutoWebProxyScriptWrapper.cs
- IImplicitResourceProvider.cs
- FaultCode.cs
- QuadraticBezierSegment.cs
- ListenerElementsCollection.cs
- Serializer.cs
- SecurityIdentifierConverter.cs
- DefaultTextStore.cs
- RowSpanVector.cs
- ProcessModuleCollection.cs
- WebBrowserEvent.cs
- DataAccessor.cs
- FileDialogCustomPlacesCollection.cs
- DbExpressionVisitor.cs
- StringWriter.cs
- CompiledXpathExpr.cs
- DataGridViewRowCollection.cs
- SecurityContextSecurityTokenResolver.cs
- QilIterator.cs
- Adorner.cs
- RIPEMD160Managed.cs
- MutexSecurity.cs
- AdapterSwitches.cs
- StreamInfo.cs
- TextTreeFixupNode.cs
- FileDialog_Vista.cs
- ValidatingReaderNodeData.cs
- WmlLiteralTextAdapter.cs
- VoiceChangeEventArgs.cs
- UnsafeNativeMethods.cs
- MenuItemBinding.cs
- HttpContextBase.cs
- PointValueSerializer.cs
- SqlDataSourceAdvancedOptionsForm.cs
- Listbox.cs
- SymbolResolver.cs
- DropShadowEffect.cs
- LineServices.cs
- TreeViewImageKeyConverter.cs
- BufferedWebEventProvider.cs
- RelationshipConstraintValidator.cs
- LessThanOrEqual.cs
- VersionedStream.cs
- NavigateEvent.cs
- SecurityRequiresReviewAttribute.cs
- RadioButtonList.cs
- DataGridViewDataConnection.cs
- ReflectPropertyDescriptor.cs
- SqlDataSourceConfigureFilterForm.cs
- RayMeshGeometry3DHitTestResult.cs
- RSAProtectedConfigurationProvider.cs
- ListViewItem.cs