OdbcHandle.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Data / System / Data / Odbc / OdbcHandle.cs / 1 / OdbcHandle.cs

                            //------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
//----------------------------------------------------------------------------- 
 
using System;
using System.Collections; 
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics; 
using System.Globalization;
using System.Runtime.CompilerServices; 
using System.Runtime.InteropServices; 
using System.Security;
using System.Security.Permissions; 
using System.Text;
using System.Threading;
using System.Runtime.ConstrainedExecution;
 
namespace System.Data.Odbc {
 
    internal abstract class OdbcHandle : SafeHandle { 

        private ODBC32.SQL_HANDLE _handleType; 
        private OdbcHandle        _parentHandle;

        protected OdbcHandle(ODBC32.SQL_HANDLE handleType, OdbcHandle parentHandle) : base(IntPtr.Zero, true) {
 
            _handleType   = handleType;
 
            bool mustRelease = false; 
            ODBC32.RetCode retcode = ODBC32.RetCode.SUCCESS;
 
            // using ConstrainedRegions to make the native ODBC call and AddRef the parent
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                // validate handleType 
                switch(handleType) {
                case ODBC32.SQL_HANDLE.ENV: 
                    Debug.Assert(null == parentHandle, "did not expect a parent handle"); 
                    retcode = UnsafeNativeMethods.SQLAllocHandle(handleType, IntPtr.Zero, out base.handle);
                    break; 
                case ODBC32.SQL_HANDLE.DBC:
                case ODBC32.SQL_HANDLE.STMT:
                    // must addref before calling native so it won't be released just after
                    Debug.Assert(null != parentHandle, "expected a parent handle"); // safehandle can't be null 
                    parentHandle.DangerousAddRef(ref mustRelease);
 
                    retcode = UnsafeNativeMethods.SQLAllocHandle(handleType, parentHandle, out base.handle); 
                    break;
//              case ODBC32.SQL_HANDLE.DESC: 
                default:
                    Debug.Assert(false, "unexpected handleType");
                    break;
                } 
            }
            finally { 
                if (mustRelease) { 
                    switch(handleType) {
                    case ODBC32.SQL_HANDLE.DBC: 
                    case ODBC32.SQL_HANDLE.STMT:
                        if (IntPtr.Zero != base.handle) {
                            // must assign _parentHandle after a handle is actually created
                            // since ReleaseHandle will only call DangerousRelease if a handle exists 
                            _parentHandle = parentHandle;
                        } 
                        else { 
                            // without a handle, ReleaseHandle may not be called
                            parentHandle.DangerousRelease(); 
                        }
                        break;
                    }
                } 
            }
            Bid.TraceSqlReturn(" %08X{SQLRETURN}\n", retcode); 
 
            if((ADP.PtrZero == base.handle) || (ODBC32.RetCode.SUCCESS != retcode)) {
                // 
                throw ODBC.CantAllocateEnvironmentHandle(retcode);
            }
        }
 
