TransactionInterop.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / tx / System / Transactions / TransactionInterop.cs / 1305376 / TransactionInterop.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

using System; 
using System.Configuration; 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; 
using System.Security.Permissions;
using System.Transactions.Oletx;
using System.Transactions.Configuration;
using System.Transactions.Diagnostics; 

 
namespace System.Transactions 
{
    // This is here for the "DTC" in the name. 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
    [
    ComImport,
    Guid("0fb15084-af41-11ce-bd2b-204c4f4f5020"), 
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
    ] 
    public interface IDtcTransaction 
    {
        void Commit(int retaining, 
            [MarshalAs(UnmanagedType.I4)] int commitType,
            int reserved);

        void Abort(IntPtr reason, 
            int retaining,
            int async); 
 
        void GetTransactionInfo( IntPtr transactionInformation);
    } 


    [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
    public static class TransactionInterop 
    {
        internal static OletxTransaction ConvertToOletxTransaction( 
            Transaction transaction 
            )
        { 
            if ( null == transaction )
            {
                throw new ArgumentNullException( "transaction" );
            } 

            if ( transaction.Disposed ) 
            { 
                throw new ObjectDisposedException( "Transaction" );
            } 

            if ( transaction.complete )
            {
                throw TransactionException.CreateTransactionCompletedException( SR.GetString( SR.TraceSourceLtm ) ); 
            }
 
            OletxTransaction oletxTx = transaction.Promote(); 
            System.Diagnostics.Debug.Assert( oletxTx != null, "transaction.Promote returned null instead of throwing." );
 
            return oletxTx;
        }

 
        // This is here for the DangerousGetHandle call.  We need to do it.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] 
        public static byte[] GetExportCookie( 
            Transaction transaction,
            byte[] whereabouts 
            )
        {
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();
 
            byte[] cookie = null;
 
            if ( null == transaction ) 
            {
                throw new ArgumentNullException( "transaction" ); 
            }

            if ( null == whereabouts )
            { 
                throw new ArgumentNullException( "whereabouts" );
            } 
 
            if ( DiagnosticTrace.Verbose )
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetExportCookie"
                    );
            } 

            // Copy the whereabouts so that it cannot be modified later. 
            byte[] whereaboutsCopy = new byte[whereabouts.Length]; 
            Array.Copy(whereabouts, whereaboutsCopy, whereabouts.Length);
            whereabouts = whereaboutsCopy; 

            int cookieIndex = 0;
            UInt32 cookieSize = 0;
            CoTaskMemHandle cookieBuffer = null; 

            // First, make sure we are working with an OletxTransaction. 
            OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); 

