diff --git a/src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs b/src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs
index 1902b7045a8e..e6e43a382ceb 100644
--- a/src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs
+++ b/src/System.Data.SqlClient/src/Interop/SNINativeMethodWrapper.Windows.cs
@@ -197,7 +197,7 @@ internal struct SNI_Error
internal static extern void SNIPacketRelease(IntPtr pPacket);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SNIPacketResetWrapper")]
- internal static extern void SNIPacketReset([In] SNIHandle pConn, IOType IOType, SNIPacket pPacket, ConsumerNumber ConsNum);
+ internal static extern void SNIPacketReset([In] SNIHandle pConn, IOType IOType, SNIPacketHandle pPacket, ConsumerNumber ConsNum);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
internal static extern uint SNIQueryInfo(QTypes QType, ref uint pbQInfo);
@@ -256,7 +256,7 @@ private static extern uint SNIOpenWrapper(
private static extern uint SNIPacketGetDataWrapper([In] IntPtr packet, [In, Out] byte[] readBuffer, uint readBufferLength, out uint dataSize);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
- private static extern unsafe void SNIPacketSetData(SNIPacket pPacket, [In] byte* pbBuf, uint cbBuf);
+ private static extern unsafe void SNIPacketSetData(SNIPacketHandle pPacket, [In] byte* pbBuf, uint cbBuf);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
private static extern unsafe uint SNISecGenClientContextWrapper(
@@ -272,10 +272,10 @@ private static extern unsafe uint SNISecGenClientContextWrapper(
[MarshalAsAttribute(UnmanagedType.LPWStr)] string pwszPassword);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
- private static extern uint SNIWriteAsyncWrapper(SNIHandle pConn, [In] SNIPacket pPacket);
+ private static extern uint SNIWriteAsyncWrapper(SNIHandle pConn, [In] SNIPacketHandle pPacket);
[DllImport(SNI, CallingConvention = CallingConvention.Cdecl)]
- private static extern uint SNIWriteSyncOverAsync(SNIHandle pConn, [In] SNIPacket pPacket);
+ private static extern uint SNIWriteSyncOverAsync(SNIHandle pConn, [In] SNIPacketHandle pPacket);
#endregion
internal static uint SniGetConnectionId(SNIHandle pConn, ref Guid connId)
@@ -347,7 +347,7 @@ internal static unsafe uint SNIPacketGetData(IntPtr packet, byte[] readBuffer, r
return SNIPacketGetDataWrapper(packet, readBuffer, (uint)readBuffer.Length, out dataSize);
}
- internal static unsafe void SNIPacketSetData(SNIPacket packet, byte[] data, int length)
+ internal static unsafe void SNIPacketSetData(SNIPacketHandle packet, byte[] data, int length)
{
fixed (byte* pin_data = &data[0])
{
@@ -374,7 +374,7 @@ internal static unsafe uint SNISecGenClientContext(SNIHandle pConnectionObject,
}
}
- internal static uint SNIWritePacket(SNIHandle pConn, SNIPacket packet, bool sync)
+ internal static uint SNIWritePacket(SNIHandle pConn, SNIPacketHandle packet, bool sync)
{
if (sync)
{
diff --git a/src/System.Data.SqlClient/src/System.Data.SqlClient.csproj b/src/System.Data.SqlClient/src/System.Data.SqlClient.csproj
index a288a3ed5c6a..98cd905bab95 100644
--- a/src/System.Data.SqlClient/src/System.Data.SqlClient.csproj
+++ b/src/System.Data.SqlClient/src/System.Data.SqlClient.csproj
@@ -9,6 +9,7 @@
4.0.0.0
4.1.0.0
$(DefineConstants);netcoreapp
+ $(DefineConstants);snidll
$(DefineConstants);FEATURE_TCPKEEPALIVE
net461-Windows_NT-Debug;net461-Windows_NT-Release;netcoreapp-Debug;netcoreapp-Release;netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;netcoreapp2.1-Debug;netcoreapp2.1-Release;netcoreapp2.1-Unix-Debug;netcoreapp2.1-Unix-Release;netcoreapp2.1-Windows_NT-Debug;netcoreapp2.1-Windows_NT-Release;netfx-Windows_NT-Debug;netfx-Windows_NT-Release;netstandard-Debug;netstandard-Release;netstandard-Unix-Debug;netstandard-Unix-Release;netstandard-Windows_NT-Debug;netstandard-Windows_NT-Release;netstandard1.2-Debug;netstandard1.2-Release;netstandard1.3-Debug;netstandard1.3-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release;uap10.0.16299-Windows_NT-Debug;uap10.0.16299-Windows_NT-Release
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIMarsHandle.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIMarsHandle.cs
index 4d079f6ad0bb..e9fd64f12d52 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIMarsHandle.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIMarsHandle.cs
@@ -317,7 +317,7 @@ public void HandleReceiveError(SNIPacket packet)
_packetEvent.Set();
}
- ((TdsParserStateObject)_callbackObject).ReadAsyncCallback(packet, 1);
+ ((TdsParserStateObject)_callbackObject).ReadAsyncCallback(PacketHandle.FromManagedPacket(packet), 1);
}
///
@@ -331,7 +331,7 @@ public void HandleSendComplete(SNIPacket packet, uint sniErrorCode)
{
Debug.Assert(_callbackObject != null);
- ((TdsParserStateObject)_callbackObject).WriteAsyncCallback(packet, sniErrorCode);
+ ((TdsParserStateObject)_callbackObject).WriteAsyncCallback(PacketHandle.FromManagedPacket(packet), sniErrorCode);
}
}
@@ -377,7 +377,7 @@ public void HandleReceiveComplete(SNIPacket packet, SNISMUXHeader header)
_asyncReceives--;
Debug.Assert(_callbackObject != null);
- ((TdsParserStateObject)_callbackObject).ReadAsyncCallback(packet, 0);
+ ((TdsParserStateObject)_callbackObject).ReadAsyncCallback(PacketHandle.FromManagedPacket(packet), 0);
}
}
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIPacket.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIPacket.cs
index 84a47740fabf..acc03819182e 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIPacket.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIPacket.cs
@@ -20,8 +20,6 @@ internal class SNIPacket : IDisposable, IEquatable
private int _offset;
private string _description;
private SNIAsyncCallback _completionCallback;
-
- private ArrayPool _arrayPool = ArrayPool.Shared;
private bool _isBufferFromArrayPool = false;
public SNIPacket() { }
@@ -98,14 +96,14 @@ public void Allocate(int capacity)
{
if (_isBufferFromArrayPool)
{
- _arrayPool.Return(_data);
+ ArrayPool.Shared.Return(_data);
}
_data = null;
}
if (_data == null)
{
- _data = _arrayPool.Rent(capacity);
+ _data = ArrayPool.Shared.Rent(capacity);
_isBufferFromArrayPool = true;
}
@@ -221,7 +219,7 @@ public void Release()
{
if(_isBufferFromArrayPool)
{
- _arrayPool.Return(_data);
+ ArrayPool.Shared.Return(_data);
}
_data = null;
_capacity = 0;
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.Windows.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.Windows.cs
index 12ce515bf93d..3c889c959bb1 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.Windows.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.Windows.cs
@@ -20,20 +20,22 @@ internal void PostReadAsyncForMars()
// Have to post read to initialize MARS - will get callback on this when connection goes
// down or is closed.
- IntPtr temp = IntPtr.Zero;
+ PacketHandle temp = default;
uint error = TdsEnums.SNI_SUCCESS;
_pMarsPhysicalConObj.IncrementPendingCallbacks();
- object handle = _pMarsPhysicalConObj.SessionHandle;
- temp = (IntPtr)_pMarsPhysicalConObj.ReadAsync(out error, ref handle);
+ SessionHandle handle = _pMarsPhysicalConObj.SessionHandle;
+ temp = _pMarsPhysicalConObj.ReadAsync(handle, out error);
- if (temp != IntPtr.Zero)
+ Debug.Assert(temp.Type == PacketHandle.NativePointerType, "unexpected packet type when requiring NativePointer");
+
+ if (temp.NativePointer != IntPtr.Zero)
{
// Be sure to release packet, otherwise it will be leaked by native.
_pMarsPhysicalConObj.ReleasePacket(temp);
}
- Debug.Assert(IntPtr.Zero == temp, "unexpected syncReadPacket without corresponding SNIPacketRelease");
+ Debug.Assert(IntPtr.Zero == temp.NativePointer, "unexpected syncReadPacket without corresponding SNIPacketRelease");
if (TdsEnums.SNI_SUCCESS_IO_PENDING != error)
{
Debug.Assert(TdsEnums.SNI_SUCCESS != error, "Unexpected successful read async on physical connection before enabling MARS!");
@@ -118,4 +120,4 @@ private SNIErrorDetails GetSniErrorDetails()
}
} // tdsparser
-}//namespace
\ No newline at end of file
+}//namespace
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs
index 55cd8a1c5fb5..4360ab64d5ab 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserSafeHandles.cs
@@ -104,7 +104,7 @@ private static void ReadDispatcher(IntPtr key, IntPtr packet, uint error)
if (null != stateObj)
{
- stateObj.ReadAsyncCallback(IntPtr.Zero, packet, error);
+ stateObj.ReadAsyncCallback(IntPtr.Zero, PacketHandle.FromNativePointer(packet), error);
}
}
}
@@ -125,7 +125,7 @@ private static void WriteDispatcher(IntPtr key, IntPtr packet, uint error)
if (null != stateObj)
{
- stateObj.WriteAsyncCallback(IntPtr.Zero, packet, error);
+ stateObj.WriteAsyncCallback(IntPtr.Zero, PacketHandle.FromNativePointer(packet), error);
}
}
}
@@ -206,9 +206,9 @@ internal uint Status
}
}
- internal sealed class SNIPacket : SafeHandle
+ internal sealed class SNIPacketHandle : SafeHandle
{
- internal SNIPacket(SafeHandle sniHandle) : base(IntPtr.Zero, true)
+ internal SNIPacketHandle(SafeHandle sniHandle) : base(IntPtr.Zero, true)
{
SNINativeMethodWrapper.SNIPacketAllocate(sniHandle, SNINativeMethodWrapper.IOType.WRITE, ref base.handle);
if (IntPtr.Zero == base.handle)
@@ -241,17 +241,17 @@ override protected bool ReleaseHandle()
internal sealed class WritePacketCache : IDisposable
{
private bool _disposed;
- private Stack _packets;
+ private Stack _packets;
public WritePacketCache()
{
_disposed = false;
- _packets = new Stack();
+ _packets = new Stack();
}
- public SNIPacket Take(SNIHandle sniHandle)
+ public SNIPacketHandle Take(SNIHandle sniHandle)
{
- SNIPacket packet;
+ SNIPacketHandle packet;
if (_packets.Count > 0)
{
// Success - reset the packet
@@ -261,12 +261,12 @@ public SNIPacket Take(SNIHandle sniHandle)
else
{
// Failed to take a packet - create a new one
- packet = new SNIPacket(sniHandle);
+ packet = new SNIPacketHandle(sniHandle);
}
return packet;
}
- public void Add(SNIPacket packet)
+ public void Add(SNIPacketHandle packet)
{
if (!_disposed)
{
@@ -296,4 +296,4 @@ public void Dispose()
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStateObject.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStateObject.cs
index dcc7eae1744e..e74c3179476e 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStateObject.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStateObject.cs
@@ -20,6 +20,102 @@ sealed internal class LastIOTimer
internal long _value;
}
+ internal readonly ref struct PacketHandle
+ {
+ public const int NativePointerType = 1;
+ public const int NativePacketType = 2;
+ public const int ManagedPacketType = 3;
+
+#if snidll
+ public readonly IntPtr NativePointer;
+ public readonly SNIPacketHandle NativePacket;
+#endif
+ public readonly SNI.SNIPacket ManagedPacket;
+ public readonly int Type;
+
+ private PacketHandle(IntPtr nativePointer,
+#if snidll
+ SNIPacketHandle
+#else
+ int
+#endif
+
+ nativePacket, SNI.SNIPacket managedPacket,int type)
+ {
+ Type = type;
+ ManagedPacket = managedPacket;
+#if snidll
+ NativePointer = nativePointer;
+ NativePacket = nativePacket;
+#endif
+ }
+
+ public static PacketHandle FromManagedPacket(SNI.SNIPacket managedPacket)
+ {
+ return new PacketHandle(default, default, managedPacket, ManagedPacketType);
+ }
+
+#if snidll
+ public static PacketHandle FromNativePointer(IntPtr nativePointer)
+ {
+ return new PacketHandle(nativePointer,default,default, NativePointerType);
+ }
+
+ public static PacketHandle FromNativePacket(SNIPacketHandle nativePacket)
+ {
+ return new PacketHandle(default, nativePacket, default, NativePacketType);
+ }
+#endif
+
+
+ }
+
+ internal readonly ref struct SessionHandle
+ {
+ public const int NativeHandleType = 1;
+ public const int ManagedHandleType = 2;
+
+ public readonly SNI.SNIHandle ManagedHandle;
+#if snidll
+ public readonly SNIHandle NativeHandle;
+#endif
+ public readonly int Type;
+
+ public SessionHandle(SNI.SNIHandle managedHandle,
+#if snidll
+ SNIHandle
+#else
+ int
+#endif
+ nativeHandle,
+ int type
+ )
+ {
+ Type = type;
+ ManagedHandle = managedHandle;
+#if snidll
+ NativeHandle = nativeHandle;
+#endif
+ }
+
+ public bool IsNull =>
+#if snidll
+ (Type == NativeHandleType) ? NativeHandle == null :
+#endif
+ ManagedHandle == null;
+
+ public static SessionHandle FromManagedSession(SNI.SNIHandle managedSessionHandle)
+ {
+ return new SessionHandle(managedSessionHandle, default, ManagedHandleType);
+ }
+#if snidll
+ public static SessionHandle FromNativeHandle(SNIHandle nativeSessionHandle)
+ {
+ return new SessionHandle(default, nativeSessionHandle, NativeHandleType);
+ }
+#endif
+ }
+
internal abstract class TdsParserStateObject
{
private const int AttentionTimeoutSeconds = 5;
@@ -392,7 +488,7 @@ internal abstract uint Status
get;
}
- internal abstract object SessionHandle
+ internal abstract SessionHandle SessionHandle
{
get;
}
@@ -761,27 +857,27 @@ private void ResetCancelAndProcessAttention()
internal abstract void DisposePacketCache();
- internal abstract bool IsPacketEmpty(object readPacket);
+ internal abstract bool IsPacketEmpty(PacketHandle readPacket);
- internal abstract object ReadSyncOverAsync(int timeoutRemaining, out uint error);
+ internal abstract PacketHandle ReadSyncOverAsync(int timeoutRemaining, out uint error);
- internal abstract object ReadAsync(out uint error, ref object handle);
+ internal abstract PacketHandle ReadAsync(SessionHandle handle, out uint error);
internal abstract uint CheckConnection();
internal abstract uint SetConnectionBufferSize(ref uint unsignedPacketSize);
- internal abstract void ReleasePacket(object syncReadPacket);
+ internal abstract void ReleasePacket(PacketHandle syncReadPacket);
- protected abstract uint SNIPacketGetData(object packet, byte[] _inBuff, ref uint dataSize);
+ protected abstract uint SNIPacketGetData(PacketHandle packet, byte[] _inBuff, ref uint dataSize);
- internal abstract object GetResetWritePacket();
+ internal abstract PacketHandle GetResetWritePacket();
internal abstract void ClearAllWritePackets();
- internal abstract object AddPacketToPendingList(object packet);
+ internal abstract PacketHandle AddPacketToPendingList(PacketHandle packet);
- protected abstract void RemovePacketFromPendingList(object pointer);
+ protected abstract void RemovePacketFromPendingList(PacketHandle pointer);
internal abstract uint GenerateSspiClientContext(byte[] receivedBuff, uint receivedLength, ref byte[] sendBuff, ref uint sendLength, byte[] _sniSpnBuffer);
@@ -855,7 +951,7 @@ internal int DecrementPendingCallbacks(bool release)
// NOTE: TdsParserSessionPool may call DecrementPendingCallbacks on a TdsParserStateObject which is already disposed
// This is not dangerous (since the stateObj is no longer in use), but we need to add a workaround in the assert for it
- Debug.Assert((remaining == -1 && SessionHandle == null) || (0 <= remaining && remaining < 3), string.Format("_pendingCallbacks values is invalid after decrementing: {0}", remaining));
+ Debug.Assert((remaining == -1 && SessionHandle.IsNull ) || (0 <= remaining && remaining < 3), string.Format("_pendingCallbacks values is invalid after decrementing: {0}", remaining));
return remaining;
}
@@ -2069,7 +2165,7 @@ internal void ReadSniSyncOverAsync()
throw ADP.ClosedConnectionError();
}
- object readPacket = null;
+ PacketHandle readPacket = default;
uint error;
@@ -2291,7 +2387,7 @@ internal void ReadSni(TaskCompletionSource