OciHandle.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / DataOracleClient / System / Data / OracleClient / OciHandle.cs / 1 / OciHandle.cs

                            //------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Data.OracleClient 
{
    using System; 
    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;
 
    //---------------------------------------------------------------------
    // OciHandle
    //
    // Class to manage the lifetime of Oracle Call Interface handles, and 
    // to simplify a number of handle-related operations
    // 
    abstract internal class OciHandle : SafeHandle { 
        [Flags]
        protected enum HANDLEFLAG { 
            DEFAULT     =   0,
            UNICODE     =   1<<0,
            NLS         =   1<<1,
        } 

        private OCI.HTYPE   _handleType; 
        private int         _refCount; 
        private OciHandle   _parentHandle;
        private bool        _isUnicode; 

        // default constructor
        protected OciHandle() : base(IntPtr.Zero, true) {
        } 

        // OciSimpleHandle constructor 
        protected OciHandle(OCI.HTYPE handleType) : base(IntPtr.Zero, false) { 
            _handleType   = handleType;
        } 

        protected OciHandle(OciHandle parentHandle, OCI.HTYPE handleType) : this(parentHandle, handleType, OCI.MODE.OCI_DEFAULT, HANDLEFLAG.DEFAULT) {
        }
 

        protected OciHandle(OciHandle parentHandle, OCI.HTYPE handleType, OCI.MODE ocimode, HANDLEFLAG handleflags) : this() { 
            int rc; 

            Debug.Assert (!(parentHandle is OciSimpleHandle), "Must not create handle on top of OciSimpleHandle"); 

            RuntimeHelpers.PrepareConstrainedRegions();
            try {} finally {
 
                _handleType   = handleType;
                _parentHandle = parentHandle; 
                _refCount     = 1; 

                // 
                switch (handleType) {
                case OCI.HTYPE.OCI_HTYPE_ENV:
                    Debug.Assert(null == parentHandle, "not null parentHandle?");
 
                    if ((handleflags & HANDLEFLAG.NLS) == HANDLEFLAG.NLS) {
                        rc = TracedNativeMethods.OCIEnvNlsCreate( 
                                                out base.handle, 
                                                ocimode,
                                                0, 
                                                0);

                        if (0 != rc || IntPtr.Zero == base.handle) {
                            throw ADP.OperationFailed("OCIEnvNlsCreate", rc); 
                        }
                    } 
                    else { 
                        rc = TracedNativeMethods.OCIEnvCreate(
                                                out base.handle, 
                                                ocimode);

                        if (0 != rc || IntPtr.Zero == base.handle) {
                            throw ADP.OperationFailed("OCIEnvCreate", rc); 
                        }
                    } 
                    break; 

                case OCI.HTYPE.OCI_HTYPE_ERROR: 
                case OCI.HTYPE.OCI_HTYPE_SERVER:
                case OCI.HTYPE.OCI_HTYPE_SVCCTX:
                case OCI.HTYPE.OCI_HTYPE_SESSION:
                case OCI.HTYPE.OCI_HTYPE_STMT: 
                    Debug.Assert(null != parentHandle, "null parentHandle?");
 
                    rc = TracedNativeMethods.OCIHandleAlloc( 
                                                parentHandle.EnvironmentHandle,
                                                out base.handle, 
                                                handleType);

                    if (0 != rc || IntPtr.Zero == base.handle) {
                        throw ADP.OperationFailed("OCIHandleAlloc", rc); 
                    }
                    break; 
 
                case OCI.HTYPE.OCI_DTYPE_LOB:
                case OCI.HTYPE.OCI_DTYPE_FILE: 
                case OCI.HTYPE.OCI_DTYPE_ROWID:
                case OCI.HTYPE.OCI_DTYPE_TIMESTAMP:
                case OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ:
                case OCI.HTYPE.OCI_DTYPE_TIMESTAMP_LTZ: 
                case OCI.HTYPE.OCI_DTYPE_INTERVAL_DS:
                    Debug.Assert(null != parentHandle, "null parentHandle?"); 
 
                    rc = TracedNativeMethods.OCIDescriptorAlloc(
                                                parentHandle.EnvironmentHandle, 
                                                out base.handle,
                                                handleType);

                    if (0 != rc || IntPtr.Zero == base.handle) { 
                        throw ADP.OperationFailed("OCIDescriptorAlloc", rc);
                    } 
                    break; 

 
                case OCI.HTYPE.OCI_HTYPE_BIND:
                case OCI.HTYPE.OCI_HTYPE_DEFINE:
                case OCI.HTYPE.OCI_DTYPE_PARAM:
                    Debug.Assert(null != parentHandle, "null parentHandle?"); 
                    // These three handles are Simple OCI handles -- they do not
                    // need to be freed. 
                    break; 

                default: 
                    Debug.Assert(false, "unexpected handleType");
                    break;
                }
 
                // If we get here, we successfully allocated the handle, so we had
                // better better up the parent's ref count. 
                if (null != parentHandle) { 
                    parentHandle.AddRef();
                    _isUnicode = parentHandle.IsUnicode; 
                }
                else {
                    _isUnicode = (handleflags & HANDLEFLAG.UNICODE) == HANDLEFLAG.UNICODE;
                } 
            }
        } 
 
        internal OciHandle EnvironmentHandle {
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
            get {
                OciHandle value;

                if (HandleType == OCI.HTYPE.OCI_HTYPE_ENV) { 
                    value = this;
                } 
                else { 
                    value = ParentHandle.EnvironmentHandle;
                } 
                return value;
            }
        }
 
        internal OCI.HTYPE HandleType {
            get { 
                return _handleType; 
            }
        } 

        public override bool IsInvalid {
            get {
                return (IntPtr.Zero == base.handle); 
            }
        } 
 
        internal bool IsUnicode {
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
            get {
                return _isUnicode;
            }
        } 

        internal OciHandle ParentHandle { 
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
            get {
                return _parentHandle; 
            }
        }

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
        internal int AddRef() {
            int refCount = Interlocked.Increment(ref _refCount); 
            return refCount; 
        }
 
        //    Wrap the OCIAttrGet calls.  We do not expect OCIAttrGet to fail,
        //    so we will throw if it does.  There are multiple overloads here,
        //    one for each type of parameter that Oracle supports
 
        internal void GetAttribute(OCI.ATTR attribute, out byte value, OciErrorHandle errorHandle) {
            uint zero = 0; 
            int rc = TracedNativeMethods.OCIAttrGet( this, out value, out zero, attribute, errorHandle ); 

            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            }
        }
 
        internal void GetAttribute(OCI.ATTR attribute, out short value, OciErrorHandle errorHandle) {
            uint zero = 0; 
            int rc = TracedNativeMethods.OCIAttrGet( this, out value, out zero, attribute, errorHandle ); 

            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            }
        }
 
        internal void GetAttribute(OCI.ATTR attribute, out int value, OciErrorHandle errorHandle) {
            uint zero = 0; 
            int rc = TracedNativeMethods.OCIAttrGet( this, out value, out zero, attribute, errorHandle ); 

            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            }
        }
 
        internal void GetAttribute(OCI.ATTR attribute, out string value, OciErrorHandle errorHandle, OracleConnection connection) {
            IntPtr    tempptr = IntPtr.Zero;  // note: no need to clean up tempptr pointer 
            uint      tempub4 = 0; 
            int rc = TracedNativeMethods.OCIAttrGet( this, ref tempptr, ref tempub4, attribute, errorHandle );
 
            if (0 != rc) {
                OracleException.Check(errorHandle, rc);
            }
 
            byte[]  bytearray = new byte[tempub4];
            Marshal.Copy(tempptr, bytearray, 0, checked((int)tempub4)); 
            value = connection.GetString(bytearray); 
        }
 
        internal byte[] GetBytes(string value) {
            byte[]     result;
            uint       valueLength = (uint)value.Length;
 
            if (IsUnicode) {
                result = new byte[valueLength * ADP.CharSize]; 
                GetBytes(value.ToCharArray(), 0, valueLength, result, 0); 
            }
            else { 
                byte[] temp       = new byte[valueLength * 4];    // one Unicode character can map to up to 4 bytes
                uint   tempLength = GetBytes(value.ToCharArray(), 0, valueLength, temp, 0);

                result = new byte[tempLength]; 

                Buffer.BlockCopy(temp, 0, result, 0, checked ((int)tempLength)); 
            } 
            return result;
        } 

        internal uint GetBytes(char[] chars, int charIndex, uint charCount, byte[] bytes, int byteIndex) {
            uint byteCount;
 
            if (IsUnicode) {
                byteCount = checked ((uint)(charCount * ADP.CharSize)); 
                Buffer.BlockCopy(chars, charIndex*ADP.CharSize, bytes, byteIndex, checked ((int)byteCount)); 
            }
            else { 
                OciHandle environmentHandle = EnvironmentHandle;
                GCHandle  charsHandle = new GCHandle();
                GCHandle  bytesHandle = new GCHandle();
                int       rc; 

                try { 
                    charsHandle = GCHandle.Alloc(chars, GCHandleType.Pinned); 

                    IntPtr charsPtr = new IntPtr((long)charsHandle.AddrOfPinnedObject() + charIndex); 
                    IntPtr bytesPtr;

                    if (null == bytes) {
                        bytesPtr = IntPtr.Zero; 
                        byteCount = 0;
                    } 
                    else { 
                        bytesHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                        bytesPtr = new IntPtr((long)bytesHandle.AddrOfPinnedObject() + byteIndex); 
                        byteCount = checked((uint)(bytes.Length-byteIndex));
                    }
                    rc = UnsafeNativeMethods.OCIUnicodeToCharSet(
                                                environmentHandle, 
                                                bytesPtr,
                                                byteCount, 
                                                charsPtr, 
                                                charCount,
                                                out byteCount 
                                                );
                }
                finally {
                    charsHandle.Free(); 

                    if (bytesHandle.IsAllocated) 
                        bytesHandle.Free(); 
                }
 
                if (0 != rc) {
                    throw ADP.OperationFailed("OCIUnicodeToCharSet", rc);
                }
            } 
            return byteCount;
        } 
 
        internal uint GetChars(byte[] bytes, int byteIndex, uint byteCount, char[] chars, int charIndex) {
            uint charCount; 

            if (IsUnicode) {
                Debug.Assert(0 == (byteCount & 0x1), "Odd Number of Unicode Bytes?");
                charCount = checked ((uint)(byteCount / ADP.CharSize)); 
                Buffer.BlockCopy(bytes, byteIndex, chars, charIndex*ADP.CharSize, checked((int)byteCount));
            } 
            else { 
                OciHandle environmentHandle = EnvironmentHandle;
                GCHandle bytesHandle = new GCHandle(); 
                GCHandle charsHandle = new GCHandle();
                int rc;

                try { 
                    bytesHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                    IntPtr bytesPtr = new IntPtr((long)bytesHandle.AddrOfPinnedObject() + byteIndex); 
                    IntPtr charsPtr; 

                    if (null == chars) { 
                        charsPtr = IntPtr.Zero;
                        charCount = 0;
                    }
                    else { 
                        charsHandle = GCHandle.Alloc(chars, GCHandleType.Pinned);
                        charsPtr = new IntPtr((long)charsHandle.AddrOfPinnedObject() + charIndex); 
                        charCount = checked((uint)(chars.Length-charIndex)); 
                    }
 
                    rc = UnsafeNativeMethods.OCICharSetToUnicode(
                                            environmentHandle,
                                            charsPtr,
                                            charCount, 
                                            bytesPtr,
                                            byteCount, 
                                            out charCount 
                                            );
                } 
                finally {
                    bytesHandle.Free();
                    if (charsHandle.IsAllocated)
                        charsHandle.Free(); 
                }
 
                if (0 != rc) { 
                    throw ADP.OperationFailed("OCICharSetToUnicode", rc);
                } 
            }
            return charCount;
        }
 
        //---------------------------------------------------------------------
        static internal string GetAttributeName 
            ( 
            OciHandle       handle,
            OCI.ATTR        atype 
            )
        {
            if (OCI.HTYPE.OCI_DTYPE_PARAM == handle.HandleType)
                return ((OCI.PATTR)atype).ToString(); 

            return atype.ToString(); 
        } 

        //---------------------------------------------------------------------- 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        static internal IntPtr HandleValueToTrace ( OciHandle handle )
        {
            return handle.DangerousGetHandle();  // for tracing purposes, it's safe to just print this -- no handle recycling issues. 
        }
 
        internal string PtrToString(NativeBuffer buf) { 
            string result = null;
 
            if (IsUnicode)
                result = buf.PtrToStringUni(0);
            else
                result = buf.PtrToStringAnsi(0); 
            return result;
        } 
 
        internal string PtrToString(IntPtr buf, int len) {
            string result; 

            if (IsUnicode)
                result = Marshal.PtrToStringUni(buf, len);
            else 
                result = Marshal.PtrToStringAnsi(buf, len);
            return result; 
        } 

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
        internal int Release() {

            int refCount;
 
            RuntimeHelpers.PrepareConstrainedRegions();
            try {} finally { 
 
                refCount = Interlocked.Decrement(ref _refCount);
 
                Debug.Assert (0 <= refCount, "refCount is negative?");

                if (0 == refCount) {
                    //Debug.WriteLine(String.Format("Releasing hande={0} value={1}", HandleTypeToString(this), HandleValueToString(base.handle))); 

                    IntPtr handle = Interlocked.CompareExchange(ref base.handle, IntPtr.Zero, base.handle); 
 
                    if (IntPtr.Zero != handle) {
                        OCI.HTYPE handleType   = HandleType; 
                        OciHandle parentHandle = ParentHandle;
                        int rc;

                        switch (handleType) { 
                        case OCI.HTYPE.OCI_HTYPE_ENV:
                            Debug.Assert(null == parentHandle, "not null parentHandle?"); 
 
                            rc = TracedNativeMethods.OCIHandleFree(handle, handleType);
 
                            if (0 != rc) {
                                throw ADP.OperationFailed("OCIHandleFree", rc);
                            }
                            break; 

                        case OCI.HTYPE.OCI_HTYPE_SERVER: 
                            Debug.Assert(null != parentHandle, "null parentHandle?"); 
                            Debug.Assert(OCI.HTYPE.OCI_HTYPE_ERROR == parentHandle.HandleType, "parentHandle of server handle must be the error handle!");
 
                            // NOTE: while it might seem to be a problem here that
                            //       we are using DangerousGetHandle on the parent
                            //       handle here, the reason that we're doing it is
                            //       that we're in shutdown mode and the handle may 
                            //       have already been released -- attempting to use
                            //       it any other way would cause the CLR to throw 
                            //       an ObjectDisposedException wit the message 
                            //       "Safe handle has been closed".  The reasons for
                            //       this are that we're using our ref-counting 
                            //       to enforce a specific release order, but the
                            //       GC will let the safehandle be closed long
                            //       before all of the handles that have a ref-
                            //       counts on this handle are closed, which means 
                            //       that the last one will cause the server detach
                            //       call. 
                            // 
                            //       There is no likelihood of having a handle
                            //       recycling attack here, because we're making 
                            //       the call that we would have been making in
                            //       ReleaseHandle -- we still own the handle
                            //       until ServerDetach is called.
                            TracedNativeMethods.OCIServerDetach(handle, parentHandle.DangerousGetHandle(), OCI.MODE.OCI_DEFAULT); 
                            // we eat failures here -- what would you suggest we do otherwise?
 
                            goto case OCI.HTYPE.OCI_HTYPE_SESSION; 

                        case OCI.HTYPE.OCI_HTYPE_SVCCTX: 
                            // NOTE: while it might seem to be a problem here that
                            //       we are using DangerousGetHandle on the parent
                            //       handle here, the reason that we're doing it is
                            //       that we're in shutdown mode and the handle may 
                            //       have already been released -- attempting to use
                            //       it any other way would cause the CLR to throw 
                            //       an ObjectDisposedException wit the message 
                            //       "Safe handle has been closed".  The reasons for
                            //       this are that we're using our ref-counting 
                            //       to enforce a specific release order, but the
                            //       GC will let the safehandle be closed long
                            //       before all of the handles that have a ref-
                            //       counts on this handle are closed, which means 
                            //       that the last one will cause the server detach
                            //       call. 
                            // 
                            //       There is no likelihood of having a handle
                            //       recycling attack here, because we're making 
                            //       the call that we would have been making in
                            //       ReleaseHandle -- we still own the handle
                            //       until they are freed, and our ref counting
                            //       prevents them from being freed out of order. 
                            OciHandle sessionHandle = parentHandle;
                            if (null != sessionHandle) { 
                                OciHandle serverHandle = sessionHandle.ParentHandle; 
                                if (null != serverHandle) {
                                    OciHandle errorHandle = serverHandle.ParentHandle; 
                                    if (null != errorHandle) {
                                        rc = TracedNativeMethods.OCISessionEnd(
                                                                    handle,                             // svchp
                                                                    errorHandle.DangerousGetHandle(),   // errhp 
                                                                    sessionHandle.DangerousGetHandle(), // usrhp
                                                                    OCI.MODE.OCI_DEFAULT    // mode 
                                                                    ); 
                                    }
                                } 
                            }
                            // we eat failures here -- what would you suggest we do otherwise?

                            goto case OCI.HTYPE.OCI_HTYPE_ERROR; 

                        case OCI.HTYPE.OCI_HTYPE_ERROR: 
                        case OCI.HTYPE.OCI_HTYPE_SESSION: 
                        case OCI.HTYPE.OCI_HTYPE_STMT:
                            Debug.Assert(null != parentHandle, "null parentHandle?"); 

                            rc = TracedNativeMethods.OCIHandleFree(handle, handleType);

                            if (0 != rc) { 
                                throw ADP.OperationFailed("OCIHandleFree", rc);
                            } 
                            break; 

                        case OCI.HTYPE.OCI_DTYPE_LOB: 
                        case OCI.HTYPE.OCI_DTYPE_FILE:
                        case OCI.HTYPE.OCI_DTYPE_ROWID:
                        case OCI.HTYPE.OCI_DTYPE_TIMESTAMP:
                        case OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ: 
                        case OCI.HTYPE.OCI_DTYPE_TIMESTAMP_LTZ:
                        case OCI.HTYPE.OCI_DTYPE_INTERVAL_DS: 
                            Debug.Assert(null != parentHandle, "null parentHandle?"); 

                            rc = TracedNativeMethods.OCIDescriptorFree(handle, handleType); 

                            if (0 != rc) {
                                throw ADP.OperationFailed("OCIDescriptorFree", rc);
                            } 
                            break;
 
                        default: 
                            Debug.Assert(false, "unexpected handleType");
                            break; 
                        }

                        // If we ended up getting released, then we have to release
                        // our reference on our parent. 
                        if (null != parentHandle) {
                            parentHandle.Release(); 
                        } 
                    }
                } 
            }
            return refCount;
        }
 
        override protected bool ReleaseHandle() {
            //Debug.WriteLine(String.Format("ReleaseHandle type={0} value={1}", HandleTypeToString(this), HandleValueToString(this))); 
            // NOTE: The SafeHandle class guarantees this will be called exactly once. 
            Release();
            return true; 
        }

        static internal void SafeDispose(ref OciHandle handle) {
            //    Safely disposes of the handle (even if it is already null) and 
            //    then nulls it out.
            if (null != handle) { 
                handle.Dispose(); 
            }
            handle = null; 
        }
        static internal void SafeDispose (ref OciEnvironmentHandle handle) {
            if (handle != null) {
                handle.Dispose(); 
            }
            handle = null; 
        } 
        static internal void SafeDispose (ref OciErrorHandle handle) {
            if (handle != null) { 
                handle.Dispose();
            }
            handle = null;
        } 
        static internal void SafeDispose (ref OciRowidDescriptor handle) {
            if (handle != null) { 
                handle.Dispose(); 
            }
            handle = null; 
        }
        static internal void SafeDispose(ref OciStatementHandle handle) {
            if (null != handle) {
                handle.Dispose(); 
            }
            handle = null; 
        } 
        static internal void SafeDispose(ref OciSessionHandle handle) {
            if (null != handle) { 
                handle.Dispose();
            }
            handle = null;
        } 
        static internal void SafeDispose(ref OciServiceContextHandle handle) {
            if (null != handle) { 
                handle.Dispose(); 
            }
            handle = null; 
        }
        static internal void SafeDispose(ref OciServerHandle handle) {
            if (null != handle) {
                handle.Dispose(); 
            }
            handle = null; 
        } 
        static internal void SafeDispose (ref OciDefineHandle handle) {
            if (handle != null) { 
                handle.Dispose();
            }
            handle = null;
        } 

        static internal void SafeDispose (ref OciBindHandle handle) { 
            if (handle != null) { 
                handle.Dispose();
            } 
            handle = null;
        }

        static internal void SafeDispose (ref OciParameterDescriptor handle) { 
            if (handle != null) {
                handle.Dispose(); 
            } 
            handle = null;
        } 

        static internal void SafeDispose(ref OciDateTimeDescriptor handle)
        {
            if (handle != null) 
            {
                handle.Dispose(); 
            } 
            handle = null;
        } 


        //    Wrap the OCIAttrSet calls.  We do not expect OCIAttrSet to fail,
        //    so we will throw if it does.  There are multiple overloads here, 
        //    one for each type of parameter that Oracle supports
 
        internal void SetAttribute(OCI.ATTR attribute, int value, OciErrorHandle errorHandle) { 
            int rc = TracedNativeMethods.OCIAttrSet(
                        this,            // trgthndlp/trghndltyp 
                        ref value,        // attributep
                        0,                // size
                        attribute,        // attrtype
                        errorHandle        // errhp 
                        );
 
            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            } 
        }

        internal void SetAttribute(OCI.ATTR attribute, OciHandle value, OciErrorHandle errorHandle) {
             int rc = TracedNativeMethods.OCIAttrSet( 
                        this,            // trgthndlp/trghndltyp
                        value,            // attributep 
                        0,                // size 
                        attribute,        // attrtype
                        errorHandle        // errhp 
                        );

            if (0 != rc) {
                OracleException.Check(errorHandle, rc); 
            }
        } 
 
        internal void SetAttribute(OCI.ATTR attribute, string value, OciErrorHandle errorHandle) {
 
            uint valueLengthAsChars = unchecked((uint)value.Length);
            byte[] valueAsBytes = new byte[valueLengthAsChars * 4];
            uint valueLengthAsBytes = GetBytes(value.ToCharArray(), 0, valueLengthAsChars, valueAsBytes, 0);
 
            int rc = TracedNativeMethods.OCIAttrSet(
                        this,                // trgthndlp/trghndltyp 
                        valueAsBytes,        // attributep 
                        valueLengthAsBytes,  // size
                        attribute,           // attrtype 
                        errorHandle          // errhp
                        );

            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            } 
        } 
    }
 
    sealed internal class OciEnvironmentHandle : OciHandle {
        internal OciEnvironmentHandle(OCI.MODE environmentMode, bool unicode)
            : base(null, OCI.HTYPE.OCI_HTYPE_ENV, environmentMode, unicode?HANDLEFLAG.UNICODE:HANDLEFLAG.DEFAULT) {}
    } 

    sealed internal class OciErrorHandle : OciHandle { 
        bool _connectionIsBroken; 
        internal OciErrorHandle(OciHandle parent) : base(parent, OCI.HTYPE.OCI_HTYPE_ERROR) {}
 
        internal bool ConnectionIsBroken {
            get {
                return _connectionIsBroken;
            } 
            set {
                _connectionIsBroken = value; 
            } 
        }
    } 

    sealed internal class OciDateTimeDescriptor : OciHandle {
        internal OciDateTimeDescriptor(OciHandle parent, OCI.HTYPE dateTimeType)
            : base(parent, AssertDateTimeType(dateTimeType)) 
        {
        } 
 
        static OCI.HTYPE AssertDateTimeType(OCI.HTYPE dateTimeType)
        { 
            Debug.Assert(
                dateTimeType == OCI.HTYPE.OCI_DTYPE_TIMESTAMP ||
                dateTimeType == OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ ||
                dateTimeType == OCI.HTYPE.OCI_DTYPE_TIMESTAMP_LTZ, 
                "unexpected OciDateTime handleType");
 
            return dateTimeType; 
        }
    } 

    sealed internal class OciFileDescriptor : OciHandle {
        internal OciFileDescriptor(OciHandle parent) : base(parent, OCI.HTYPE.OCI_DTYPE_FILE) {}
 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal int OCILobFileSetNameWrapper( OciHandle envhp, OciHandle errhp, byte[] dirAlias, ushort dirAliasLength, byte[] fileName, ushort fileNameLength) { 
            int rc; 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                RuntimeHelpers.PrepareConstrainedRegions(); 
                try {} finally {
                    IntPtr bfileDescriptor = DangerousGetHandle(); 
 
                    rc = UnsafeNativeMethods.OCILobFileSetName(
                                                envhp, 
                                                errhp,
                                                ref bfileDescriptor,
                                                dirAlias,
                                                dirAliasLength, 
                                                fileName,
                                                fileNameLength); 
                    base.handle = bfileDescriptor; 
                }
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
            return rc; 
        } 
    };
 
    sealed internal class OciIntervalDescriptor : OciHandle {
        internal OciIntervalDescriptor(OciHandle parent) : base(parent, OCI.HTYPE.OCI_DTYPE_INTERVAL_DS) {
        }
    } 

    sealed internal class OciLobDescriptor : OciHandle { 
        internal OciLobDescriptor(OciHandle parent) : base(parent, OCI.HTYPE.OCI_DTYPE_LOB) {} 
    }
 
    sealed internal class OciNlsEnvironmentHandle : OciHandle {
        internal OciNlsEnvironmentHandle(OCI.MODE environmentMode )
            : base(null, OCI.HTYPE.OCI_HTYPE_ENV, environmentMode, HANDLEFLAG.NLS) {}
    } 

    sealed internal class OciRowidDescriptor : OciHandle { 
        internal OciRowidDescriptor(OciHandle parent) : base(parent, OCI.HTYPE.OCI_DTYPE_ROWID) {} 

        internal void GetRowid( OciStatementHandle statementHandle, OciErrorHandle errorHandle ) { 
            uint zero = 0;
            int rc = TracedNativeMethods.OCIAttrGet( statementHandle, this, out zero, OCI.ATTR.OCI_ATTR_ROWID, errorHandle );

            if ((int)OCI.RETURNCODE.OCI_NO_DATA == rc) { 
                Dispose();
            } 
            else if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            } 
        }

    }
 
    sealed internal class OciServerHandle : OciHandle {
        internal OciServerHandle(OciHandle parent) : base(parent, OCI.HTYPE.OCI_HTYPE_SERVER, OCI.MODE.OCI_DEFAULT, HANDLEFLAG.DEFAULT) {} 
    } 

    sealed internal class OciServiceContextHandle : OciHandle { 
        internal OciServiceContextHandle(OciHandle parent) : base(parent, OCI.HTYPE.OCI_HTYPE_SVCCTX, OCI.MODE.OCI_DEFAULT, HANDLEFLAG.DEFAULT) {}
    }

    sealed internal class OciSessionHandle:OciHandle{ 
        internal OciSessionHandle(OciHandle parent):base(parent, OCI.HTYPE.OCI_HTYPE_SESSION, OCI.MODE.OCI_DEFAULT, HANDLEFLAG.DEFAULT){}
    } 
 
    sealed internal class OciStatementHandle : OciHandle {
 
        internal OciStatementHandle(OciHandle parent) : base(parent, OCI.HTYPE.OCI_HTYPE_STMT) {
        }

        internal OciParameterDescriptor GetDescriptor(int i, OciErrorHandle errorHandle) { 
            // Wraps the OCIParamGet call. We do not expect it to fail, so we
            // will throw if it does. 
 
            IntPtr paramdesc;
            int rc = TracedNativeMethods.OCIParamGet(this, HandleType, errorHandle, out paramdesc, i+1 ); // NOTE: Oracle is 1-based, but we're zero-based. 

            if (0 != rc) {
                OracleException.Check(errorHandle, rc);
            } 
            OciParameterDescriptor result = new OciParameterDescriptor(this, paramdesc);
            return result; 
        } 

        internal OciRowidDescriptor GetRowid( OciHandle environmentHandle, OciErrorHandle errorHandle ) { 
            OciRowidDescriptor rowidHandle = new OciRowidDescriptor(environmentHandle);
            rowidHandle.GetRowid(this, errorHandle);
            return rowidHandle;
        } 
    }
 