            try 
            {
                oletxTx.realOletxTransaction.TransactionShim.Export(
                    Convert.ToUInt32(whereabouts.Length),
                    whereabouts, 
                    out cookieIndex,
                    out cookieSize, 
                    out cookieBuffer ); 

                // allocate and fill in the cookie 
                cookie = new byte[cookieSize];
                Marshal.Copy( cookieBuffer.DangerousGetHandle(), cookie, 0, Convert.ToInt32(cookieSize) );
            }
            catch (COMException comException) 
            {
                OletxTransactionManager.ProxyException( comException ); 
 
                // We are unsure of what the exception may mean.  It is possible that
                // we could get E_FAIL when trying to contact a transaction manager that is 
                // being blocked by a fire wall.  On the other hand we may get a COMException
                // based on bad data.  The more common situation is that the data is fine
                // (since it is generated by Microsoft code) and the problem is with
                // communication.  So in this case we default for unknown exceptions to 
                // assume that the problem is with communication.
                throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException ); 
            } 
            finally
            { 
                if ( null != cookieBuffer )
                {
                    cookieBuffer.Close();
                } 
            }
 
            if ( DiagnosticTrace.Verbose ) 
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                    "TransactionInterop.GetExportCookie"
                    );
            }
 
            return cookie;
        } 
 
        public static Transaction GetTransactionFromExportCookie(
            byte[] cookie 
            )
        {
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();
 
            if ( null == cookie )
            { 
                throw new ArgumentNullException( "cookie" ); 
            }
 
            if ( cookie.Length < 32 )
            {
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "cookie" );
            } 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromExportCookie" 
                    );
            }

            byte[] cookieCopy = new byte [cookie.Length]; 
            Array.Copy(cookie, cookieCopy, cookie.Length);
            cookie = cookieCopy; 
 
            Transaction transaction = null;
            ITransactionShim transactionShim = null; 
            Guid txIdentifier = Guid.Empty;
            OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
            OutcomeEnlistment outcomeEnlistment = null;
            OletxTransaction oleTx = null; 

            // Extract the transaction guid from the propagation token to see if we already have a 
            // transaction object for the transaction. 
            byte[] guidByteArray = new byte[16];
            for (int i = 0; i < guidByteArray.Length; i++ ) 
            {
                // In a cookie, the transaction guid is preceeded by a signature guid.
                guidByteArray[i] = cookie[i+16];
            } 

            Guid txId = new Guid( guidByteArray ); 
 
            // First check to see if there is a promoted LTM transaction with the same ID.  If there
            // is, just return that. 
            transaction = TransactionManager.FindPromotedTransaction( txId );
            if ( null != transaction )
            {
                if ( DiagnosticTrace.Verbose ) 
                {
                    MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                        "TransactionInterop.GetTransactionFromExportCookie" 
                        );
                } 
                return transaction;
            }

            // We need to create a new transaction 
            RealOletxTransaction realTx = null;
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; 
 
            oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 );
            try 
            {
                outcomeEnlistment = new OutcomeEnlistment();
                IntPtr outcomeEnlistmentHandle = IntPtr.Zero;
                RuntimeHelpers.PrepareConstrainedRegions(); 
                try
                { 
                    outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); 
                    oletxTm.DtcTransactionManager.ProxyShimFactory.Import(
                        Convert.ToUInt32(cookie.Length), 
                        cookie,
                        outcomeEnlistmentHandle,
                        out txIdentifier,
                        out oletxIsoLevel, 
                        out transactionShim );
                } 
                finally 
                {
                    if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) 
                    {
                        HandleTable.FreeHandle( outcomeEnlistmentHandle );
                    }
                } 
            }
            catch ( COMException comException ) 
            { 
                OletxTransactionManager.ProxyException( comException );
 
                // We are unsure of what the exception may mean.  It is possible that
                // we could get E_FAIL when trying to contact a transaction manager that is
                // being blocked by a fire wall.  On the other hand we may get a COMException
                // based on bad data.  The more common situation is that the data is fine 
                // (since it is generated by Microsoft code) and the problem is with
                // communication.  So in this case we default for unknown exceptions to 
                // assume that the problem is with communication. 
                throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException );
            } 
            finally
            {
                oletxTm.dtcTransactionManagerLock.ReleaseReaderLock();
            } 

            // We need to create a new RealOletxTransaction. 
            realTx = new RealOletxTransaction( 
                oletxTm,
                transactionShim, 
                outcomeEnlistment,
                txIdentifier,
                oletxIsoLevel,
                false ); 

            // Now create the associated OletxTransaction. 
            oleTx = new OletxTransaction( realTx ); 

            // If a transaction is found then FindOrCreate will Dispose the oletx 
            // created.
            transaction = TransactionManager.FindOrCreatePromotedTransaction( txId, oleTx );

            if ( DiagnosticTrace.Verbose ) 
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                    "TransactionInterop.GetTransactionFromExportCookie" 
                    );
            } 

            return transaction;
        }
 

        public static byte[] GetTransmitterPropagationToken( 
            Transaction transaction 
            )
        { 
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();

            if ( null == transaction )
            { 
                throw new ArgumentNullException( "transaction" );
            } 
 
            if ( DiagnosticTrace.Verbose )
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransmitterPropagationToken"
                    );
            } 

            // First, make sure we are working with an OletxTransaction. 
            OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); 

            byte [] token = GetTransmitterPropagationToken( oletxTx ); 

            if ( DiagnosticTrace.Verbose )
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                    "TransactionInterop.GetTransmitterPropagationToken"
                    ); 
            } 

            return token; 
        }


        // This is here for the DangerousGetHandle call.  We need to do it. 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
        internal static byte[] GetTransmitterPropagationToken( 
            OletxTransaction oletxTx 
            )
        { 
            byte[] propagationToken = null;
            CoTaskMemHandle propagationTokenBuffer = null;
            UInt32 tokenSize = 0;
 
            try
            { 
                oletxTx.realOletxTransaction.TransactionShim.GetPropagationToken( 
                    out tokenSize,
                    out propagationTokenBuffer ); 
                propagationToken = new byte[ tokenSize ];
                Marshal.Copy( propagationTokenBuffer.DangerousGetHandle(), propagationToken, 0, Convert.ToInt32(tokenSize) );
            }
            catch (COMException comException) 
            {
                OletxTransactionManager.ProxyException( comException ); 
                throw; 
            }
            finally 
            {
                if ( null != propagationTokenBuffer )
                {
                    propagationTokenBuffer.Close(); 
                }
            } 
 
            return propagationToken;
        } 



        public static Transaction GetTransactionFromTransmitterPropagationToken( 
            byte[] propagationToken
            ) 
        { 
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();
 
            Transaction returnValue = null;

            if ( null == propagationToken )
            { 
                throw new ArgumentNullException( "propagationToken" );
            } 
 
            if ( propagationToken.Length < 24 )
            { 
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "propagationToken" );
            }

            if ( DiagnosticTrace.Verbose ) 
            {
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                    "TransactionInterop.GetTransactionFromTransmitterPropagationToken" 
                    );
            } 

            // Extract the transaction guid from the propagation token to see if we already have a
            // transaction object for the transaction.
            byte[] guidByteArray = new byte[16]; 
            for (int i = 0; i < guidByteArray.Length; i++ )
            { 
                // In a propagation token, the transaction guid is preceeded by two version DWORDs. 
                guidByteArray[i] = propagationToken[i+8];
            } 

            Guid txId = new Guid( guidByteArray );

            // First check to see if there is a promoted LTM transaction with the same ID.  If there 
            // is, just return that.
            Transaction tx = TransactionManager.FindPromotedTransaction( txId ); 
            if ( null != tx ) 
            {
                if ( DiagnosticTrace.Verbose ) 
                {
                    MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                        "TransactionInterop.GetTransactionFromTransmitterPropagationToken"
                        ); 
                }
                return tx; 
            } 

            OletxTransaction oleTx = TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken( propagationToken ); 

            // If a transaction is found then FindOrCreate will Dispose the oletx
            // created.
            returnValue = TransactionManager.FindOrCreatePromotedTransaction( txId, oleTx ); 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromTransmitterPropagationToken" 
                    );
            }
            return returnValue;
        } 

 
 
        internal static OletxTransaction GetOletxTransactionFromTransmitterPropigationToken(
            byte[] propagationToken 
            )
        {
            Guid identifier;
            OletxTransactionIsolationLevel oletxIsoLevel; 
            OutcomeEnlistment outcomeEnlistment;
            ITransactionShim transactionShim = null; 
 
            if ( null == propagationToken )
            { 
                throw new ArgumentNullException( "propagationToken" );
            }

            if ( propagationToken.Length < 24 ) 
            {
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "propagationToken" ); 
            } 

            byte [] propagationTokenCopy = new byte [propagationToken.Length]; 
            Array.Copy(propagationToken, propagationTokenCopy, propagationToken.Length);
            propagationToken = propagationTokenCopy;

            // First we need to create an OletxTransactionManager from Config. 
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;
 
            oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); 
            try
            { 
                outcomeEnlistment = new OutcomeEnlistment();
                IntPtr outcomeEnlistmentHandle = IntPtr.Zero;
                RuntimeHelpers.PrepareConstrainedRegions();
                try 
                {
                    outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); 
                    oletxTm.DtcTransactionManager.ProxyShimFactory.ReceiveTransaction( 
                        Convert.ToUInt32(propagationToken.Length),
                        propagationToken, 
                        outcomeEnlistmentHandle,
                        out identifier,
                        out oletxIsoLevel,
                        out transactionShim 
                        );
                } 
                finally 
                {
                    if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) 
                    {
                        HandleTable.FreeHandle( outcomeEnlistmentHandle );
                    }
                } 
            }
            catch ( COMException comException ) 
            { 
                OletxTransactionManager.ProxyException( comException );
 
                // We are unsure of what the exception may mean.  It is possible that
                // we could get E_FAIL when trying to contact a transaction manager that is
                // being blocked by a fire wall.  On the other hand we may get a COMException
                // based on bad data.  The more common situation is that the data is fine 
                // (since it is generated by Microsoft code) and the problem is with
                // communication.  So in this case we default for unknown exceptions to 
                // assume that the problem is with communication. 
                throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException );
            } 
            finally
            {
                oletxTm.dtcTransactionManagerLock.ReleaseReaderLock();
            } 

            RealOletxTransaction realTx = null; 
 
            realTx = new RealOletxTransaction(
                oletxTm, 
                transactionShim,
                outcomeEnlistment,
                identifier,
                oletxIsoLevel, 
                false );
 
            return new OletxTransaction( realTx ); 
        }
 

        // This is here for the "Dtc" in the name.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
        public static IDtcTransaction GetDtcTransaction( 
            Transaction transaction
            ) 
        { 
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();
 
            if ( null == transaction )
            {
                throw new ArgumentNullException( "transaction" );
            } 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetDtcTransaction" 
                    );
            }

            IDtcTransaction transactionNative = null; 

            // First, make sure we are working with an OletxTransaction. 
            OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); 

            try 
            {
                oletxTx.realOletxTransaction.TransactionShim.GetITransactionNative( out transactionNative );
            }
            catch( COMException comException ) 
            {
                OletxTransactionManager.ProxyException( comException ); 
                throw; 
            }
 
            if ( DiagnosticTrace.Verbose )
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetDtcTransaction" 
                    );
            } 
            return transactionNative; 
        }
 
        // This is here for the "DTC" in the name.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
        public static Transaction GetTransactionFromDtcTransaction(
            IDtcTransaction transactionNative 
            )
        { 
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); 

            bool tooLate = false; 
            ITransactionShim transactionShim = null;
            Guid txIdentifier = Guid.Empty;
            OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
            OutcomeEnlistment outcomeEnlistment = null; 
            RealOletxTransaction realTx = null;
            OletxTransaction oleTx = null; 
 
            if ( null == transactionNative )
            { 
                throw new ArgumentNullException( "transactionNative" );
            }

            Transaction transaction = null; 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromDtc" 
                    );
            }

            // Let's get the guid of the transaction from the proxy to see if we already 
            // have an object.
            ITransactionNativeInternal myTransactionNative = transactionNative as ITransactionNativeInternal; 
            if ( null == myTransactionNative ) 
            {
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "transactionNative" ); 
            }

            OletxXactTransInfo xactInfo;
            try 
            {
                myTransactionNative.GetTransactionInfo( out xactInfo ); 
            } 
            catch ( COMException ex )
            { 
                if ( Oletx.NativeMethods.XACT_E_NOTRANSACTION != ex.ErrorCode )
                {
                    throw;
                } 

                // If we get here, the transaction has appraently already been committed or aborted.  Allow creation of the 
                // OletxTransaction, but it will be marked with a status of InDoubt and attempts to get its Identifier 
                // property will result in a TransactionException.
                tooLate = true; 
                xactInfo.uow = Guid.Empty;

            }
 
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;
            if ( ! tooLate ) 
            { 
                // First check to see if there is a promoted LTM transaction with the same ID.  If there
                // is, just return that. 
                transaction = TransactionManager.FindPromotedTransaction( xactInfo.uow );
                if ( null != transaction )
                {
                    if ( DiagnosticTrace.Verbose ) 
                    {
                        MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                            "TransactionInterop.GetTransactionFromDtcTransaction" 
                            );
                    } 
                    return transaction;
                }

                // We need to create a new RealOletxTransaction... 
                oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 );
                try 
                { 
                    outcomeEnlistment = new OutcomeEnlistment();
                    IntPtr outcomeEnlistmentHandle = IntPtr.Zero; 
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try
                    {
                        outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); 
                        oletxTm.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim(
                            transactionNative, 
                            outcomeEnlistmentHandle, 
                            out txIdentifier,
                            out oletxIsoLevel, 
                            out transactionShim );
                    }
                    finally
                    { 
                        if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero )
                        { 
                            HandleTable.FreeHandle( outcomeEnlistmentHandle ); 
                        }
                    } 
                }
                catch ( COMException comException )
                {
                    OletxTransactionManager.ProxyException( comException ); 
                    throw;
                } 
                finally 
                {
                    oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); 
                }

                // We need to create a new RealOletxTransaction.
                realTx = new RealOletxTransaction( 
                    oletxTm,
                    transactionShim, 
                    outcomeEnlistment, 
                    txIdentifier,
                    oletxIsoLevel, 
                    false );

                oleTx = new OletxTransaction( realTx );
 
                // If a transaction is found then FindOrCreate will Dispose the oletx
                // created. 
                transaction = TransactionManager.FindOrCreatePromotedTransaction( xactInfo.uow, oleTx ); 
            }
            else 
            {
                // It was too late to do a clone of the provided ITransactionNative, so we are just going to
                // create a RealOletxTransaction without a transaction shim or outcome enlistment.
                realTx = new RealOletxTransaction( 
                    oletxTm,
                    null, 
                    null, 
                    txIdentifier,
                    OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE, 
                    false );

                oleTx = new OletxTransaction( realTx );
                transaction = new Transaction( oleTx ); 
                TransactionManager.FireDistributedTransactionStarted( transaction );
                oleTx.savedLtmPromotedTransaction = transaction; 
 
                InternalTransaction.DistributedTransactionOutcome(transaction.internalTransaction, TransactionStatus.InDoubt);
            } 


            if ( DiagnosticTrace.Verbose )
            { 
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromDtc" 
                    ); 
            }
            return transaction; 
        }

        public static byte[] GetWhereabouts(
            ) 
        {
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); 
 
            byte[] returnValue = null;
 
            if ( DiagnosticTrace.Verbose )
            {
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetWhereabouts" 
                    );
            } 
 
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;
            if ( null == oletxTm ) 
            {
                throw new ArgumentException( SR.GetString( SR.ArgumentWrongType ), "transactionManager" );
            }
 
            oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 );
            try 
            { 
                returnValue = oletxTm.DtcTransactionManager.Whereabouts;
            } 
            finally
            {
                oletxTm.dtcTransactionManagerLock.ReleaseReaderLock();
            } 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetWhereabouts" 
                    );
            }
            return returnValue;
 
        }
    } 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