        internal OdbcHandle(OdbcStatementHandle parentHandle, ODBC32.SQL_ATTR attribute) : base(IntPtr.Zero, true) {
            Debug.Assert((ODBC32.SQL_ATTR.APP_PARAM_DESC == attribute) || (ODBC32.SQL_ATTR.APP_ROW_DESC == attribute), "invalid attribute"); 
            _handleType   = ODBC32.SQL_HANDLE.DESC; 

            int cbActual; 
            ODBC32.RetCode retcode;
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                // must addref before calling native so it won't be released just after
                parentHandle.DangerousAddRef(ref mustRelease); 
 
                retcode = parentHandle.GetStatementAttribute(attribute, out base.handle, out cbActual);
            } 
            finally {
                if (mustRelease) {
                    if (IntPtr.Zero != base.handle) {
                        // must call DangerousAddRef after a handle is actually created 
                        // since ReleaseHandle will only call DangerousRelease if a handle exists
                        _parentHandle = parentHandle; 
                    } 
                    else {
                        // without a handle, ReleaseHandle may not be called 
                        parentHandle.DangerousRelease();
                    }
                }
            } 
            if (ADP.PtrZero == base.handle) {
                throw ODBC.FailedToGetDescriptorHandle(retcode); 
            } 
            // no info-message handle on getting a descriptor handle
        } 

        internal ODBC32.SQL_HANDLE HandleType {
            get {
                return _handleType; 
            }
        } 
 
        public override bool IsInvalid {
            get { 
                // we should not have a parent if we do not have a handle
                return (IntPtr.Zero == base.handle);
            }
        } 

        override protected bool ReleaseHandle() { 
            // NOTE: The SafeHandle class guarantees this will be called exactly once and is non-interrutible. 
            IntPtr handle = base.handle;
            base.handle = IntPtr.Zero; 

            if (IntPtr.Zero != handle) {
                ODBC32.SQL_HANDLE handleType   = HandleType;
 
                switch (handleType) {
                case ODBC32.SQL_HANDLE.DBC: 
                    // Disconnect happens in OdbcConnectionHandle.ReleaseHandle 
                case ODBC32.SQL_HANDLE.ENV:
                case ODBC32.SQL_HANDLE.STMT: 
                    ODBC32.RetCode retcode = UnsafeNativeMethods.SQLFreeHandle(handleType, handle);
                    Bid.TraceSqlReturn(" %08X{SQLRETURN}\n", retcode);
                    break;
 
                case ODBC32.SQL_HANDLE.DESC:
                    // nothing to free on the handle 
                    break; 

                // case 0: ThreadAbortException setting handle before HandleType 
                default:
                    Debug.Assert(ADP.PtrZero == handle, "unknown handle type");
                    break;
                } 
            }
 
            // If we ended up getting released, then we have to release 
            // our reference on our parent.
            OdbcHandle parentHandle = _parentHandle; 
            _parentHandle = null;
            if (null != parentHandle) {
                parentHandle.DangerousRelease();
                parentHandle = null; 
            }
            return true; 
        } 

        internal ODBC32.RetCode GetDiagnosticField (out string sqlState) { 
            short cbActual;
            // ODBC (MSDN) documents it expects a buffer large enough to hold 5(+L'\0') unicode characters
            StringBuilder sb = new StringBuilder(6);
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDiagFieldW( 
                HandleType,
                this, 
                (short)1, 
                ODBC32.SQL_DIAG_SQLSTATE,
                sb, 
                checked((short)(2*sb.Capacity)), // expects number of bytes, see \\kbinternal\kb\articles\294\1\69.HTM
                out cbActual);
            ODBC.TraceODBC(3, "SQLGetDiagFieldW", retcode);
            if ((retcode == ODBC32.RetCode.SUCCESS) || (retcode == ODBC32.RetCode.SUCCESS_WITH_INFO)) { 
                sqlState = sb.ToString();
            } 
            else { 
                sqlState = ADP.StrEmpty;
            } 
            return retcode;
        }

        internal ODBC32.RetCode GetDiagnosticRecord(short record, out string sqlState, StringBuilder message, out int nativeError, out short cchActual) { 
            // ODBC (MSDN) documents it expects a buffer large enough to hold 4(+L'\0') unicode characters
            StringBuilder sb = new StringBuilder(5); 
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDiagRecW(HandleType, this, record, sb, out nativeError, message, checked((short)message.Capacity), out cchActual); 
            ODBC.TraceODBC(3, "SQLGetDiagRecW", retcode);
 
            if ((retcode == ODBC32.RetCode.SUCCESS) || (retcode == ODBC32.RetCode.SUCCESS_WITH_INFO)) {
                sqlState = sb.ToString();
            }
            else { 
                sqlState = ADP.StrEmpty;
            } 
            return retcode; 
        }
    } 

    sealed internal class OdbcDescriptorHandle : OdbcHandle {

        internal OdbcDescriptorHandle(OdbcStatementHandle statementHandle, ODBC32.SQL_ATTR attribute) : base(statementHandle, attribute) { 
        }
 
        internal ODBC32.RetCode GetDescriptionField(int i, ODBC32.SQL_DESC attribute, CNativeBuffer buffer, out int numericAttribute) { 
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDescFieldW(this, checked((short)i), attribute, buffer, buffer.ShortLength, out numericAttribute);
            ODBC.TraceODBC(3, "SQLGetDescFieldW", retcode); 
            return retcode;
        }

        internal ODBC32.RetCode SetDescriptionField1(short ordinal, ODBC32.SQL_DESC type, IntPtr value) { 
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetDescFieldW(this, ordinal, type, value, 0);
            ODBC.TraceODBC(3, "SQLSetDescFieldW", retcode); 
            return retcode; 
        }
 
        internal ODBC32.RetCode SetDescriptionField2(short ordinal, ODBC32.SQL_DESC type, HandleRef value) {
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetDescFieldW(this, ordinal, type, value, 0);
            ODBC.TraceODBC(3, "SQLSetDescFieldW", retcode);
            return retcode; 
        }
    } 
 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