/*+---------------------------------------------------------------------------------------------------+*/ 
// should be moved to a separate file
 
    abstract internal class OciSimpleHandle : OciHandle {
        // This class implements OciHandle for handle types that do not require
        // cricial finalization.
 
        internal OciSimpleHandle(OciHandle parent, OCI.HTYPE handleType, IntPtr value) : base(handleType) {
            base.handle = value; 
        } 

        public override bool IsInvalid { 
            get {
                return true;    // guarantees we never try and release this...
            }
        } 
    }
 
    sealed internal class OciBindHandle : OciSimpleHandle { 
        internal OciBindHandle(OciHandle parent, IntPtr value) : base(parent, OCI.HTYPE.OCI_HTYPE_BIND, value) {
        } 
    };

    sealed internal class OciDefineHandle : OciSimpleHandle {
        internal OciDefineHandle(OciHandle parent, IntPtr value) : base(parent, OCI.HTYPE.OCI_HTYPE_DEFINE, value) { 
        }
    }; 
 
    sealed internal class OciParameterDescriptor : OciSimpleHandle {
        internal OciParameterDescriptor(OciHandle parent, IntPtr value) : base(parent, OCI.HTYPE.OCI_DTYPE_PARAM, value) { 
        }
    };

} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Data.OracleClient 
{
    using System; 
    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;
 
    //---------------------------------------------------------------------
    // OciHandle
    //
    // Class to manage the lifetime of Oracle Call Interface handles, and 
    // to simplify a number of handle-related operations
    // 
    abstract internal class OciHandle : SafeHandle { 
        [Flags]
        protected enum HANDLEFLAG { 
            DEFAULT     =   0,
            UNICODE     =   1<<0,
            NLS         =   1<<1,
        } 

        private OCI.HTYPE   _handleType; 
        private int         _refCount; 
        private OciHandle   _parentHandle;
        private bool        _isUnicode; 

        // default constructor
        protected OciHandle() : base(IntPtr.Zero, true) {
        } 

        // OciSimpleHandle constructor 
        protected OciHandle(OCI.HTYPE handleType) : base(IntPtr.Zero, false) { 
            _handleType   = handleType;
        } 

        protected OciHandle(OciHandle parentHandle, OCI.HTYPE handleType) : this(parentHandle, handleType, OCI.MODE.OCI_DEFAULT, HANDLEFLAG.DEFAULT) {
        }
 

        protected OciHandle(OciHandle parentHandle, OCI.HTYPE handleType, OCI.MODE ocimode, HANDLEFLAG handleflags) : this() { 
            int rc; 

            Debug.Assert (!(parentHandle is OciSimpleHandle), "Must not create handle on top of OciSimpleHandle"); 

            RuntimeHelpers.PrepareConstrainedRegions();
            try {} finally {
 
                _handleType   = handleType;
                _parentHandle = parentHandle; 
                _refCount     = 1; 

                // 
                switch (handleType) {
                case OCI.HTYPE.OCI_HTYPE_ENV:
                    Debug.Assert(null == parentHandle, "not null parentHandle?");
 
                    if ((handleflags & HANDLEFLAG.NLS) == HANDLEFLAG.NLS) {
                        rc = TracedNativeMethods.OCIEnvNlsCreate( 
                                                out base.handle, 
                                                ocimode,
                                                0, 
                                                0);

                        if (0 != rc || IntPtr.Zero == base.handle) {
                            throw ADP.OperationFailed("OCIEnvNlsCreate", rc); 
                        }
                    } 
                    else { 
                        rc = TracedNativeMethods.OCIEnvCreate(
                                                out base.handle, 
                                                ocimode);

                        if (0 != rc || IntPtr.Zero == base.handle) {
                            throw ADP.OperationFailed("OCIEnvCreate", rc); 
                        }
                    } 
                    break; 

                case OCI.HTYPE.OCI_HTYPE_ERROR: 
                case OCI.HTYPE.OCI_HTYPE_SERVER:
                case OCI.HTYPE.OCI_HTYPE_SVCCTX:
                case OCI.HTYPE.OCI_HTYPE_SESSION:
                case OCI.HTYPE.OCI_HTYPE_STMT: 
                    Debug.Assert(null != parentHandle, "null parentHandle?");
 
                    rc = TracedNativeMethods.OCIHandleAlloc( 
                                                parentHandle.EnvironmentHandle,
                                                out base.handle, 
                                                handleType);

                    if (0 != rc || IntPtr.Zero == base.handle) {
                        throw ADP.OperationFailed("OCIHandleAlloc", rc); 
                    }
                    break; 
 
                case OCI.HTYPE.OCI_DTYPE_LOB:
                case OCI.HTYPE.OCI_DTYPE_FILE: 
                case OCI.HTYPE.OCI_DTYPE_ROWID:
                case OCI.HTYPE.OCI_DTYPE_TIMESTAMP:
                case OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ:
                case OCI.HTYPE.OCI_DTYPE_TIMESTAMP_LTZ: 
                case OCI.HTYPE.OCI_DTYPE_INTERVAL_DS:
                    Debug.Assert(null != parentHandle, "null parentHandle?"); 
 
                    rc = TracedNativeMethods.OCIDescriptorAlloc(
                                                parentHandle.EnvironmentHandle, 
                                                out base.handle,
                                                handleType);

                    if (0 != rc || IntPtr.Zero == base.handle) { 
                        throw ADP.OperationFailed("OCIDescriptorAlloc", rc);
                    } 
                    break; 

 
                case OCI.HTYPE.OCI_HTYPE_BIND:
                case OCI.HTYPE.OCI_HTYPE_DEFINE:
                case OCI.HTYPE.OCI_DTYPE_PARAM:
                    Debug.Assert(null != parentHandle, "null parentHandle?"); 
                    // These three handles are Simple OCI handles -- they do not
                    // need to be freed. 
                    break; 

                default: 
                    Debug.Assert(false, "unexpected handleType");
                    break;
                }
 
                // If we get here, we successfully allocated the handle, so we had
                // better better up the parent's ref count. 
                if (null != parentHandle) { 
                    parentHandle.AddRef();
                    _isUnicode = parentHandle.IsUnicode; 
                }
                else {
                    _isUnicode = (handleflags & HANDLEFLAG.UNICODE) == HANDLEFLAG.UNICODE;
                } 
            }
        } 
 
        internal OciHandle EnvironmentHandle {
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
            get {
                OciHandle value;

                if (HandleType == OCI.HTYPE.OCI_HTYPE_ENV) { 
                    value = this;
                } 
                else { 
                    value = ParentHandle.EnvironmentHandle;
                } 
                return value;
            }
        }
 
        internal OCI.HTYPE HandleType {
            get { 
                return _handleType; 
            }
        } 

        public override bool IsInvalid {
            get {
                return (IntPtr.Zero == base.handle); 
            }
        } 
 
        internal bool IsUnicode {
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
            get {
                return _isUnicode;
            }
        } 

        internal OciHandle ParentHandle { 
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
            get {
                return _parentHandle; 
            }
        }

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
        internal int AddRef() {
            int refCount = Interlocked.Increment(ref _refCount); 
            return refCount; 
        }
 
        //    Wrap the OCIAttrGet calls.  We do not expect OCIAttrGet to fail,
        //    so we will throw if it does.  There are multiple overloads here,
        //    one for each type of parameter that Oracle supports
 
        internal void GetAttribute(OCI.ATTR attribute, out byte value, OciErrorHandle errorHandle) {
            uint zero = 0; 
            int rc = TracedNativeMethods.OCIAttrGet( this, out value, out zero, attribute, errorHandle ); 

            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            }
        }
 
        internal void GetAttribute(OCI.ATTR attribute, out short value, OciErrorHandle errorHandle) {
            uint zero = 0; 
            int rc = TracedNativeMethods.OCIAttrGet( this, out value, out zero, attribute, errorHandle ); 

            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            }
        }
 
        internal void GetAttribute(OCI.ATTR attribute, out int value, OciErrorHandle errorHandle) {
            uint zero = 0; 
            int rc = TracedNativeMethods.OCIAttrGet( this, out value, out zero, attribute, errorHandle ); 

            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            }
        }
 
        internal void GetAttribute(OCI.ATTR attribute, out string value, OciErrorHandle errorHandle, OracleConnection connection) {
            IntPtr    tempptr = IntPtr.Zero;  // note: no need to clean up tempptr pointer 
            uint      tempub4 = 0; 
            int rc = TracedNativeMethods.OCIAttrGet( this, ref tempptr, ref tempub4, attribute, errorHandle );
 
            if (0 != rc) {
                OracleException.Check(errorHandle, rc);
            }
 
            byte[]  bytearray = new byte[tempub4];
            Marshal.Copy(tempptr, bytearray, 0, checked((int)tempub4)); 
            value = connection.GetString(bytearray); 
        }
 
        internal byte[] GetBytes(string value) {
            byte[]     result;
            uint       valueLength = (uint)value.Length;
 
            if (IsUnicode) {
                result = new byte[valueLength * ADP.CharSize]; 
                GetBytes(value.ToCharArray(), 0, valueLength, result, 0); 
            }
            else { 
                byte[] temp       = new byte[valueLength * 4];    // one Unicode character can map to up to 4 bytes
                uint   tempLength = GetBytes(value.ToCharArray(), 0, valueLength, temp, 0);

                result = new byte[tempLength]; 

                Buffer.BlockCopy(temp, 0, result, 0, checked ((int)tempLength)); 
            } 
            return result;
        } 

        internal uint GetBytes(char[] chars, int charIndex, uint charCount, byte[] bytes, int byteIndex) {
            uint byteCount;
 
            if (IsUnicode) {
                byteCount = checked ((uint)(charCount * ADP.CharSize)); 
                Buffer.BlockCopy(chars, charIndex*ADP.CharSize, bytes, byteIndex, checked ((int)byteCount)); 
            }
            else { 
                OciHandle environmentHandle = EnvironmentHandle;
                GCHandle  charsHandle = new GCHandle();
                GCHandle  bytesHandle = new GCHandle();
                int       rc; 

                try { 
                    charsHandle = GCHandle.Alloc(chars, GCHandleType.Pinned); 

                    IntPtr charsPtr = new IntPtr((long)charsHandle.AddrOfPinnedObject() + charIndex); 
                    IntPtr bytesPtr;

                    if (null == bytes) {
                        bytesPtr = IntPtr.Zero; 
                        byteCount = 0;
                    } 
                    else { 
                        bytesHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                        bytesPtr = new IntPtr((long)bytesHandle.AddrOfPinnedObject() + byteIndex); 
                        byteCount = checked((uint)(bytes.Length-byteIndex));
                    }
                    rc = UnsafeNativeMethods.OCIUnicodeToCharSet(
                                                environmentHandle, 
                                                bytesPtr,
                                                byteCount, 
                                                charsPtr, 
                                                charCount,
                                                out byteCount 
                                                );
                }
                finally {
                    charsHandle.Free(); 

                    if (bytesHandle.IsAllocated) 
                        bytesHandle.Free(); 
                }
 
                if (0 != rc) {
                    throw ADP.OperationFailed("OCIUnicodeToCharSet", rc);
                }
            } 
            return byteCount;
        } 
 
        internal uint GetChars(byte[] bytes, int byteIndex, uint byteCount, char[] chars, int charIndex) {
            uint charCount; 

            if (IsUnicode) {
                Debug.Assert(0 == (byteCount & 0x1), "Odd Number of Unicode Bytes?");
                charCount = checked ((uint)(byteCount / ADP.CharSize)); 
                Buffer.BlockCopy(bytes, byteIndex, chars, charIndex*ADP.CharSize, checked((int)byteCount));
            } 
            else { 
                OciHandle environmentHandle = EnvironmentHandle;
                GCHandle bytesHandle = new GCHandle(); 
                GCHandle charsHandle = new GCHandle();
                int rc;

                try { 
                    bytesHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                    IntPtr bytesPtr = new IntPtr((long)bytesHandle.AddrOfPinnedObject() + byteIndex); 
                    IntPtr charsPtr; 

                    if (null == chars) { 
                        charsPtr = IntPtr.Zero;
                        charCount = 0;
                    }
                    else { 
                        charsHandle = GCHandle.Alloc(chars, GCHandleType.Pinned);
                        charsPtr = new IntPtr((long)charsHandle.AddrOfPinnedObject() + charIndex); 
                        charCount = checked((uint)(chars.Length-charIndex)); 
                    }
 
                    rc = UnsafeNativeMethods.OCICharSetToUnicode(
                                            environmentHandle,
                                            charsPtr,
                                            charCount, 
                                            bytesPtr,
                                            byteCount, 
                                            out charCount 
                                            );
                } 
                finally {
                    bytesHandle.Free();
                    if (charsHandle.IsAllocated)
                        charsHandle.Free(); 
                }
 
                if (0 != rc) { 
                    throw ADP.OperationFailed("OCICharSetToUnicode", rc);
                } 
            }
            return charCount;
        }
 
        //---------------------------------------------------------------------
        static internal string GetAttributeName 
            ( 
            OciHandle       handle,
            OCI.ATTR        atype 
            )
        {
            if (OCI.HTYPE.OCI_DTYPE_PARAM == handle.HandleType)
                return ((OCI.PATTR)atype).ToString(); 

            return atype.ToString(); 
        } 

        //---------------------------------------------------------------------- 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        static internal IntPtr HandleValueToTrace ( OciHandle handle )
        {
            return handle.DangerousGetHandle();  // for tracing purposes, it's safe to just print this -- no handle recycling issues. 
        }
 
        internal string PtrToString(NativeBuffer buf) { 
            string result = null;
 
            if (IsUnicode)
                result = buf.PtrToStringUni(0);
            else
                result = buf.PtrToStringAnsi(0); 
            return result;
        } 
 
        internal string PtrToString(IntPtr buf, int len) {
            string result; 

            if (IsUnicode)
                result = Marshal.PtrToStringUni(buf, len);
            else 
                result = Marshal.PtrToStringAnsi(buf, len);
            return result; 
        } 

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
        internal int Release() {

            int refCount;
 
            RuntimeHelpers.PrepareConstrainedRegions();
            try {} finally { 
 
                refCount = Interlocked.Decrement(ref _refCount);
 
                Debug.Assert (0 <= refCount, "refCount is negative?");

                if (0 == refCount) {
                    //Debug.WriteLine(String.Format("Releasing hande={0} value={1}", HandleTypeToString(this), HandleValueToString(base.handle))); 

                    IntPtr handle = Interlocked.CompareExchange(ref base.handle, IntPtr.Zero, base.handle); 
 
                    if (IntPtr.Zero != handle) {
                        OCI.HTYPE handleType   = HandleType; 
                        OciHandle parentHandle = ParentHandle;
                        int rc;

                        switch (handleType) { 
                        case OCI.HTYPE.OCI_HTYPE_ENV:
                            Debug.Assert(null == parentHandle, "not null parentHandle?"); 
 
                            rc = TracedNativeMethods.OCIHandleFree(handle, handleType);
 
                            if (0 != rc) {
                                throw ADP.OperationFailed("OCIHandleFree", rc);
                            }
                            break; 

                        case OCI.HTYPE.OCI_HTYPE_SERVER: 
                            Debug.Assert(null != parentHandle, "null parentHandle?"); 
                            Debug.Assert(OCI.HTYPE.OCI_HTYPE_ERROR == parentHandle.HandleType, "parentHandle of server handle must be the error handle!");
 
                            // NOTE: while it might seem to be a problem here that
                            //       we are using DangerousGetHandle on the parent
                            //       handle here, the reason that we're doing it is
                            //       that we're in shutdown mode and the handle may 
                            //       have already been released -- attempting to use
                            //       it any other way would cause the CLR to throw 
                            //       an ObjectDisposedException wit the message 
                            //       "Safe handle has been closed".  The reasons for
                            //       this are that we're using our ref-counting 
                            //       to enforce a specific release order, but the
                            //       GC will let the safehandle be closed long
                            //       before all of the handles that have a ref-
                            //       counts on this handle are closed, which means 
                            //       that the last one will cause the server detach
                            //       call. 
                            // 
                            //       There is no likelihood of having a handle
                            //       recycling attack here, because we're making 
                            //       the call that we would have been making in
                            //       ReleaseHandle -- we still own the handle
                            //       until ServerDetach is called.
                            TracedNativeMethods.OCIServerDetach(handle, parentHandle.DangerousGetHandle(), OCI.MODE.OCI_DEFAULT); 
                            // we eat failures here -- what would you suggest we do otherwise?
 
                            goto case OCI.HTYPE.OCI_HTYPE_SESSION; 

                        case OCI.HTYPE.OCI_HTYPE_SVCCTX: 
                            // NOTE: while it might seem to be a problem here that
                            //       we are using DangerousGetHandle on the parent
                            //       handle here, the reason that we're doing it is
                            //       that we're in shutdown mode and the handle may 
                            //       have already been released -- attempting to use
                            //       it any other way would cause the CLR to throw 
                            //       an ObjectDisposedException wit the message 
                            //       "Safe handle has been closed".  The reasons for
                            //       this are that we're using our ref-counting 
                            //       to enforce a specific release order, but the
                            //       GC will let the safehandle be closed long
                            //       before all of the handles that have a ref-
                            //       counts on this handle are closed, which means 
                            //       that the last one will cause the server detach
                            //       call. 
                            // 
                            //       There is no likelihood of having a handle
                            //       recycling attack here, because we're making 
                            //       the call that we would have been making in
                            //       ReleaseHandle -- we still own the handle
                            //       until they are freed, and our ref counting
                            //       prevents them from being freed out of order. 
                            OciHandle sessionHandle = parentHandle;
                            if (null != sessionHandle) { 
                                OciHandle serverHandle = sessionHandle.ParentHandle; 
                                if (null != serverHandle) {
                                    OciHandle errorHandle = serverHandle.ParentHandle; 
                                    if (null != errorHandle) {
                                        rc = TracedNativeMethods.OCISessionEnd(
                                                                    handle,                             // svchp
                                                                    errorHandle.DangerousGetHandle(),   // errhp 
                                                                    sessionHandle.DangerousGetHandle(), // usrhp
                                                                    OCI.MODE.OCI_DEFAULT    // mode 
                                                                    ); 
                                    }
                                } 
                            }
                            // we eat failures here -- what would you suggest we do otherwise?

                            goto case OCI.HTYPE.OCI_HTYPE_ERROR; 

                        case OCI.HTYPE.OCI_HTYPE_ERROR: 
                        case OCI.HTYPE.OCI_HTYPE_SESSION: 
                        case OCI.HTYPE.OCI_HTYPE_STMT:
                            Debug.Assert(null != parentHandle, "null parentHandle?"); 

                            rc = TracedNativeMethods.OCIHandleFree(handle, handleType);

                            if (0 != rc) { 
                                throw ADP.OperationFailed("OCIHandleFree", rc);
                            } 
                            break; 

                        case OCI.HTYPE.OCI_DTYPE_LOB: 
                        case OCI.HTYPE.OCI_DTYPE_FILE:
                        case OCI.HTYPE.OCI_DTYPE_ROWID:
                        case OCI.HTYPE.OCI_DTYPE_TIMESTAMP:
                        case OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ: 
                        case OCI.HTYPE.OCI_DTYPE_TIMESTAMP_LTZ:
                        case OCI.HTYPE.OCI_DTYPE_INTERVAL_DS: 
                            Debug.Assert(null != parentHandle, "null parentHandle?"); 

                            rc = TracedNativeMethods.OCIDescriptorFree(handle, handleType); 

                            if (0 != rc) {
                                throw ADP.OperationFailed("OCIDescriptorFree", rc);
                            } 
                            break;
 
                        default: 
                            Debug.Assert(false, "unexpected handleType");
                            break; 
                        }

                        // If we ended up getting released, then we have to release
                        // our reference on our parent. 
                        if (null != parentHandle) {
                            parentHandle.Release(); 
                        } 
                    }
                } 
            }
            return refCount;
        }
 
        override protected bool ReleaseHandle() {
            //Debug.WriteLine(String.Format("ReleaseHandle type={0} value={1}", HandleTypeToString(this), HandleValueToString(this))); 
            // NOTE: The SafeHandle class guarantees this will be called exactly once. 
            Release();
            return true; 
        }

        static internal void SafeDispose(ref OciHandle handle) {
            //    Safely disposes of the handle (even if it is already null) and 
            //    then nulls it out.
            if (null != handle) { 
                handle.Dispose(); 
            }
            handle = null; 
        }
        static internal void SafeDispose (ref OciEnvironmentHandle handle) {
            if (handle != null) {
                handle.Dispose(); 
            }
            handle = null; 
        } 
        static internal void SafeDispose (ref OciErrorHandle handle) {
            if (handle != null) { 
                handle.Dispose();
            }
            handle = null;
        } 
        static internal void SafeDispose (ref OciRowidDescriptor handle) {
            if (handle != null) { 
                handle.Dispose(); 
            }
            handle = null; 
        }
        static internal void SafeDispose(ref OciStatementHandle handle) {
            if (null != handle) {
                handle.Dispose(); 
            }
            handle = null; 
        } 
        static internal void SafeDispose(ref OciSessionHandle handle) {
            if (null != handle) { 
                handle.Dispose();
            }
            handle = null;
        } 
        static internal void SafeDispose(ref OciServiceContextHandle handle) {
            if (null != handle) { 
                handle.Dispose(); 
            }
            handle = null; 
        }
        static internal void SafeDispose(ref OciServerHandle handle) {
            if (null != handle) {
                handle.Dispose(); 
            }
            handle = null; 
        } 
        static internal void SafeDispose (ref OciDefineHandle handle) {
            if (handle != null) { 
                handle.Dispose();
            }
            handle = null;
        } 

        static internal void SafeDispose (ref OciBindHandle handle) { 
            if (handle != null) { 
                handle.Dispose();
            } 
            handle = null;
        }

        static internal void SafeDispose (ref OciParameterDescriptor handle) { 
            if (handle != null) {
                handle.Dispose(); 
            } 
            handle = null;
        } 

        static internal void SafeDispose(ref OciDateTimeDescriptor handle)
        {
            if (handle != null) 
            {
                handle.Dispose(); 
            } 
            handle = null;
        } 


        //    Wrap the OCIAttrSet calls.  We do not expect OCIAttrSet to fail,
        //    so we will throw if it does.  There are multiple overloads here, 
        //    one for each type of parameter that Oracle supports
 
        internal void SetAttribute(OCI.ATTR attribute, int value, OciErrorHandle errorHandle) { 
            int rc = TracedNativeMethods.OCIAttrSet(
                        this,            // trgthndlp/trghndltyp 
                        ref value,        // attributep
                        0,                // size
                        attribute,        // attrtype
                        errorHandle        // errhp 
                        );
 
            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            } 
        }

        internal void SetAttribute(OCI.ATTR attribute, OciHandle value, OciErrorHandle errorHandle) {
             int rc = TracedNativeMethods.OCIAttrSet( 
                        this,            // trgthndlp/trghndltyp
                        value,            // attributep 
                        0,                // size 
                        attribute,        // attrtype
                        errorHandle        // errhp 
                        );

            if (0 != rc) {
                OracleException.Check(errorHandle, rc); 
            }
        } 
 
        internal void SetAttribute(OCI.ATTR attribute, string value, OciErrorHandle errorHandle) {
 
            uint valueLengthAsChars = unchecked((uint)value.Length);
            byte[] valueAsBytes = new byte[valueLengthAsChars * 4];
            uint valueLengthAsBytes = GetBytes(value.ToCharArray(), 0, valueLengthAsChars, valueAsBytes, 0);
 
            int rc = TracedNativeMethods.OCIAttrSet(
                        this,                // trgthndlp/trghndltyp 
                        valueAsBytes,        // attributep 
                        valueLengthAsBytes,  // size
                        attribute,           // attrtype 
                        errorHandle          // errhp
                        );

            if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            } 
        } 
    }
 
    sealed internal class OciEnvironmentHandle : OciHandle {
        internal OciEnvironmentHandle(OCI.MODE environmentMode, bool unicode)
            : base(null, OCI.HTYPE.OCI_HTYPE_ENV, environmentMode, unicode?HANDLEFLAG.UNICODE:HANDLEFLAG.DEFAULT) {}
    } 

    sealed internal class OciErrorHandle : OciHandle { 
        bool _connectionIsBroken; 
        internal OciErrorHandle(OciHandle parent) : base(parent, OCI.HTYPE.OCI_HTYPE_ERROR) {}
 
        internal bool ConnectionIsBroken {
            get {
                return _connectionIsBroken;
            } 
            set {
                _connectionIsBroken = value; 
            } 
        }
    } 

    sealed internal class OciDateTimeDescriptor : OciHandle {
        internal OciDateTimeDescriptor(OciHandle parent, OCI.HTYPE dateTimeType)
            : base(parent, AssertDateTimeType(dateTimeType)) 
        {
        } 
 
        static OCI.HTYPE AssertDateTimeType(OCI.HTYPE dateTimeType)
        { 
            Debug.Assert(
                dateTimeType == OCI.HTYPE.OCI_DTYPE_TIMESTAMP ||
                dateTimeType == OCI.HTYPE.OCI_DTYPE_TIMESTAMP_TZ ||
                dateTimeType == OCI.HTYPE.OCI_DTYPE_TIMESTAMP_LTZ, 
                "unexpected OciDateTime handleType");
 
            return dateTimeType; 
        }
    } 

    sealed internal class OciFileDescriptor : OciHandle {
        internal OciFileDescriptor(OciHandle parent) : base(parent, OCI.HTYPE.OCI_DTYPE_FILE) {}
 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal int OCILobFileSetNameWrapper( OciHandle envhp, OciHandle errhp, byte[] dirAlias, ushort dirAliasLength, byte[] fileName, ushort fileNameLength) { 
            int rc; 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                RuntimeHelpers.PrepareConstrainedRegions(); 
                try {} finally {
                    IntPtr bfileDescriptor = DangerousGetHandle(); 
 
                    rc = UnsafeNativeMethods.OCILobFileSetName(
                                                envhp, 
                                                errhp,
                                                ref bfileDescriptor,
                                                dirAlias,
                                                dirAliasLength, 
                                                fileName,
                                                fileNameLength); 
                    base.handle = bfileDescriptor; 
                }
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
            return rc; 
        } 
    };
 
    sealed internal class OciIntervalDescriptor : OciHandle {
        internal OciIntervalDescriptor(OciHandle parent) : base(parent, OCI.HTYPE.OCI_DTYPE_INTERVAL_DS) {
        }
    } 

    sealed internal class OciLobDescriptor : OciHandle { 
        internal OciLobDescriptor(OciHandle parent) : base(parent, OCI.HTYPE.OCI_DTYPE_LOB) {} 
    }
 
    sealed internal class OciNlsEnvironmentHandle : OciHandle {
        internal OciNlsEnvironmentHandle(OCI.MODE environmentMode )
            : base(null, OCI.HTYPE.OCI_HTYPE_ENV, environmentMode, HANDLEFLAG.NLS) {}
    } 

    sealed internal class OciRowidDescriptor : OciHandle { 
        internal OciRowidDescriptor(OciHandle parent) : base(parent, OCI.HTYPE.OCI_DTYPE_ROWID) {} 

        internal void GetRowid( OciStatementHandle statementHandle, OciErrorHandle errorHandle ) { 
            uint zero = 0;
            int rc = TracedNativeMethods.OCIAttrGet( statementHandle, this, out zero, OCI.ATTR.OCI_ATTR_ROWID, errorHandle );

            if ((int)OCI.RETURNCODE.OCI_NO_DATA == rc) { 
                Dispose();
            } 
            else if (0 != rc) { 
                OracleException.Check(errorHandle, rc);
            } 
        }

    }
 
    sealed internal class OciServerHandle : OciHandle {
        internal OciServerHandle(OciHandle parent) : base(parent, OCI.HTYPE.OCI_HTYPE_SERVER, OCI.MODE.OCI_DEFAULT, HANDLEFLAG.DEFAULT) {} 
    } 

    sealed internal class OciServiceContextHandle : OciHandle { 
        internal OciServiceContextHandle(OciHandle parent) : base(parent, OCI.HTYPE.OCI_HTYPE_SVCCTX, OCI.MODE.OCI_DEFAULT, HANDLEFLAG.DEFAULT) {}
    }

    sealed internal class OciSessionHandle:OciHandle{ 
        internal OciSessionHandle(OciHandle parent):base(parent, OCI.HTYPE.OCI_HTYPE_SESSION, OCI.MODE.OCI_DEFAULT, HANDLEFLAG.DEFAULT){}
    } 
 
    sealed internal class OciStatementHandle : OciHandle {
 
        internal OciStatementHandle(OciHandle parent) : base(parent, OCI.HTYPE.OCI_HTYPE_STMT) {
        }

        internal OciParameterDescriptor GetDescriptor(int i, OciErrorHandle errorHandle) { 
            // Wraps the OCIParamGet call. We do not expect it to fail, so we
            // will throw if it does. 
 
            IntPtr paramdesc;
            int rc = TracedNativeMethods.OCIParamGet(this, HandleType, errorHandle, out paramdesc, i+1 ); // NOTE: Oracle is 1-based, but we're zero-based. 

            if (0 != rc) {
                OracleException.Check(errorHandle, rc);
            } 
            OciParameterDescriptor result = new OciParameterDescriptor(this, paramdesc);
            return result; 
        } 

        internal OciRowidDescriptor GetRowid( OciHandle environmentHandle, OciErrorHandle errorHandle ) { 
            OciRowidDescriptor rowidHandle = new OciRowidDescriptor(environmentHandle);
            rowidHandle.GetRowid(this, errorHandle);
            return rowidHandle;
        } 
    }
 
/*+---------------------------------------------------------------------------------------------------+*/ 
// should be moved to a separate file
 
    abstract internal class OciSimpleHandle : OciHandle {
        // This class implements OciHandle for handle types that do not require
        // cricial finalization.
 
        internal OciSimpleHandle(OciHandle parent, OCI.HTYPE handleType, IntPtr value) : base(handleType) {
            base.handle = value; 
        } 

        public override bool IsInvalid { 
            get {
                return true;    // guarantees we never try and release this...
            }
        } 
    }
 
    sealed internal class OciBindHandle : OciSimpleHandle { 
        internal OciBindHandle(OciHandle parent, IntPtr value) : base(parent, OCI.HTYPE.OCI_HTYPE_BIND, value) {
        } 
    };

    sealed internal class OciDefineHandle : OciSimpleHandle {
        internal OciDefineHandle(OciHandle parent, IntPtr value) : base(parent, OCI.HTYPE.OCI_HTYPE_DEFINE, value) { 
        }
    }; 
 
    sealed internal class OciParameterDescriptor : OciSimpleHandle {
        internal OciParameterDescriptor(OciHandle parent, IntPtr value) : base(parent, OCI.HTYPE.OCI_DTYPE_PARAM, value) { 
        }
    };

} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK