From 5383be631341c06b88d7e874d7d8cb962ef2ccf1 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Mon, 4 Mar 2024 06:58:10 +0000 Subject: [PATCH 1/6] Removing direct usage of DbBuffer class from .NET Framework. This now aligns with .NET Core --- .../Data/ProviderBase/DbConnectionPool.cs | 153 ++++-------------- 1 file changed, 30 insertions(+), 123 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs index f39be43eee..8e2aad5992 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs @@ -311,9 +311,8 @@ internal void TransactionEnded(SysTx.Transaction transaction, DbConnectionIntern } - private sealed class PoolWaitHandles : DbBuffer + private sealed class PoolWaitHandles { - private readonly Semaphore _poolSemaphore; private readonly ManualResetEvent _errorEvent; @@ -322,63 +321,19 @@ private sealed class PoolWaitHandles : DbBuffer // Using an AutoResetEvent does not have that complication. private readonly Semaphore _creationSemaphore; - private readonly SafeHandle _poolHandle; - private readonly SafeHandle _errorHandle; - private readonly SafeHandle _creationHandle; - - private readonly int _releaseFlags; + private readonly WaitHandle[] _handlesWithCreate; + private readonly WaitHandle[] _handlesWithoutCreate; [ResourceExposure(ResourceScope.None)] // SxS: this method does not create named objects [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] - internal PoolWaitHandles() : base(3 * IntPtr.Size) + internal PoolWaitHandles() { - bool mustRelease1 = false, mustRelease2 = false, mustRelease3 = false; - _poolSemaphore = new Semaphore(0, MAX_Q_SIZE); _errorEvent = new ManualResetEvent(false); _creationSemaphore = new Semaphore(1, 1); - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - // because SafeWaitHandle doesn't have reliability contract - _poolHandle = _poolSemaphore.SafeWaitHandle; - _errorHandle = _errorEvent.SafeWaitHandle; - _creationHandle = _creationSemaphore.SafeWaitHandle; - - _poolHandle.DangerousAddRef(ref mustRelease1); - _errorHandle.DangerousAddRef(ref mustRelease2); - _creationHandle.DangerousAddRef(ref mustRelease3); - - Debug.Assert(0 == SEMAPHORE_HANDLE, "SEMAPHORE_HANDLE"); - Debug.Assert(1 == ERROR_HANDLE, "ERROR_HANDLE"); - Debug.Assert(2 == CREATION_HANDLE, "CREATION_HANDLE"); - - WriteIntPtr(SEMAPHORE_HANDLE * IntPtr.Size, _poolHandle.DangerousGetHandle()); - WriteIntPtr(ERROR_HANDLE * IntPtr.Size, _errorHandle.DangerousGetHandle()); - WriteIntPtr(CREATION_HANDLE * IntPtr.Size, _creationHandle.DangerousGetHandle()); - } - finally - { - if (mustRelease1) - { - _releaseFlags |= 1; - } - if (mustRelease2) - { - _releaseFlags |= 2; - } - if (mustRelease3) - { - _releaseFlags |= 4; - } - } - } - - internal SafeHandle CreationHandle - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - get { return _creationHandle; } + _handlesWithCreate = new WaitHandle[] { _poolSemaphore, _errorEvent, _creationSemaphore }; + _handlesWithoutCreate = new WaitHandle[] { _poolSemaphore, _errorEvent }; } internal Semaphore CreationSemaphore @@ -396,23 +351,9 @@ internal Semaphore PoolSemaphore get { return _poolSemaphore; } } - protected override bool ReleaseHandle() + internal WaitHandle[] GetHandles(bool withCreate) { - // NOTE: The SafeHandle class guarantees this will be called exactly once. - // we know we can touch these other managed objects because of our original DangerousAddRef - if (0 != (1 & _releaseFlags)) - { - _poolHandle.DangerousRelease(); - } - if (0 != (2 & _releaseFlags)) - { - _errorHandle.DangerousRelease(); - } - if (0 != (4 & _releaseFlags)) - { - _creationHandle.DangerousRelease(); - } - return base.ReleaseHandle(); + return withCreate ? _handlesWithCreate : _handlesWithoutCreate; } } @@ -426,10 +367,7 @@ protected override bool ReleaseHandle() private const int CREATION_HANDLE = (int)0x2; private const int BOGUS_HANDLE = (int)0x3; - private const int WAIT_OBJECT_0 = 0; - private const int WAIT_TIMEOUT = (int)0x102; private const int WAIT_ABANDONED = (int)0x80; - private const int WAIT_FAILED = -1; private const int ERROR_WAIT_DEFAULT = 5 * 1000; // 5 seconds @@ -1351,36 +1289,23 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj if (null == obj) { Interlocked.Increment(ref _waitCount); - uint waitHandleCount = allowCreate ? 3u : 2u; do { int waitResult = BOGUS_HANDLE; - int releaseSemaphoreResult = 0; - bool mustRelease = false; - int waitForMultipleObjectsExHR = 0; RuntimeHelpers.PrepareConstrainedRegions(); try { - _waitHandles.DangerousAddRef(ref mustRelease); - // We absolutely must have the value of waitResult set, // or we may leak the mutex in async abort cases. RuntimeHelpers.PrepareConstrainedRegions(); try { - Debug.Assert(2 == waitHandleCount || 3 == waitHandleCount, "unexpected waithandle count"); } finally { - waitResult = SafeNativeMethods.WaitForMultipleObjectsEx(waitHandleCount, _waitHandles.DangerousGetHandle(), false, waitForMultipleObjectsTimeout, false); - - // VSTFDEVDIV 479551 - call GetHRForLastWin32Error immediately after after the native call - if (waitResult == WAIT_FAILED) - { - waitForMultipleObjectsExHR = Marshal.GetHRForLastWin32Error(); - } + waitResult = WaitHandle.WaitAny(_waitHandles.GetHandles(allowCreate), unchecked((int)waitForMultipleObjectsTimeout)); } // From the WaitAny docs: "If more than one object became signaled during @@ -1391,14 +1316,13 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj switch (waitResult) { - case WAIT_TIMEOUT: + case WaitHandle.WaitTimeout: SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Wait timed out.", ObjectID); Interlocked.Decrement(ref _waitCount); connection = null; return false; case ERROR_HANDLE: - // Throw the error that PoolCreateRequest stashed. SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Errors are set.", ObjectID); Interlocked.Decrement(ref _waitCount); @@ -1443,7 +1367,7 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj { // modify handle array not to wait on creation mutex anymore Debug.Assert(2 == CREATION_HANDLE, "creation handle changed value"); - waitHandleCount = 2; + allowCreate = false; } } } @@ -1488,13 +1412,6 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj } break; - case WAIT_FAILED: - Debug.Assert(waitForMultipleObjectsExHR != 0, "WaitForMultipleObjectsEx failed but waitForMultipleObjectsExHR remained 0"); - SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Wait failed.", ObjectID); - Interlocked.Decrement(ref _waitCount); - Marshal.ThrowExceptionForHR(waitForMultipleObjectsExHR); - goto default; // if ThrowExceptionForHR didn't throw for some reason - case (WAIT_ABANDONED + SEMAPHORE_HANDLE): SqlClientEventSource.Log.TryPoolerTraceEvent(" {0}, Semaphore handle abandonded.", ObjectID); Interlocked.Decrement(ref _waitCount); @@ -1520,21 +1437,9 @@ private bool TryGetConnection(DbConnection owningObject, uint waitForMultipleObj { if (CREATION_HANDLE == waitResult) { - int result = SafeNativeMethods.ReleaseSemaphore(_waitHandles.CreationHandle.DangerousGetHandle(), 1, IntPtr.Zero); - if (0 == result) - { // failure case - releaseSemaphoreResult = Marshal.GetHRForLastWin32Error(); - } - } - if (mustRelease) - { - _waitHandles.DangerousRelease(); + _waitHandles.CreationSemaphore.Release(1); } } - if (0 != releaseSemaphoreResult) - { - Marshal.ThrowExceptionForHR(releaseSemaphoreResult); // will only throw if (hresult < 0) - } // Do not use this pooled connection if access token is about to expire soon before we can connect. if (null != obj && obj.IsAccessTokenExpired) @@ -1708,15 +1613,11 @@ private void PoolCreateRequest(object state) { return; } - bool mustRelease = false; int waitResult = BOGUS_HANDLE; - uint timeout = (uint)CreationTimeout; RuntimeHelpers.PrepareConstrainedRegions(); try { - _waitHandles.DangerousAddRef(ref mustRelease); - // Obtain creation mutex so we're the only one creating objects // and we must have the wait result RuntimeHelpers.PrepareConstrainedRegions(); @@ -1724,9 +1625,9 @@ private void PoolCreateRequest(object state) { } finally { - waitResult = SafeNativeMethods.WaitForSingleObjectEx(_waitHandles.CreationHandle.DangerousGetHandle(), timeout, false); + waitResult = WaitHandle.WaitAny(_waitHandles.GetHandles(withCreate: true), CreationTimeout); } - if (WAIT_OBJECT_0 == waitResult) + if (CREATION_HANDLE == waitResult) { DbConnectionInternal newObj; @@ -1735,9 +1636,19 @@ private void PoolCreateRequest(object state) { while (NeedToReplenish) { - // Don't specify any user options because there is no outer connection associated with the new connection - newObj = CreateObject(owningObject: null, userOptions: null, oldConnection: null); - + try + { + // Don't specify any user options because there is no outer connection associated with the new connection + newObj = CreateObject(owningObject: null, userOptions: null, oldConnection: null); + } + catch + { + // Catch all the exceptions occuring during CreateObject so that they + // don't emerge as unhandled on the thread pool and don't crash applications + // The error is handled in CreateObject and surfaced to the caller of the Connection Pool + // using the ErrorEvent. Hence it is OK to swallow all exceptions here. + break; + } // We do not need to check error flag here, since we know if // CreateObject returned null, we are in error case. if (null != newObj) @@ -1751,7 +1662,7 @@ private void PoolCreateRequest(object state) } } } - else if (WAIT_TIMEOUT == waitResult) + else if (WaitHandle.WaitTimeout == waitResult) { // do not wait forever and potential block this worker thread // instead wait for a period of time and just requeue to try again @@ -1778,14 +1689,10 @@ private void PoolCreateRequest(object state) } finally { - if (WAIT_OBJECT_0 == waitResult) + if (CREATION_HANDLE == waitResult) { // reuse waitResult and ignore its value - waitResult = SafeNativeMethods.ReleaseSemaphore(_waitHandles.CreationHandle.DangerousGetHandle(), 1, IntPtr.Zero); - } - if (mustRelease) - { - _waitHandles.DangerousRelease(); + _waitHandles.CreationSemaphore.Release(1); } } } From c5d2ce0e27f8d52e8636e0ffcbc03249abfe748f Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Mon, 4 Mar 2024 07:35:46 +0000 Subject: [PATCH 2/6] Merged and cleaned up DbConnectionPoolIdentity --- .../src/Microsoft.Data.SqlClient.csproj | 16 +- .../netfx/src/Microsoft.Data.SqlClient.csproj | 7 +- .../ProviderBase/DbConnectionPoolIdentity.cs | 240 ------------------ .../DbConnectionPoolIdentity.Unix.cs | 0 .../DbConnectionPoolIdentity.Windows.cs | 17 +- .../ProviderBase/DbConnectionPoolIdentity.cs | 3 +- 6 files changed, 36 insertions(+), 247 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs (100%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs (73%) rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs (93%) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 7a3a8e208f..46ef13e510 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -72,6 +72,9 @@ Microsoft\Data\ProviderBase\DbConnectionPoolGroupProviderInfo.cs + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.cs + Microsoft\Data\ProviderBase\DbConnectionPoolOptions.cs @@ -626,7 +629,6 @@ - @@ -758,7 +760,9 @@ - + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Unix.cs + @@ -772,7 +776,9 @@ Common\Interop\Windows\kernel32\Interop.LoadLibraryEx.cs - + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Windows.cs + @@ -809,7 +815,9 @@ - + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Unix.cs + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 97feee8bef..706a0d36e0 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -139,6 +139,12 @@ Microsoft\Data\ProviderBase\DbConnectionPoolGroupProviderInfo.cs + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.cs + + + Microsoft\Data\ProviderBase\DbConnectionPoolIdentity.Windows.cs + Microsoft\Data\ProviderBase\DbConnectionPoolOptions.cs @@ -630,7 +636,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs deleted file mode 100644 index 2bbf57eb76..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs +++ /dev/null @@ -1,240 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.Data.ProviderBase -{ - - using System; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using System.Runtime.Versioning; - using System.Security.Permissions; - using System.Security.Principal; - using Microsoft.Data.Common; - - [Serializable] // Serializable so SqlDependencyProcessDispatcher can marshall cross domain to SqlDependency. - sealed internal class DbConnectionPoolIdentity - { - private const int E_NotImpersonationToken = unchecked((int)0x8007051D); - private const int Win32_CheckTokenMembership = 1; - private const int Win32_GetTokenInformation_1 = 2; - private const int Win32_GetTokenInformation_2 = 3; - private const int Win32_ConvertSidToStringSidW = 4; - private const int Win32_CreateWellKnownSid = 5; - - static public readonly DbConnectionPoolIdentity NoIdentity = new DbConnectionPoolIdentity(String.Empty, false, true); - static private readonly byte[] NetworkSid = (ADP.s_isWindowsNT ? CreateWellKnownSid(WellKnownSidType.NetworkSid) : null); - static private DbConnectionPoolIdentity _lastIdentity = null; - - private readonly string _sidString; - private readonly bool _isRestricted; - private readonly bool _isNetwork; - private readonly int _hashCode; - - private DbConnectionPoolIdentity(string sidString, bool isRestricted, bool isNetwork) - { - _sidString = sidString; - _isRestricted = isRestricted; - _isNetwork = isNetwork; - _hashCode = sidString == null ? 0 : sidString.GetHashCode(); - } - - internal bool IsRestricted - { - get { return _isRestricted; } - } - - internal bool IsNetwork - { - get { return _isNetwork; } - } - - static private byte[] CreateWellKnownSid(WellKnownSidType sidType) - { - // Passing an array as big as it can ever be is a small price to pay for - // not having to P/Invoke twice (once to get the buffer, once to get the data) - - uint length = (uint)SecurityIdentifier.MaxBinaryLength; - byte[] resultSid = new byte[length]; - - // NOTE - We copied this code from System.Security.Principal.Win32.CreateWellKnownSid... - - if (0 == UnsafeNativeMethods.CreateWellKnownSid((int)sidType, null, resultSid, ref length)) - { - IntegratedSecurityError(Win32_CreateWellKnownSid); - } - return resultSid; - } - - override public bool Equals(object value) - { - bool result = ((this == NoIdentity) || (this == value)); - if (!result && (null != value)) - { - DbConnectionPoolIdentity that = ((DbConnectionPoolIdentity)value); - result = ((this._sidString == that._sidString) && (this._isRestricted == that._isRestricted) && (this._isNetwork == that._isNetwork)); - } - return result; - } - - [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)] - static internal WindowsIdentity GetCurrentWindowsIdentity() - { - return WindowsIdentity.GetCurrent(); - } - - [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)] - static private IntPtr GetWindowsIdentityToken(WindowsIdentity identity) - { - return identity.Token; - } - - [ResourceExposure(ResourceScope.None)] // SxS: this method does not create named objects - [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] - static internal DbConnectionPoolIdentity GetCurrent() - { - - // DEVNOTE: GetTokenInfo and EqualSID do not work on 9x. WindowsIdentity does not - // work either on 9x. In fact, after checking with native there is no way - // to validate the user on 9x, so simply don't. It is a known issue in - // native, and we will handle this the same way. - - if (!ADP.s_isWindowsNT) - { - return NoIdentity; - } - - WindowsIdentity identity = GetCurrentWindowsIdentity(); - IntPtr token = GetWindowsIdentityToken(identity); // Free'd by WindowsIdentity. - uint bufferLength = 2048; // Suggested default given by Greg Fee. - uint lengthNeeded = 0; - - IntPtr tokenStruct = IntPtr.Zero; - IntPtr SID; - IntPtr sidStringBuffer = IntPtr.Zero; - bool isNetwork; - - // Win32NativeMethods.IsTokenRestricted will raise exception if the native call fails - bool isRestricted = Win32NativeMethods.IsTokenRestrictedWrapper(token); - - DbConnectionPoolIdentity current = null; - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - if (!UnsafeNativeMethods.CheckTokenMembership(token, NetworkSid, out isNetwork)) - { - // will always fail with 0x8007051D if token is not an impersonation token - IntegratedSecurityError(Win32_CheckTokenMembership); - } - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { } - finally - { - // allocating memory and assigning to tokenStruct must happen - tokenStruct = SafeNativeMethods.LocalAlloc(DbBuffer.LMEM_FIXED, (IntPtr)bufferLength); - } - if (IntPtr.Zero == tokenStruct) - { - throw new OutOfMemoryException(); - } - if (!UnsafeNativeMethods.GetTokenInformation(token, 1, tokenStruct, bufferLength, ref lengthNeeded)) - { - if (lengthNeeded > bufferLength) - { - bufferLength = lengthNeeded; - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { } - finally - { - // freeing token struct and setting tokenstruct to null must happen together - // allocating memory and assigning to tokenStruct must happen - SafeNativeMethods.LocalFree(tokenStruct); - tokenStruct = IntPtr.Zero; // protect against LocalAlloc throwing an exception - tokenStruct = SafeNativeMethods.LocalAlloc(DbBuffer.LMEM_FIXED, (IntPtr)bufferLength); - } - if (IntPtr.Zero == tokenStruct) - { - throw new OutOfMemoryException(); - } - - if (!UnsafeNativeMethods.GetTokenInformation(token, 1, tokenStruct, bufferLength, ref lengthNeeded)) - { - IntegratedSecurityError(Win32_GetTokenInformation_1); - } - } - else - { - IntegratedSecurityError(Win32_GetTokenInformation_2); - } - } - - identity.Dispose(); // Keep identity variable alive until after GetTokenInformation calls. - - - SID = Marshal.ReadIntPtr(tokenStruct, 0); - - if (!UnsafeNativeMethods.ConvertSidToStringSidW(SID, out sidStringBuffer)) - { - IntegratedSecurityError(Win32_ConvertSidToStringSidW); - } - - if (IntPtr.Zero == sidStringBuffer) - { - throw ADP.InternalError(ADP.InternalErrorCode.ConvertSidToStringSidWReturnedNull); - } - - string sidString = Marshal.PtrToStringUni(sidStringBuffer); - - var lastIdentity = _lastIdentity; - if ((lastIdentity != null) && (lastIdentity._sidString == sidString) && (lastIdentity._isRestricted == isRestricted) && (lastIdentity._isNetwork == isNetwork)) - { - current = lastIdentity; - } - else - { - current = new DbConnectionPoolIdentity(sidString, isRestricted, isNetwork); - } - } - finally - { - // Marshal.FreeHGlobal does not have a ReliabilityContract - if (IntPtr.Zero != tokenStruct) - { - SafeNativeMethods.LocalFree(tokenStruct); - tokenStruct = IntPtr.Zero; - } - if (IntPtr.Zero != sidStringBuffer) - { - SafeNativeMethods.LocalFree(sidStringBuffer); - sidStringBuffer = IntPtr.Zero; - } - } - _lastIdentity = current; - return current; - } - - override public int GetHashCode() - { - return _hashCode; - } - - static private void IntegratedSecurityError(int caller) - { - // passing 1,2,3,4,5 instead of true/false so that with a debugger - // we could determine more easily which Win32 method call failed - int lastError = Marshal.GetHRForLastWin32Error(); - if ((Win32_CheckTokenMembership != caller) || (E_NotImpersonationToken != lastError)) - { - Marshal.ThrowExceptionForHR(lastError); // will only throw if (hresult < 0) - } - } - - } -} - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Unix.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs similarity index 73% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs index 93d2b0f329..ff95cc64eb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.Windows.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using System.Runtime.Versioning; +using System.Security.Permissions; using System.Security.Principal; using Microsoft.Data.SqlClient; @@ -10,12 +12,25 @@ namespace Microsoft.Data.ProviderBase { partial class DbConnectionPoolIdentity { - private static DbConnectionPoolIdentity s_lastIdentity = null; +#if NETFRAMEWORK || NETSTANDARD2_0 + [ResourceExposure(ResourceScope.None)] // SxS: this method does not create named objects + [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] + internal static DbConnectionPoolIdentity GetCurrent() + { + return GetCurrentNative(); + } + [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)] + internal static WindowsIdentity GetCurrentWindowsIdentity() + { + return WindowsIdentity.GetCurrent(); + } +#else internal static DbConnectionPoolIdentity GetCurrent() { return TdsParserStateObjectFactory.UseManagedSNI ? GetCurrentManaged() : GetCurrentNative(); } +#endif private static DbConnectionPoolIdentity GetCurrentNative() { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs similarity index 93% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs index f1b985a6de..394372ec35 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs @@ -7,6 +7,7 @@ namespace Microsoft.Data.ProviderBase sealed internal partial class DbConnectionPoolIdentity { public static readonly DbConnectionPoolIdentity NoIdentity = new DbConnectionPoolIdentity(string.Empty, false, true); + private static DbConnectionPoolIdentity s_lastIdentity = null; private readonly string _sidString; private readonly bool _isRestricted; @@ -43,7 +44,7 @@ override public int GetHashCode() return _hashCode; } - internal static DbConnectionPoolIdentity GetCurrentManaged() + private static DbConnectionPoolIdentity GetCurrentManaged() { string domainString = System.Environment.UserDomainName; string sidString = (!string.IsNullOrWhiteSpace(domainString) ? domainString + "\\" : "") + System.Environment.UserName; From 8c5cbdfa7cc08007e37fac65d3119224d2b13444 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Mon, 4 Mar 2024 07:37:28 +0000 Subject: [PATCH 3/6] Deleted now-unused DbBuffer class --- .../netfx/src/Microsoft.Data.SqlClient.csproj | 7 +- .../Microsoft/Data/ProviderBase/DbBuffer.cs | 807 ------------------ 2 files changed, 3 insertions(+), 811 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 706a0d36e0..9a77bea2c8 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -22,14 +22,14 @@ full - + $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(GeneratedSourceFileName)')) - + True @@ -630,7 +630,6 @@ - @@ -756,4 +755,4 @@ - + \ No newline at end of file diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs deleted file mode 100644 index 3e44134e7f..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/ProviderBase/DbBuffer.cs +++ /dev/null @@ -1,807 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.Data.ProviderBase -{ - using System; - using System.Diagnostics; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using Microsoft.Data.Common; - - // DbBuffer is abstract to require derived class to exist - // so that when debugging, we can tell the difference between one DbBuffer and another - internal abstract class DbBuffer : SafeHandle - { - internal const int LMEM_FIXED = 0x0000; - internal const int LMEM_MOVEABLE = 0x0002; - internal const int LMEM_ZEROINIT = 0x0040; - - private readonly int _bufferLength; - - private DbBuffer(int initialSize, bool zeroBuffer) : base(IntPtr.Zero, true) - { - if (0 < initialSize) - { - int flags = ((zeroBuffer) ? LMEM_ZEROINIT : LMEM_FIXED); - - _bufferLength = initialSize; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { } - finally - { - base.handle = SafeNativeMethods.LocalAlloc(flags, (IntPtr)initialSize); - } - if (IntPtr.Zero == base.handle) - { - throw new OutOfMemoryException(); - } - } - } - - protected DbBuffer(int initialSize) : this(initialSize, true) - { - } - - protected DbBuffer(IntPtr invalidHandleValue, bool ownsHandle) : base(invalidHandleValue, ownsHandle) - { - } - - private int BaseOffset { get { return 0; } } - - public override bool IsInvalid - { - get - { - return (IntPtr.Zero == base.handle); - } - } - - internal int Length - { - get - { - return _bufferLength; - } - } - - internal string PtrToStringUni(int offset) - { - offset += BaseOffset; - Validate(offset, 2); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - - string value = null; - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - int length = UnsafeNativeMethods.lstrlenW(ptr); - Validate(offset, (2 * (length + 1))); - value = Marshal.PtrToStringUni(ptr, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - - return value; - } - - internal String PtrToStringUni(int offset, int length) - { - offset += BaseOffset; - Validate(offset, 2 * length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - - string value = null; - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - value = Marshal.PtrToStringUni(ptr, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - return value; - } - - internal byte ReadByte(int offset) - { - offset += BaseOffset; - ValidateCheck(offset, 1); - Debug.Assert(0 == offset % 4, "invalid alignment"); - - byte value; - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - value = Marshal.ReadByte(ptr, offset); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - return value; - } - - internal byte[] ReadBytes(int offset, int length) - { - byte[] value = new byte[length]; - return ReadBytes(offset, value, 0, length); - } - - internal byte[] ReadBytes(int offset, byte[] destination, int startIndex, int length) - { - offset += BaseOffset; - Validate(offset, length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - Debug.Assert(null != destination, "null destination"); - Debug.Assert(startIndex + length <= destination.Length, "destination too small"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.Copy(ptr, destination, startIndex, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - return destination; - } - - internal Char ReadChar(int offset) - { - short value = ReadInt16(offset); - return unchecked((char)value); - } - - internal char[] ReadChars(int offset, char[] destination, int startIndex, int length) - { - offset += BaseOffset; - Validate(offset, 2 * length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - Debug.Assert(null != destination, "null destination"); - Debug.Assert(startIndex + length <= destination.Length, "destination too small"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.Copy(ptr, destination, startIndex, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - return destination; - } - - internal Double ReadDouble(int offset) - { - Int64 value = ReadInt64(offset); - return BitConverter.Int64BitsToDouble(value); - } - - internal Int16 ReadInt16(int offset) - { - offset += BaseOffset; - ValidateCheck(offset, 2); - Debug.Assert(0 == offset % 2, "invalid alignment"); - - short value; - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - value = Marshal.ReadInt16(ptr, offset); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - return value; - } - - internal void ReadInt16Array(int offset, short[] destination, int startIndex, int length) - { - offset += BaseOffset; - Validate(offset, 2 * length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - Debug.Assert(null != destination, "null destination"); - Debug.Assert(startIndex + length <= destination.Length, "destination too small"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.Copy(ptr, destination, startIndex, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal Int32 ReadInt32(int offset) - { - offset += BaseOffset; - ValidateCheck(offset, 4); - Debug.Assert(0 == offset % 4, "invalid alignment"); - - int value; - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - value = Marshal.ReadInt32(ptr, offset); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - return value; - } - - internal void ReadInt32Array(int offset, int[] destination, int startIndex, int length) - { - offset += BaseOffset; - Validate(offset, 4 * length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - Debug.Assert(null != destination, "null destination"); - Debug.Assert(startIndex + length <= destination.Length, "destination too small"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.Copy(ptr, destination, startIndex, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal Int64 ReadInt64(int offset) - { - offset += BaseOffset; - ValidateCheck(offset, 8); - Debug.Assert(0 == offset % IntPtr.Size, "invalid alignment"); - - long value; - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - value = Marshal.ReadInt64(ptr, offset); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - return value; - } - - internal IntPtr ReadIntPtr(int offset) - { - offset += BaseOffset; - ValidateCheck(offset, IntPtr.Size); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - - IntPtr value; - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - value = Marshal.ReadIntPtr(ptr, offset); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - return value; - } - - internal unsafe Single ReadSingle(int offset) - { - Int32 value = ReadInt32(offset); - return *(Single*)&value; - } - - override protected bool ReleaseHandle() - { - // NOTE: The SafeHandle class guarantees this will be called exactly once. - IntPtr ptr = base.handle; - base.handle = IntPtr.Zero; - if (IntPtr.Zero != ptr) - { - SafeNativeMethods.LocalFree(ptr); - } - return true; - } - - private void StructureToPtr(int offset, object structure) - { - Debug.Assert(null != structure, "null structure"); - offset += BaseOffset; - ValidateCheck(offset, Marshal.SizeOf(structure.GetType())); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.StructureToPtr(structure, ptr, false/*fDeleteOld*/); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteByte(int offset, byte value) - { - offset += BaseOffset; - ValidateCheck(offset, 1); - Debug.Assert(0 == offset % 4, "invalid alignment"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - Marshal.WriteByte(ptr, offset, value); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteBytes(int offset, byte[] source, int startIndex, int length) - { - offset += BaseOffset; - Validate(offset, length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - Debug.Assert(null != source, "null source"); - Debug.Assert(startIndex + length <= source.Length, "source too small"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.Copy(source, startIndex, ptr, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteCharArray(int offset, char[] source, int startIndex, int length) - { - offset += BaseOffset; - Validate(offset, 2 * length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - Debug.Assert(null != source, "null source"); - Debug.Assert(startIndex + length <= source.Length, "source too small"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.Copy(source, startIndex, ptr, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteDouble(int offset, Double value) - { - WriteInt64(offset, BitConverter.DoubleToInt64Bits(value)); - } - - internal void WriteInt16(int offset, short value) - { - offset += BaseOffset; - ValidateCheck(offset, 2); - Debug.Assert(0 == offset % 2, "invalid alignment"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - Marshal.WriteInt16(ptr, offset, value); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteInt16Array(int offset, short[] source, int startIndex, int length) - { - offset += BaseOffset; - Validate(offset, 2 * length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - Debug.Assert(null != source, "null source"); - Debug.Assert(startIndex + length <= source.Length, "source too small"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.Copy(source, startIndex, ptr, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteInt32(int offset, int value) - { - offset += BaseOffset; - ValidateCheck(offset, 4); - Debug.Assert(0 == offset % 4, "invalid alignment"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - Marshal.WriteInt32(ptr, offset, value); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteInt32Array(int offset, int[] source, int startIndex, int length) - { - offset += BaseOffset; - Validate(offset, 4 * length); - Debug.Assert(0 == offset % ADP.s_ptrSize, "invalid alignment"); - Debug.Assert(null != source, "null source"); - Debug.Assert(startIndex + length <= source.Length, "source too small"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); - Marshal.Copy(source, startIndex, ptr, length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteInt64(int offset, long value) - { - offset += BaseOffset; - ValidateCheck(offset, 8); - Debug.Assert(0 == offset % IntPtr.Size, "invalid alignment"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - Marshal.WriteInt64(ptr, offset, value); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal void WriteIntPtr(int offset, IntPtr value) - { - offset += BaseOffset; - ValidateCheck(offset, IntPtr.Size); - Debug.Assert(0 == offset % IntPtr.Size, "invalid alignment"); - - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - Marshal.WriteIntPtr(ptr, offset, value); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal unsafe void WriteSingle(int offset, Single value) - { - WriteInt32(offset, *(Int32*)&value); - } - - internal void ZeroMemory() - { - bool mustRelease = false; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - DangerousAddRef(ref mustRelease); - - IntPtr ptr = DangerousGetHandle(); - SafeNativeMethods.ZeroMemory(ptr, (IntPtr)Length); - } - finally - { - if (mustRelease) - { - DangerousRelease(); - } - } - } - - internal Guid ReadGuid(int offset) - { - // faster than Marshal.PtrToStructure(offset, typeof(Guid)) - byte[] buffer = new byte[16]; - ReadBytes(offset, buffer, 0, 16); - return new Guid(buffer); - } - internal void WriteGuid(int offset, Guid value) - { - // faster than Marshal.Copy(value.GetByteArray() - StructureToPtr(offset, value); - } - - internal DateTime ReadDate(int offset) - { - short[] buffer = new short[3]; - ReadInt16Array(offset, buffer, 0, 3); - return new DateTime( - unchecked((ushort)buffer[0]), // Year - unchecked((ushort)buffer[1]), // Month - unchecked((ushort)buffer[2])); // Day - } - internal void WriteDate(int offset, DateTime value) - { - short[] buffer = new short[3] { - unchecked((short)value.Year), - unchecked((short)value.Month), - unchecked((short)value.Day), - }; - WriteInt16Array(offset, buffer, 0, 3); - } - - internal TimeSpan ReadTime(int offset) - { - short[] buffer = new short[3]; - ReadInt16Array(offset, buffer, 0, 3); - return new TimeSpan( - unchecked((ushort)buffer[0]), // Hours - unchecked((ushort)buffer[1]), // Minutes - unchecked((ushort)buffer[2])); // Seconds - } - internal void WriteTime(int offset, TimeSpan value) - { - short[] buffer = new short[3] { - unchecked((short)value.Hours), - unchecked((short)value.Minutes), - unchecked((short)value.Seconds), - }; - WriteInt16Array(offset, buffer, 0, 3); - } - - internal DateTime ReadDateTime(int offset) - { - short[] buffer = new short[6]; - ReadInt16Array(offset, buffer, 0, 6); - int ticks = ReadInt32(offset + 12); - DateTime value = new DateTime( - unchecked((ushort)buffer[0]), // Year - unchecked((ushort)buffer[1]), // Month - unchecked((ushort)buffer[2]), // Day - unchecked((ushort)buffer[3]), // Hours - unchecked((ushort)buffer[4]), // Minutes - unchecked((ushort)buffer[5])); // Seconds - return value.AddTicks(ticks / 100); - } - internal void WriteDateTime(int offset, DateTime value) - { - int ticks = (int)(value.Ticks % 10000000L) * 100; - short[] buffer = new short[6] { - unchecked((short)value.Year), - unchecked((short)value.Month), - unchecked((short)value.Day), - unchecked((short)value.Hour), - unchecked((short)value.Minute), - unchecked((short)value.Second), - }; - WriteInt16Array(offset, buffer, 0, 6); - WriteInt32(offset + 12, ticks); - } - - internal Decimal ReadNumeric(int offset) - { - byte[] bits = new byte[20]; - ReadBytes(offset, bits, 1, 19); - - int[] buffer = new int[4]; - buffer[3] = ((int)bits[2]) << 16; // scale - if (0 == bits[3]) - { - buffer[3] |= unchecked((int)0x80000000); //sign - } - buffer[0] = BitConverter.ToInt32(bits, 4); // low - buffer[1] = BitConverter.ToInt32(bits, 8); // mid - buffer[2] = BitConverter.ToInt32(bits, 12); // high - if (0 != BitConverter.ToInt32(bits, 16)) - { - throw ADP.NumericToDecimalOverflow(); - } - return new Decimal(buffer); - } - - internal void WriteNumeric(int offset, Decimal value, byte precision) - { - int[] tmp = Decimal.GetBits(value); - byte[] buffer = new byte[20]; - - buffer[1] = precision; - Buffer.BlockCopy(tmp, 14, buffer, 2, 2); // copy sign and scale - buffer[3] = (Byte)((0 == buffer[3]) ? 1 : 0); // flip sign for native - Buffer.BlockCopy(tmp, 0, buffer, 4, 12); - buffer[16] = 0; - buffer[17] = 0; - buffer[18] = 0; - buffer[19] = 0; - WriteBytes(offset, buffer, 1, 19); - } - - [ConditionalAttribute("DEBUG")] - protected void ValidateCheck(int offset, int count) - { - Validate(offset, count); - } - - protected void Validate(int offset, int count) - { - if ((offset < 0) || (count < 0) || (Length < checked(offset + count))) - { - throw ADP.InternalError(ADP.InternalErrorCode.InvalidBuffer); - } - } - } -} From d8f92e9ad8f2689d1f51f056dd94b813ac773834 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Wed, 6 Mar 2024 06:55:45 +0000 Subject: [PATCH 4/6] DbConnectionPoolIdentity.GetCurrentManaged needs to update the cached identity. --- .../Data/ProviderBase/DbConnectionPoolIdentity.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs index 394372ec35..196119cf3c 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPoolIdentity.cs @@ -46,11 +46,24 @@ override public int GetHashCode() private static DbConnectionPoolIdentity GetCurrentManaged() { + DbConnectionPoolIdentity current; string domainString = System.Environment.UserDomainName; string sidString = (!string.IsNullOrWhiteSpace(domainString) ? domainString + "\\" : "") + System.Environment.UserName; bool isNetwork = false; bool isRestricted = false; - return new DbConnectionPoolIdentity(sidString, isRestricted, isNetwork); + + var lastIdentity = s_lastIdentity; + + if ((lastIdentity != null) && (lastIdentity._sidString == sidString) && (lastIdentity._isRestricted == isRestricted) && (lastIdentity._isNetwork == isNetwork)) + { + current = lastIdentity; + } + else + { + current = new DbConnectionPoolIdentity(sidString, isRestricted, isNetwork); + } + s_lastIdentity = current; + return current; } } } From 6e74c211eb861819d42b990005502d87d9a55f32 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Wed, 21 Aug 2024 08:26:43 +0100 Subject: [PATCH 5/6] Removed duplicate reference to DbConnectionPoolIdentity.Unix.cs --- .../netcore/src/Microsoft.Data.SqlClient.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 65cd2bfc7e..74d0ee60d8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -918,7 +918,6 @@ - From b645fea5b4e2957b409011c4a65cd04500568e58 Mon Sep 17 00:00:00 2001 From: Edward Neal <55035479+edwardneal@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:00:38 +0100 Subject: [PATCH 6/6] Eliminated DbConnectionPool.NetCoreApp.cs --- .../src/Microsoft.Data.SqlClient.csproj | 1 - .../DbConnectionPool.NetCoreApp.cs | 49 ------------------- .../Data/ProviderBase/DbConnectionPool.cs | 36 +++++++++++++- 3 files changed, 35 insertions(+), 51 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 74d0ee60d8..494bd0b96c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -637,7 +637,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs deleted file mode 100644 index 4a59e0b858..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.NetCoreApp.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -#if NET6_0_OR_GREATER - -using System.Diagnostics; -using Microsoft.Data.Common; -using Microsoft.Data.SqlClient; - -namespace Microsoft.Data.ProviderBase -{ - internal sealed partial class DbConnectionPool - { - private bool IsBlockingPeriodEnabled() - { - var poolGroupConnectionOptions = _connectionPoolGroup.ConnectionOptions as SqlConnectionString; - if (poolGroupConnectionOptions == null) - { - return true; - } - var policy = poolGroupConnectionOptions.PoolBlockingPeriod; - - switch (policy) - { - case PoolBlockingPeriod.Auto: - { - return !ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource); - } - case PoolBlockingPeriod.AlwaysBlock: - { - return true; //Enabled - } - case PoolBlockingPeriod.NeverBlock: - { - return false; //Disabled - } - default: - { - //we should never get into this path. - Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement."); - return true; - } - } - } - } -} - -#endif diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs index 745ca55c0e..5694d8c05f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs @@ -15,7 +15,7 @@ namespace Microsoft.Data.ProviderBase { - sealed internal partial class DbConnectionPool + internal sealed class DbConnectionPool { private enum State { @@ -1763,5 +1763,39 @@ private DbConnectionInternal UserCreateRequest(DbConnection owningObject, DbConn return obj; } } + +#if NET6_0_OR_GREATER + private bool IsBlockingPeriodEnabled() + { + var poolGroupConnectionOptions = _connectionPoolGroup.ConnectionOptions as SqlConnectionString; + if (poolGroupConnectionOptions == null) + { + return true; + } + var policy = poolGroupConnectionOptions.PoolBlockingPeriod; + + switch (policy) + { + case PoolBlockingPeriod.Auto: + { + return !ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource); + } + case PoolBlockingPeriod.AlwaysBlock: + { + return true; //Enabled + } + case PoolBlockingPeriod.NeverBlock: + { + return false; //Disabled + } + default: + { + //we should never get into this path. + Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement."); + return true; + } + } + } +#endif } }