//----------------------------------------------------------------------------- 
 
using System;
using System.Collections; 
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics; 
using System.Globalization;
using System.Runtime.CompilerServices; 
using System.Runtime.InteropServices; 
using System.Security;
using System.Security.Permissions; 
using System.Text;
using System.Threading;
using System.Runtime.ConstrainedExecution;
 
namespace System.Data.Odbc {
 
    internal abstract class OdbcHandle : SafeHandle { 

        private ODBC32.SQL_HANDLE _handleType; 
        private OdbcHandle        _parentHandle;

        protected OdbcHandle(ODBC32.SQL_HANDLE handleType, OdbcHandle parentHandle) : base(IntPtr.Zero, true) {
 
            _handleType   = handleType;
 
            bool mustRelease = false; 
            ODBC32.RetCode retcode = ODBC32.RetCode.SUCCESS;
 
            // using ConstrainedRegions to make the native ODBC call and AddRef the parent
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                // validate handleType 
                switch(handleType) {
                case ODBC32.SQL_HANDLE.ENV: 
                    Debug.Assert(null == parentHandle, "did not expect a parent handle"); 
                    retcode = UnsafeNativeMethods.SQLAllocHandle(handleType, IntPtr.Zero, out base.handle);
                    break; 
                case ODBC32.SQL_HANDLE.DBC:
                case ODBC32.SQL_HANDLE.STMT:
                    // must addref before calling native so it won't be released just after
                    Debug.Assert(null != parentHandle, "expected a parent handle"); // safehandle can't be null 
                    parentHandle.DangerousAddRef(ref mustRelease);
 
                    retcode = UnsafeNativeMethods.SQLAllocHandle(handleType, parentHandle, out base.handle); 
                    break;
//              case ODBC32.SQL_HANDLE.DESC: 
                default:
                    Debug.Assert(false, "unexpected handleType");
                    break;
                } 
            }
            finally { 
                if (mustRelease) { 
                    switch(handleType) {
                    case ODBC32.SQL_HANDLE.DBC: 
                    case ODBC32.SQL_HANDLE.STMT:
                        if (IntPtr.Zero != base.handle) {
                            // must assign _parentHandle after a handle is actually created
                            // since ReleaseHandle will only call DangerousRelease if a handle exists 
                            _parentHandle = parentHandle;
                        } 
                        else { 
                            // without a handle, ReleaseHandle may not be called
                            parentHandle.DangerousRelease(); 
                        }
                        break;
                    }
                } 
            }
            Bid.TraceSqlReturn(" %08X{SQLRETURN}\n", retcode); 
 
            if((ADP.PtrZero == base.handle) || (ODBC32.RetCode.SUCCESS != retcode)) {
                // 
                throw ODBC.CantAllocateEnvironmentHandle(retcode);
            }
        }
 