using System; 
using System.Configuration; 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; 
using System.Security.Permissions;
using System.Transactions.Oletx;
using System.Transactions.Configuration;
using System.Transactions.Diagnostics; 

 
namespace System.Transactions 
{
    // This is here for the "DTC" in the name. 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
    [
    ComImport,
    Guid("0fb15084-af41-11ce-bd2b-204c4f4f5020"), 
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
    ] 
    public interface IDtcTransaction 
    {
        void Commit(int retaining, 
            [MarshalAs(UnmanagedType.I4)] int commitType,
            int reserved);

        void Abort(IntPtr reason, 
            int retaining,
            int async); 
 
        void GetTransactionInfo( IntPtr transactionInformation);
    } 


    [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")]
    public static class TransactionInterop 
    {
        internal static OletxTransaction ConvertToOletxTransaction( 
            Transaction transaction 
            )
        { 
            if ( null == transaction )
            {
                throw new ArgumentNullException( "transaction" );
            } 

            if ( transaction.Disposed ) 
            { 
                throw new ObjectDisposedException( "Transaction" );
            } 

            if ( transaction.complete )
            {
                throw TransactionException.CreateTransactionCompletedException( SR.GetString( SR.TraceSourceLtm ) ); 
            }
 
            OletxTransaction oletxTx = transaction.Promote(); 
            System.Diagnostics.Debug.Assert( oletxTx != null, "transaction.Promote returned null instead of throwing." );
 
            return oletxTx;
        }

 
        // This is here for the DangerousGetHandle call.  We need to do it.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] 
        public static byte[] GetExportCookie( 
            Transaction transaction,
            byte[] whereabouts 
            )
        {
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();
 
            byte[] cookie = null;
 
            if ( null == transaction ) 
            {
                throw new ArgumentNullException( "transaction" ); 
            }

            if ( null == whereabouts )
            { 
                throw new ArgumentNullException( "whereabouts" );
            } 
 
            if ( DiagnosticTrace.Verbose )
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetExportCookie"
                    );
            } 

            // Copy the whereabouts so that it cannot be modified later. 
            byte[] whereaboutsCopy = new byte[whereabouts.Length]; 
            Array.Copy(whereabouts, whereaboutsCopy, whereabouts.Length);
            whereabouts = whereaboutsCopy; 

            int cookieIndex = 0;
            UInt32 cookieSize = 0;
            CoTaskMemHandle cookieBuffer = null; 

            // First, make sure we are working with an OletxTransaction. 
            OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); 

