| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- //------------------------------------------------------------------------------
- // <copyright file="TdsParserSafeHandles.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- //------------------------------------------------------------------------------
- namespace System.Data.SqlClient {
- using System;
- using System.Collections.Generic;
- using System.Data.Common;
- using System.Diagnostics;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using System.Security;
- using System.Security.Permissions;
- using System.Threading;
- using System.Runtime.ConstrainedExecution;
- internal sealed class SNILoadHandle : SafeHandle {
- internal static readonly SNILoadHandle SingletonInstance = new SNILoadHandle();
- internal readonly SNINativeMethodWrapper.SqlAsyncCallbackDelegate ReadAsyncCallbackDispatcher = new SNINativeMethodWrapper.SqlAsyncCallbackDelegate(ReadDispatcher);
- internal readonly SNINativeMethodWrapper.SqlAsyncCallbackDelegate WriteAsyncCallbackDispatcher = new SNINativeMethodWrapper.SqlAsyncCallbackDelegate(WriteDispatcher);
- private readonly UInt32 _sniStatus = TdsEnums.SNI_UNINITIALIZED;
- private readonly EncryptionOptions _encryptionOption;
- private SNILoadHandle() : base(IntPtr.Zero, true) {
- // SQL BU DT 346588 - from security review - SafeHandle guarantees this is only called once.
- // The reason for the safehandle is guaranteed initialization and termination of SNI to
- // ensure SNI terminates and cleans up properly.
- RuntimeHelpers.PrepareConstrainedRegions();
- try {} finally {
-
- _sniStatus = SNINativeMethodWrapper.SNIInitialize();
- UInt32 value = 0;
- // VSDevDiv 479597: If initialize fails, don't call QueryInfo.
- if (TdsEnums.SNI_SUCCESS == _sniStatus) {
- // Query OS to find out whether encryption is supported.
- SNINativeMethodWrapper.SNIQueryInfo(SNINativeMethodWrapper.QTypes.SNI_QUERY_CLIENT_ENCRYPT_POSSIBLE, ref value);
- }
- _encryptionOption = (value == 0) ? EncryptionOptions.NOT_SUP : EncryptionOptions.OFF;
- base.handle = (IntPtr) 1; // Initialize to non-zero dummy variable.
- }
- }
- public override bool IsInvalid {
- get {
- return (IntPtr.Zero == base.handle);
- }
- }
- override protected bool ReleaseHandle() {
- if (base.handle != IntPtr.Zero) {
- if (TdsEnums.SNI_SUCCESS == _sniStatus) {
- LocalDBAPI.ReleaseDLLHandles();
- SNINativeMethodWrapper.SNITerminate();
- }
- base.handle = IntPtr.Zero;
- }
- return true;
- }
- public UInt32 SNIStatus {
- get {
- return _sniStatus;
- }
- }
- public EncryptionOptions Options {
- get {
- return _encryptionOption;
- }
- }
- static private void ReadDispatcher(IntPtr key, IntPtr packet, UInt32 error) {
- // This is the app-domain dispatcher for all async read callbacks, It
- // simply gets the state object from the key that it is passed, and
- // calls the state object's read callback.
- Debug.Assert(IntPtr.Zero != key, "no key passed to read callback dispatcher?");
- if (IntPtr.Zero != key) {
- // NOTE: we will get a null ref here if we don't get a key that
- // contains a GCHandle to TDSParserStateObject; that is
- // very bad, and we want that to occur so we can catch it.
- GCHandle gcHandle = (GCHandle)key;
- TdsParserStateObject stateObj = (TdsParserStateObject)gcHandle.Target;
- if (null != stateObj) {
- stateObj.ReadAsyncCallback(IntPtr.Zero, packet, error);
- }
- }
- }
- static private void WriteDispatcher(IntPtr key, IntPtr packet, UInt32 error) {
- // This is the app-domain dispatcher for all async write callbacks, It
- // simply gets the state object from the key that it is passed, and
- // calls the state object's write callback.
- Debug.Assert(IntPtr.Zero != key, "no key passed to write callback dispatcher?");
- if (IntPtr.Zero != key) {
- // NOTE: we will get a null ref here if we don't get a key that
- // contains a GCHandle to TDSParserStateObject; that is
- // very bad, and we want that to occur so we can catch it.
- GCHandle gcHandle = (GCHandle)key;
- TdsParserStateObject stateObj = (TdsParserStateObject)gcHandle.Target;
- if (null != stateObj) {
- stateObj.WriteAsyncCallback(IntPtr.Zero, packet, error);
- }
- }
- }
- }
- internal sealed class SNIHandle : SafeHandle {
- private readonly UInt32 _status = TdsEnums.SNI_UNINITIALIZED;
- private readonly bool _fSync = false;
- // creates a physical connection
- internal SNIHandle(
- SNINativeMethodWrapper.ConsumerInfo myInfo,
- string serverName,
- byte[] spnBuffer,
- bool ignoreSniOpenTimeout,
- int timeout,
- out byte[] instanceName,
- bool flushCache,
- bool fSync,
- bool fParallel,
- TransparentNetworkResolutionState transparentNetworkResolutionState,
- int totalTimeout)
- : base(IntPtr.Zero, true) {
- RuntimeHelpers.PrepareConstrainedRegions();
- try {} finally {
- _fSync = fSync;
- instanceName = new byte[256]; // Size as specified by netlibs.
- if (ignoreSniOpenTimeout) {
- //
- timeout = Timeout.Infinite; // -1 == native SNIOPEN_TIMEOUT_VALUE / INFINITE
- }
- int transparentNetworkResolutionStateNo = (int)transparentNetworkResolutionState;
- _status = SNINativeMethodWrapper.SNIOpenSyncEx(myInfo, serverName, ref base.handle,
- spnBuffer, instanceName, flushCache, fSync, timeout, fParallel, transparentNetworkResolutionStateNo, totalTimeout);
- }
- }
- // constructs SNI Handle for MARS session
- internal SNIHandle(SNINativeMethodWrapper.ConsumerInfo myInfo, SNIHandle parent) : base(IntPtr.Zero, true) {
- RuntimeHelpers.PrepareConstrainedRegions();
- try {} finally {
- _status = SNINativeMethodWrapper.SNIOpenMarsSession(myInfo, parent, ref base.handle, parent._fSync);
- }
- }
- public override bool IsInvalid {
- get {
- return (IntPtr.Zero == base.handle);
- }
- }
- 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) {
- if (0 != SNINativeMethodWrapper.SNIClose(ptr)) {
- return false; // SNIClose should never fail.
- }
- }
- return true;
- }
- internal UInt32 Status {
- get {
- return _status;
- }
- }
- }
- internal sealed class SNIPacket : SafeHandle {
- internal SNIPacket(SafeHandle sniHandle) : base(IntPtr.Zero, true) {
- SNINativeMethodWrapper.SNIPacketAllocate(sniHandle, SNINativeMethodWrapper.IOType.WRITE, ref base.handle);
- if (IntPtr.Zero == base.handle) {
- throw SQL.SNIPacketAllocationFailure();
- }
- }
- public override bool IsInvalid {
- get {
- return (IntPtr.Zero == base.handle);
- }
- }
- 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) {
- SNINativeMethodWrapper.SNIPacketRelease(ptr);
- }
- return true;
- }
- }
- internal sealed class WritePacketCache : IDisposable {
- private bool _disposed;
- private Stack<SNIPacket> _packets;
- public WritePacketCache() {
- _disposed = false;
- _packets = new Stack<SNIPacket>();
- }
- public SNIPacket Take(SNIHandle sniHandle) {
- SNIPacket packet;
- if (_packets.Count > 0) {
- // Success - reset the packet
- packet = _packets.Pop();
- SNINativeMethodWrapper.SNIPacketReset(sniHandle, SNINativeMethodWrapper.IOType.WRITE, packet, SNINativeMethodWrapper.ConsumerNumber.SNI_Consumer_SNI);
- }
- else {
- // Failed to take a packet - create a new one
- packet = new SNIPacket(sniHandle);
- }
- return packet;
- }
- public void Add(SNIPacket packet) {
- if (!_disposed) {
- _packets.Push(packet);
- }
- else {
- // If we're disposed, then get rid of any packets added to us
- packet.Dispose();
- }
- }
- public void Clear() {
- while (_packets.Count > 0) {
- _packets.Pop().Dispose();
- }
- }
- public void Dispose() {
- if (!_disposed) {
- _disposed = true;
- Clear();
- }
- }
- }
- }
|