        internal OdbcHandle(OdbcStatementHandle parentHandle, ODBC32.SQL_ATTR attribute) : base(IntPtr.Zero, true) {
            Debug.Assert((ODBC32.SQL_ATTR.APP_PARAM_DESC == attribute) || (ODBC32.SQL_ATTR.APP_ROW_DESC == attribute), "invalid attribute"); 
            _handleType   = ODBC32.SQL_HANDLE.DESC; 

            int cbActual; 
            ODBC32.RetCode retcode;
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                // must addref before calling native so it won't be released just after
                parentHandle.DangerousAddRef(ref mustRelease); 
 
                retcode = parentHandle.GetStatementAttribute(attribute, out base.handle, out cbActual);
            } 
            finally {
                if (mustRelease) {
                    if (IntPtr.Zero != base.handle) {
                        // must call DangerousAddRef after a handle is actually created 
                        // since ReleaseHandle will only call DangerousRelease if a handle exists
                        _parentHandle = parentHandle; 
                    } 
                    else {
                        // without a handle, ReleaseHandle may not be called 
                        parentHandle.DangerousRelease();
                    }
                }
            } 
            if (ADP.PtrZero == base.handle) {
                throw ODBC.FailedToGetDescriptorHandle(retcode); 
            } 
            // no info-message handle on getting a descriptor handle
        } 

        internal ODBC32.SQL_HANDLE HandleType {
            get {
                return _handleType; 
            }
        } 
 
        public override bool IsInvalid {
            get { 
                // we should not have a parent if we do not have a handle
                return (IntPtr.Zero == base.handle);
            }
        } 

        override protected bool ReleaseHandle() { 
            // NOTE: The SafeHandle class guarantees this will be called exactly once and is non-interrutible. 
            IntPtr handle = base.handle;
            base.handle = IntPtr.Zero; 

            if (IntPtr.Zero != handle) {
                ODBC32.SQL_HANDLE handleType   = HandleType;
 
                switch (handleType) {
                case ODBC32.SQL_HANDLE.DBC: 
                    // Disconnect happens in OdbcConnectionHandle.ReleaseHandle 
                case ODBC32.SQL_HANDLE.ENV:
                case ODBC32.SQL_HANDLE.STMT: 
                    ODBC32.RetCode retcode = UnsafeNativeMethods.SQLFreeHandle(handleType, handle);
                    Bid.TraceSqlReturn(" %08X{SQLRETURN}\n", retcode);
                    break;
 
                case ODBC32.SQL_HANDLE.DESC:
                    // nothing to free on the handle 
                    break; 

                // case 0: ThreadAbortException setting handle before HandleType 
                default:
                    Debug.Assert(ADP.PtrZero == handle, "unknown handle type");
                    break;
                } 
            }
 
            // If we ended up getting released, then we have to release 
            // our reference on our parent.
            OdbcHandle parentHandle = _parentHandle; 
            _parentHandle = null;
            if (null != parentHandle) {
                parentHandle.DangerousRelease();
                parentHandle = null; 
            }
            return true; 
        } 

        internal ODBC32.RetCode GetDiagnosticField (out string sqlState) { 
            short cbActual;
            // ODBC (MSDN) documents it expects a buffer large enough to hold 5(+L'\0') unicode characters
            StringBuilder sb = new StringBuilder(6);
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDiagFieldW( 
                HandleType,
                this, 
                (short)1, 
                ODBC32.SQL_DIAG_SQLSTATE,
                sb, 
                checked((short)(2*sb.Capacity)), // expects number of bytes, see \\kbinternal\kb\articles\294\1\69.HTM
                out cbActual);
            ODBC.TraceODBC(3, "SQLGetDiagFieldW", retcode);
            if ((retcode == ODBC32.RetCode.SUCCESS) || (retcode == ODBC32.RetCode.SUCCESS_WITH_INFO)) { 
                sqlState = sb.ToString();
            } 
            else { 
                sqlState = ADP.StrEmpty;
            } 
            return retcode;
        }

        internal ODBC32.RetCode GetDiagnosticRecord(short record, out string sqlState, StringBuilder message, out int nativeError, out short cchActual) { 
            // ODBC (MSDN) documents it expects a buffer large enough to hold 4(+L'\0') unicode characters
            StringBuilder sb = new StringBuilder(5); 
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDiagRecW(HandleType, this, record, sb, out nativeError, message, checked((short)message.Capacity), out cchActual); 
            ODBC.TraceODBC(3, "SQLGetDiagRecW", retcode);
 
            if ((retcode == ODBC32.RetCode.SUCCESS) || (retcode == ODBC32.RetCode.SUCCESS_WITH_INFO)) {
                sqlState = sb.ToString();
            }
            else { 
                sqlState = ADP.StrEmpty;
            } 
            return retcode; 
        }
    } 

    sealed internal class OdbcDescriptorHandle : OdbcHandle {

        internal OdbcDescriptorHandle(OdbcStatementHandle statementHandle, ODBC32.SQL_ATTR attribute) : base(statementHandle, attribute) { 
        }
 
        internal ODBC32.RetCode GetDescriptionField(int i, ODBC32.SQL_DESC attribute, CNativeBuffer buffer, out int numericAttribute) { 
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLGetDescFieldW(this, checked((short)i), attribute, buffer, buffer.ShortLength, out numericAttribute);
            ODBC.TraceODBC(3, "SQLGetDescFieldW", retcode); 
            return retcode;
        }

        internal ODBC32.RetCode SetDescriptionField1(short ordinal, ODBC32.SQL_DESC type, IntPtr value) { 
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetDescFieldW(this, ordinal, type, value, 0);
            ODBC.TraceODBC(3, "SQLSetDescFieldW", retcode); 
            return retcode; 
        }
 
        internal ODBC32.RetCode SetDescriptionField2(short ordinal, ODBC32.SQL_DESC type, HandleRef value) {
            ODBC32.RetCode retcode = UnsafeNativeMethods.SQLSetDescFieldW(this, ordinal, type, value, 0);
            ODBC.TraceODBC(3, "SQLSetDescFieldW", retcode);
            return retcode; 
        }
    } 
 
}
 

// 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