            try 
            {
                oletxTx.realOletxTransaction.TransactionShim.Export(
                    Convert.ToUInt32(whereabouts.Length),
                    whereabouts, 
                    out cookieIndex,
                    out cookieSize, 
                    out cookieBuffer ); 

                // allocate and fill in the cookie 
                cookie = new byte[cookieSize];
                Marshal.Copy( cookieBuffer.DangerousGetHandle(), cookie, 0, Convert.ToInt32(cookieSize) );
            }
            catch (COMException comException) 
            {
                OletxTransactionManager.ProxyException( comException ); 
 
                // We are unsure of what the exception may mean.  It is possible that
                // we could get E_FAIL when trying to contact a transaction manager that is 
                // being blocked by a fire wall.  On the other hand we may get a COMException
                // based on bad data.  The more common situation is that the data is fine
                // (since it is generated by Microsoft code) and the problem is with
                // communication.  So in this case we default for unknown exceptions to 
                // assume that the problem is with communication.
                throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException ); 
            } 
            finally
            { 
                if ( null != cookieBuffer )
                {
                    cookieBuffer.Close();
                } 
            }
 
            if ( DiagnosticTrace.Verbose ) 
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                    "TransactionInterop.GetExportCookie"
                    );
            }
 
            return cookie;
        } 
 
        public static Transaction GetTransactionFromExportCookie(
            byte[] cookie 
            )
        {
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();
 
            if ( null == cookie )
            { 
                throw new ArgumentNullException( "cookie" ); 
            }
 
            if ( cookie.Length < 32 )
            {
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "cookie" );
            } 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromExportCookie" 
                    );
            }

            byte[] cookieCopy = new byte [cookie.Length]; 
            Array.Copy(cookie, cookieCopy, cookie.Length);
            cookie = cookieCopy; 
 
            Transaction transaction = null;
            ITransactionShim transactionShim = null; 
            Guid txIdentifier = Guid.Empty;
            OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
            OutcomeEnlistment outcomeEnlistment = null;
            OletxTransaction oleTx = null; 

            // Extract the transaction guid from the propagation token to see if we already have a 
            // transaction object for the transaction. 
            byte[] guidByteArray = new byte[16];
            for (int i = 0; i < guidByteArray.Length; i++ ) 
            {
                // In a cookie, the transaction guid is preceeded by a signature guid.
                guidByteArray[i] = cookie[i+16];
            } 

            Guid txId = new Guid( guidByteArray ); 
 
            // First check to see if there is a promoted LTM transaction with the same ID.  If there
            // is, just return that. 
            transaction = TransactionManager.FindPromotedTransaction( txId );
            if ( null != transaction )
            {
                if ( DiagnosticTrace.Verbose ) 
                {
                    MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                        "TransactionInterop.GetTransactionFromExportCookie" 
                        );
                } 
                return transaction;
            }

            // We need to create a new transaction 
            RealOletxTransaction realTx = null;
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; 
 
            oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 );
            try 
            {
                outcomeEnlistment = new OutcomeEnlistment();
                IntPtr outcomeEnlistmentHandle = IntPtr.Zero;
                RuntimeHelpers.PrepareConstrainedRegions(); 
                try
                { 
                    outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); 
                    oletxTm.DtcTransactionManager.ProxyShimFactory.Import(
                        Convert.ToUInt32(cookie.Length), 
                        cookie,
                        outcomeEnlistmentHandle,
                        out txIdentifier,
                        out oletxIsoLevel, 
                        out transactionShim );
                } 
                finally 
                {
                    if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) 
                    {
                        HandleTable.FreeHandle( outcomeEnlistmentHandle );
                    }
                } 
            }
            catch ( COMException comException ) 
            { 
                OletxTransactionManager.ProxyException( comException );
 
                // We are unsure of what the exception may mean.  It is possible that
                // we could get E_FAIL when trying to contact a transaction manager that is
                // being blocked by a fire wall.  On the other hand we may get a COMException
                // based on bad data.  The more common situation is that the data is fine 
                // (since it is generated by Microsoft code) and the problem is with
                // communication.  So in this case we default for unknown exceptions to 
                // assume that the problem is with communication. 
                throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException );
            } 
            finally
            {
                oletxTm.dtcTransactionManagerLock.ReleaseReaderLock();
            } 

            // We need to create a new RealOletxTransaction. 
            realTx = new RealOletxTransaction( 
                oletxTm,
                transactionShim, 
                outcomeEnlistment,
                txIdentifier,
                oletxIsoLevel,
                false ); 

            // Now create the associated OletxTransaction. 
            oleTx = new OletxTransaction( realTx ); 

            // If a transaction is found then FindOrCreate will Dispose the oletx 
            // created.
            transaction = TransactionManager.FindOrCreatePromotedTransaction( txId, oleTx );

            if ( DiagnosticTrace.Verbose ) 
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                    "TransactionInterop.GetTransactionFromExportCookie" 
                    );
            } 

            return transaction;
        }
 

        public static byte[] GetTransmitterPropagationToken( 
            Transaction transaction 
            )
        { 
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();

            if ( null == transaction )
            { 
                throw new ArgumentNullException( "transaction" );
            } 
 
            if ( DiagnosticTrace.Verbose )
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransmitterPropagationToken"
                    );
            } 

            // First, make sure we are working with an OletxTransaction. 
            OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); 

            byte [] token = GetTransmitterPropagationToken( oletxTx ); 

            if ( DiagnosticTrace.Verbose )
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                    "TransactionInterop.GetTransmitterPropagationToken"
                    ); 
            } 

            return token; 
        }


        // This is here for the DangerousGetHandle call.  We need to do it. 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
        internal static byte[] GetTransmitterPropagationToken( 
            OletxTransaction oletxTx 
            )
        { 
            byte[] propagationToken = null;
            CoTaskMemHandle propagationTokenBuffer = null;
            UInt32 tokenSize = 0;
 
            try
            { 
                oletxTx.realOletxTransaction.TransactionShim.GetPropagationToken( 
                    out tokenSize,
                    out propagationTokenBuffer ); 
                propagationToken = new byte[ tokenSize ];
                Marshal.Copy( propagationTokenBuffer.DangerousGetHandle(), propagationToken, 0, Convert.ToInt32(tokenSize) );
            }
            catch (COMException comException) 
            {
                OletxTransactionManager.ProxyException( comException ); 
                throw; 
            }
            finally 
            {
                if ( null != propagationTokenBuffer )
                {
                    propagationTokenBuffer.Close(); 
                }
            } 
 
            return propagationToken;
        } 



        public static Transaction GetTransactionFromTransmitterPropagationToken( 
            byte[] propagationToken
            ) 
        { 
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();
 
            Transaction returnValue = null;

            if ( null == propagationToken )
            { 
                throw new ArgumentNullException( "propagationToken" );
            } 
 
            if ( propagationToken.Length < 24 )
            { 
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "propagationToken" );
            }

            if ( DiagnosticTrace.Verbose ) 
            {
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                    "TransactionInterop.GetTransactionFromTransmitterPropagationToken" 
                    );
            } 

            // Extract the transaction guid from the propagation token to see if we already have a
            // transaction object for the transaction.
            byte[] guidByteArray = new byte[16]; 
            for (int i = 0; i < guidByteArray.Length; i++ )
            { 
                // In a propagation token, the transaction guid is preceeded by two version DWORDs. 
                guidByteArray[i] = propagationToken[i+8];
            } 

            Guid txId = new Guid( guidByteArray );

            // First check to see if there is a promoted LTM transaction with the same ID.  If there 
            // is, just return that.
            Transaction tx = TransactionManager.FindPromotedTransaction( txId ); 
            if ( null != tx ) 
            {
                if ( DiagnosticTrace.Verbose ) 
                {
                    MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                        "TransactionInterop.GetTransactionFromTransmitterPropagationToken"
                        ); 
                }
                return tx; 
            } 

            OletxTransaction oleTx = TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken( propagationToken ); 

            // If a transaction is found then FindOrCreate will Dispose the oletx
            // created.
            returnValue = TransactionManager.FindOrCreatePromotedTransaction( txId, oleTx ); 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromTransmitterPropagationToken" 
                    );
            }
            return returnValue;
        } 

 
 
        internal static OletxTransaction GetOletxTransactionFromTransmitterPropigationToken(
            byte[] propagationToken 
            )
        {
            Guid identifier;
            OletxTransactionIsolationLevel oletxIsoLevel; 
            OutcomeEnlistment outcomeEnlistment;
            ITransactionShim transactionShim = null; 
 
            if ( null == propagationToken )
            { 
                throw new ArgumentNullException( "propagationToken" );
            }

            if ( propagationToken.Length < 24 ) 
            {
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "propagationToken" ); 
            } 

            byte [] propagationTokenCopy = new byte [propagationToken.Length]; 
            Array.Copy(propagationToken, propagationTokenCopy, propagationToken.Length);
            propagationToken = propagationTokenCopy;

            // First we need to create an OletxTransactionManager from Config. 
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;
 
            oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); 
            try
            { 
                outcomeEnlistment = new OutcomeEnlistment();
                IntPtr outcomeEnlistmentHandle = IntPtr.Zero;
                RuntimeHelpers.PrepareConstrainedRegions();
                try 
                {
                    outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); 
                    oletxTm.DtcTransactionManager.ProxyShimFactory.ReceiveTransaction( 
                        Convert.ToUInt32(propagationToken.Length),
                        propagationToken, 
                        outcomeEnlistmentHandle,
                        out identifier,
                        out oletxIsoLevel,
                        out transactionShim 
                        );
                } 
                finally 
                {
                    if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) 
                    {
                        HandleTable.FreeHandle( outcomeEnlistmentHandle );
                    }
                } 
            }
            catch ( COMException comException ) 
            { 
                OletxTransactionManager.ProxyException( comException );
 
                // We are unsure of what the exception may mean.  It is possible that
                // we could get E_FAIL when trying to contact a transaction manager that is
                // being blocked by a fire wall.  On the other hand we may get a COMException
                // based on bad data.  The more common situation is that the data is fine 
                // (since it is generated by Microsoft code) and the problem is with
                // communication.  So in this case we default for unknown exceptions to 
                // assume that the problem is with communication. 
                throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException );
            } 
            finally
            {
                oletxTm.dtcTransactionManagerLock.ReleaseReaderLock();
            } 

            RealOletxTransaction realTx = null; 
 
            realTx = new RealOletxTransaction(
                oletxTm, 
                transactionShim,
                outcomeEnlistment,
                identifier,
                oletxIsoLevel, 
                false );
 
            return new OletxTransaction( realTx ); 
        }
 

        // This is here for the "Dtc" in the name.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
        public static IDtcTransaction GetDtcTransaction( 
            Transaction transaction
            ) 
        { 
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform();
 
            if ( null == transaction )
            {
                throw new ArgumentNullException( "transaction" );
            } 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetDtcTransaction" 
                    );
            }

            IDtcTransaction transactionNative = null; 

            // First, make sure we are working with an OletxTransaction. 
            OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); 

            try 
            {
                oletxTx.realOletxTransaction.TransactionShim.GetITransactionNative( out transactionNative );
            }
            catch( COMException comException ) 
            {
                OletxTransactionManager.ProxyException( comException ); 
                throw; 
            }
 
            if ( DiagnosticTrace.Verbose )
            {
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetDtcTransaction" 
                    );
            } 
            return transactionNative; 
        }
 
        // This is here for the "DTC" in the name.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
        public static Transaction GetTransactionFromDtcTransaction(
            IDtcTransaction transactionNative 
            )
        { 
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); 

            bool tooLate = false; 
            ITransactionShim transactionShim = null;
            Guid txIdentifier = Guid.Empty;
            OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
            OutcomeEnlistment outcomeEnlistment = null; 
            RealOletxTransaction realTx = null;
            OletxTransaction oleTx = null; 
 
            if ( null == transactionNative )
            { 
                throw new ArgumentNullException( "transactionNative" );
            }

            Transaction transaction = null; 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromDtc" 
                    );
            }

            // Let's get the guid of the transaction from the proxy to see if we already 
            // have an object.
            ITransactionNativeInternal myTransactionNative = transactionNative as ITransactionNativeInternal; 
            if ( null == myTransactionNative ) 
            {
                throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "transactionNative" ); 
            }

            OletxXactTransInfo xactInfo;
            try 
            {
                myTransactionNative.GetTransactionInfo( out xactInfo ); 
            } 
            catch ( COMException ex )
            { 
                if ( Oletx.NativeMethods.XACT_E_NOTRANSACTION != ex.ErrorCode )
                {
                    throw;
                } 

                // If we get here, the transaction has appraently already been committed or aborted.  Allow creation of the 
                // OletxTransaction, but it will be marked with a status of InDoubt and attempts to get its Identifier 
                // property will result in a TransactionException.
                tooLate = true; 
                xactInfo.uow = Guid.Empty;

            }
 
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;
            if ( ! tooLate ) 
            { 
                // First check to see if there is a promoted LTM transaction with the same ID.  If there
                // is, just return that. 
                transaction = TransactionManager.FindPromotedTransaction( xactInfo.uow );
                if ( null != transaction )
                {
                    if ( DiagnosticTrace.Verbose ) 
                    {
                        MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), 
                            "TransactionInterop.GetTransactionFromDtcTransaction" 
                            );
                    } 
                    return transaction;
                }

                // We need to create a new RealOletxTransaction... 
                oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 );
                try 
                { 
                    outcomeEnlistment = new OutcomeEnlistment();
                    IntPtr outcomeEnlistmentHandle = IntPtr.Zero; 
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try
                    {
                        outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); 
                        oletxTm.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim(
                            transactionNative, 
                            outcomeEnlistmentHandle, 
                            out txIdentifier,
                            out oletxIsoLevel, 
                            out transactionShim );
                    }
                    finally
                    { 
                        if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero )
                        { 
                            HandleTable.FreeHandle( outcomeEnlistmentHandle ); 
                        }
                    } 
                }
                catch ( COMException comException )
                {
                    OletxTransactionManager.ProxyException( comException ); 
                    throw;
                } 
                finally 
                {
                    oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); 
                }

                // We need to create a new RealOletxTransaction.
                realTx = new RealOletxTransaction( 
                    oletxTm,
                    transactionShim, 
                    outcomeEnlistment, 
                    txIdentifier,
                    oletxIsoLevel, 
                    false );

                oleTx = new OletxTransaction( realTx );
 
                // If a transaction is found then FindOrCreate will Dispose the oletx
                // created. 
                transaction = TransactionManager.FindOrCreatePromotedTransaction( xactInfo.uow, oleTx ); 
            }
            else 
            {
                // It was too late to do a clone of the provided ITransactionNative, so we are just going to
                // create a RealOletxTransaction without a transaction shim or outcome enlistment.
                realTx = new RealOletxTransaction( 
                    oletxTm,
                    null, 
                    null, 
                    txIdentifier,
                    OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE, 
                    false );

                oleTx = new OletxTransaction( realTx );
                transaction = new Transaction( oleTx ); 
                TransactionManager.FireDistributedTransactionStarted( transaction );
                oleTx.savedLtmPromotedTransaction = transaction; 
 
                InternalTransaction.DistributedTransactionOutcome(transaction.internalTransaction, TransactionStatus.InDoubt);
            } 


            if ( DiagnosticTrace.Verbose )
            { 
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetTransactionFromDtc" 
                    ); 
            }
            return transaction; 
        }

        public static byte[] GetWhereabouts(
            ) 
        {
            if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); 
 
            byte[] returnValue = null;
 
            if ( DiagnosticTrace.Verbose )
            {
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetWhereabouts" 
                    );
            } 
 
            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;
            if ( null == oletxTm ) 
            {
                throw new ArgumentException( SR.GetString( SR.ArgumentWrongType ), "transactionManager" );
            }
 
            oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 );
            try 
            { 
                returnValue = oletxTm.DtcTransactionManager.Whereabouts;
            } 
            finally
            {
                oletxTm.dtcTransactionManagerLock.ReleaseReaderLock();
            } 

            if ( DiagnosticTrace.Verbose ) 
            { 
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ),
                    "TransactionInterop.GetWhereabouts" 
                    );
            }
            return returnValue;
 
        }
    } 
} 


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