public static byte[] GetWhereabouts()
        {
            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.${nameof(GetWhereabouts)}");
            }

            OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager;

            if (oletxTm == null)
            {
                throw new ArgumentException(SR.InvalidArgument, "transactionManager");
            }

            byte[]? returnValue;

            oletxTm.DtcTransactionManagerLock.AcquireReaderLock(-1);
            try
            {
                returnValue = oletxTm.DtcTransactionManager.Whereabouts;
            }
            finally
            {
                oletxTm.DtcTransactionManagerLock.ReleaseReaderLock();
            }

            if (etwLog.IsEnabled())
            {
                etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.${nameof(GetWhereabouts)}");
            }

            return(returnValue);
        }
Beispiel #2
0
        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 IDtcTransaction GetDtcTransaction(Transaction transaction)
        {
            ArgumentNullException.ThrowIfNull(transaction);

            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetDtcTransaction)}");
            }

            IDtcTransaction?transactionNative;

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

            try
            {
                oletxTx.RealOletxTransaction.TransactionShim.GetITransactionNative(out transactionNative);
            }
            catch (COMException comException)
            {
                OletxTransactionManager.ProxyException(comException);
                throw;
            }

            if (etwLog.IsEnabled())
            {
                etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetDtcTransaction)}");
            }

            return(transactionNative);
        }
    // This is called by the internal RM when it gets a TM Down notification.  This routine will
    // tell the enlistments about the TMDown from the internal RM.  The enlistments will then
    // decide what to do, based on their state.  This is mainly to work around COMPlus bug 36760/36758,
    // where Phase0 enlistments get Phase0Request( abortHint = false ) when the TM goes down.  We want
    // to try to avoid telling the application to prepare when we know the transaction will abort.
    // We can't do this out of the normal TMDown notification to the RM because it is too late.  The
    // Phase0Request gets sent before the TMDown notification.
    internal void TMDownFromInternalRM(OletxTransactionManager oletxTM)
    {
        Hashtable             localEnlistmentHashtable;
        IDictionaryEnumerator enlistEnum;
        OletxEnlistment?      enlistment;

        // If the internal RM got a TMDown, we will shortly, so null out our ResourceManagerShim now.
        ResourceManagerShim = null;

        // Make our own copy of the hashtable of enlistments.
        lock (EnlistmentHashtable.SyncRoot)
        {
            localEnlistmentHashtable = (Hashtable)EnlistmentHashtable.Clone();
        }

        // Tell all of our enlistments that the TM went down.  The proxy only
        // tells enlistments that are in the Prepared state, but we want our Phase0
        // enlistments to know so they can avoid sending Prepare when they get a
        // Phase0Request - COMPlus bug 36760/36758.
        enlistEnum = localEnlistmentHashtable.GetEnumerator();
        while (enlistEnum.MoveNext())
        {
            enlistment = enlistEnum.Value as OletxEnlistment;
            enlistment?.TMDownFromInternalRM(oletxTM);
        }
    }
        internal static OletxTransaction GetOletxTransactionFromTransmitterPropagationToken(byte[] propagationToken)
        {
            ArgumentNullException.ThrowIfNull(propagationToken);

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

            Guid identifier;
            OletxTransactionIsolationLevel oletxIsoLevel;
            OutcomeEnlistment outcomeEnlistment;
            TransactionShim?  transactionShim = null;

            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();
                oletxTm.DtcTransactionManager.ProxyShimFactory.ReceiveTransaction(
                    propagationToken,
                    outcomeEnlistment,
                    out identifier,
                    out oletxIsoLevel,
                    out transactionShim);
            }
            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.TraceSourceOletx, comException);
            }
            finally
            {
                oletxTm.DtcTransactionManagerLock.ReleaseReaderLock();
            }

            var realTx = new RealOletxTransaction(
                oletxTm,
                transactionShim,
                outcomeEnlistment,
                identifier,
                oletxIsoLevel,
                false);

            return(new OletxTransaction(realTx));
        }
Beispiel #6
0
        public static byte[] GetWhereabouts()
        {
            if (!TransactionManager._platformValidated)
            {
                TransactionManager.ValidatePlatform();
            }
            byte[] whereabouts = null;
            if (DiagnosticTrace.Verbose)
            {
                MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetWhereabouts");
            }
            OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager;

            if (distributedTransactionManager == null)
            {
                throw new ArgumentException(System.Transactions.SR.GetString("ArgumentWrongType"), "transactionManager");
            }
            distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1);
            try
            {
                whereabouts = distributedTransactionManager.DtcTransactionManager.Whereabouts;
            }
            finally
            {
                distributedTransactionManager.dtcTransactionManagerLock.ReleaseReaderLock();
            }
            if (DiagnosticTrace.Verbose)
            {
                MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetWhereabouts");
            }
            return(whereabouts);
        }
Beispiel #7
0
        internal static byte[] GetTransmitterPropagationToken(OletxTransaction oletxTx)
        {
            CoTaskMemHandle propgationToken = null;

            byte[] destination         = null;
            uint   propagationTokeSize = 0;

            try
            {
                oletxTx.realOletxTransaction.TransactionShim.GetPropagationToken(out propagationTokeSize, out propgationToken);
                destination = new byte[propagationTokeSize];
                Marshal.Copy(propgationToken.DangerousGetHandle(), destination, 0, Convert.ToInt32(propagationTokeSize));
            }
            catch (COMException exception)
            {
                OletxTransactionManager.ProxyException(exception);
                throw;
            }
            finally
            {
                if (propgationToken != null)
                {
                    propgationToken.Close();
                }
            }
            return(destination);
        }
Beispiel #8
0
        public static IDtcTransaction GetDtcTransaction(Transaction transaction)
        {
            if (!TransactionManager._platformValidated)
            {
                TransactionManager.ValidatePlatform();
            }
            if (null == transaction)
            {
                throw new ArgumentNullException("transaction");
            }
            if (DiagnosticTrace.Verbose)
            {
                MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetDtcTransaction");
            }
            IDtcTransaction  transactionNative = null;
            OletxTransaction transaction2      = ConvertToOletxTransaction(transaction);

            try
            {
                transaction2.realOletxTransaction.TransactionShim.GetITransactionNative(out transactionNative);
            }
            catch (COMException exception)
            {
                OletxTransactionManager.ProxyException(exception);
                throw;
            }
            if (DiagnosticTrace.Verbose)
            {
                MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetDtcTransaction");
            }
            return(transactionNative);
        }
        private static OletxTransactionManager CheckTransactionManager(string nodeName)
        {
            OletxTransactionManager distributedTransactionManager = DistributedTransactionManager;

            if (((distributedTransactionManager.NodeName != null) || ((nodeName != null) && (nodeName.Length != 0))) && ((distributedTransactionManager.NodeName == null) || !distributedTransactionManager.NodeName.Equals(nodeName)))
            {
                throw new ArgumentException(System.Transactions.SR.GetString("InvalidRecoveryInformation"), "recoveryInformation");
            }
            return(distributedTransactionManager);
        }
Beispiel #10
0
        private static OletxTransactionManager CheckTransactionManager(string?nodeName)
        {
            OletxTransactionManager tm = DistributedTransactionManager;

            if (!((tm.NodeName == null && (nodeName == null || nodeName.Length == 0)) ||
                  (tm.NodeName != null && tm.NodeName.Equals(nodeName))))
            {
                throw new ArgumentException(SR.InvalidRecoveryInformation, "recoveryInformation");
            }
            return(tm);
        }
        public static Transaction GetTransactionFromExportCookie(byte[] cookie)
        {
            ArgumentNullException.ThrowIfNull(cookie);

            if (cookie.Length < 32)
            {
                throw new ArgumentException(SR.InvalidArgument, nameof(cookie));
            }

            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetTransactionFromExportCookie");
            }

            var cookieCopy = new byte[cookie.Length];

            Buffer.BlockCopy(cookie, 0, cookieCopy, 0, cookie.Length);
            cookie = cookieCopy;

            // Extract the transaction guid from the propagation token to see if we already have a
            // transaction object for the transaction.
            // In a cookie, the transaction guid is preceded by a signature guid.
            var txId = new Guid(cookie.AsSpan(16, 16));

            // First check to see if there is a promoted LTM transaction with the same ID.  If there
            // is, just return that.
            Transaction?transaction = TransactionManager.FindPromotedTransaction(txId);

            if (transaction != null)
            {
                if (etwLog.IsEnabled())
                {
                    etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetTransactionFromExportCookie");
                }

                return(transaction);
            }

            // Find or create the promoted transaction.
            OletxTransaction dTx = OletxTransactionManager.GetTransactionFromExportCookie(cookieCopy, txId);

            transaction = TransactionManager.FindOrCreatePromotedTransaction(txId, dTx);

            if (etwLog.IsEnabled())
            {
                etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetTransactionFromExportCookie");
            }

            return(transaction);
        }
Beispiel #12
0
        public static byte[] GetExportCookie(Transaction transaction, byte[] whereabouts)
        {
            if (!TransactionManager._platformValidated)
            {
                TransactionManager.ValidatePlatform();
            }
            byte[] destination = null;
            if (null == transaction)
            {
                throw new ArgumentNullException("transaction");
            }
            if (whereabouts == null)
            {
                throw new ArgumentNullException("whereabouts");
            }
            if (DiagnosticTrace.Verbose)
            {
                MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetExportCookie");
            }
            byte[] destinationArray = new byte[whereabouts.Length];
            Array.Copy(whereabouts, destinationArray, whereabouts.Length);
            whereabouts = destinationArray;
            int              cookieIndex  = 0;
            uint             cookieSize   = 0;
            CoTaskMemHandle  cookieBuffer = null;
            OletxTransaction transaction2 = ConvertToOletxTransaction(transaction);

            try
            {
                transaction2.realOletxTransaction.TransactionShim.Export(Convert.ToUInt32(whereabouts.Length), whereabouts, out cookieIndex, out cookieSize, out cookieBuffer);
                destination = new byte[cookieSize];
                Marshal.Copy(cookieBuffer.DangerousGetHandle(), destination, 0, Convert.ToInt32(cookieSize));
            }
            catch (COMException exception)
            {
                OletxTransactionManager.ProxyException(exception);
                throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), exception);
            }
            finally
            {
                if (cookieBuffer != null)
                {
                    cookieBuffer.Close();
                }
            }
            if (DiagnosticTrace.Verbose)
            {
                MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetExportCookie");
            }
            return(destination);
        }
Beispiel #13
0
        internal static OletxTransaction GetOletxTransactionFromTransmitterPropigationToken(byte[] propagationToken)
        {
            OutcomeEnlistment enlistment;
            ITransactionShim  transactionShim = null;
            OletxTransactionIsolationLevel level;
            Guid guid;

            if (propagationToken == null)
            {
                throw new ArgumentNullException("propagationToken");
            }
            if (propagationToken.Length < 0x18)
            {
                throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "propagationToken");
            }
            byte[] destinationArray = new byte[propagationToken.Length];
            Array.Copy(propagationToken, destinationArray, propagationToken.Length);
            propagationToken = destinationArray;
            OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager;

            distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1);
            try
            {
                enlistment = new OutcomeEnlistment();
                IntPtr zero = IntPtr.Zero;
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    zero = HandleTable.AllocHandle(enlistment);
                    distributedTransactionManager.DtcTransactionManager.ProxyShimFactory.ReceiveTransaction(Convert.ToUInt32(propagationToken.Length), propagationToken, zero, out guid, out level, out transactionShim);
                }
                finally
                {
                    if ((transactionShim == null) && (zero != IntPtr.Zero))
                    {
                        HandleTable.FreeHandle(zero);
                    }
                }
            }
            catch (COMException exception)
            {
                OletxTransactionManager.ProxyException(exception);
                throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), exception);
            }
            finally
            {
                distributedTransactionManager.dtcTransactionManagerLock.ReleaseReaderLock();
            }
            return(new OletxTransaction(new RealOletxTransaction(distributedTransactionManager, transactionShim, enlistment, guid, level, false)));
        }
        internal static OletxTransaction GetOletxTransactionFromTransmitterPropagationToken(byte[] propagationToken)
        {
            ArgumentNullException.ThrowIfNull(propagationToken);

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

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

            return(OletxTransactionManager.GetOletxTransactionFromTransmitterPropagationToken(propagationTokenCopy));
        }
Beispiel #15
0
        internal static byte[] GetTransmitterPropagationToken(OletxTransaction oletxTx)
        {
            byte[]? propagationToken = null;

            try
            {
                propagationToken = oletxTx.RealOletxTransaction.TransactionShim.GetPropagationToken();
            }
            catch (COMException comException)
            {
                OletxTransactionManager.ProxyException(comException);
                throw;
            }

            return(propagationToken);
        }
Beispiel #16
0
        public static byte[] GetExportCookie(Transaction transaction, byte[] whereabouts)
        {
            ArgumentNullException.ThrowIfNull(transaction);
            ArgumentNullException.ThrowIfNull(whereabouts);

            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetExportCookie)}");
            }

            byte[] cookie;

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

            Buffer.BlockCopy(whereabouts, 0, whereaboutsCopy, 0, whereabouts.Length);

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

            try
            {
                oletxTx.RealOletxTransaction.TransactionShim.Export(whereabouts, out cookie);
            }
            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(null, comException);
            }

            if (etwLog.IsEnabled())
            {
                etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetExportCookie)}");
            }

            return(cookie);
        }
    internal OletxResourceManager(OletxTransactionManager transactionManager, Guid resourceManagerIdentifier)
    {
        Debug.Assert(transactionManager != null, "Argument is null");

        // This will get set later, after the resource manager is created with the proxy.
        resourceManagerShim       = null;
        OletxTransactionManager   = transactionManager;
        ResourceManagerIdentifier = resourceManagerIdentifier;

        EnlistmentHashtable = new Hashtable();
        ReenlistList        = new ArrayList();
        ReenlistPendingList = new ArrayList();

        ReenlistThreadTimer = null;
        reenlistThread      = null;
        RecoveryCompleteCalledByApplication = false;
    }
        public static byte[] GetWhereabouts()
        {
            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetWhereabouts");
            }

            byte[] returnValue = OletxTransactionManager.GetWhereabouts();

            if (etwLog.IsEnabled())
            {
                etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetWhereabouts");
            }
            return(returnValue);
        }
    private void Initialize()
    {
        if (_whereabouts is not null)
        {
            return;
        }

        OletxInternalResourceManager internalRM = _oletxTm.InternalResourceManager;
        bool nodeNameMatches;

        try
        {
            _proxyShimFactory.ConnectToProxy(
                _nodeName,
                internalRM.Identifier,
                internalRM,
                out nodeNameMatches,
                out _whereabouts,
                out ResourceManagerShim resourceManagerShim);

            // If the node name does not match, throw.
            if (!nodeNameMatches)
            {
                throw new NotSupportedException(SR.ProxyCannotSupportMultipleNodeNames);
            }

            // Give the IResourceManagerShim to the internalRM and tell it to call ReenlistComplete.
            internalRM.ResourceManagerShim = resourceManagerShim;
            internalRM.CallReenlistComplete();
        }
        catch (COMException ex)
        {
            if (ex.ErrorCode == OletxHelper.XACT_E_NOTSUPPORTED)
            {
                throw new NotSupportedException(SR.CannotSupportNodeNameSpecification);
            }

            OletxTransactionManager.ProxyException(ex);

            // Unfortunately MSDTCPRX may return unknown error codes when attempting to connect to MSDTC
            // that error should be propagated back as a TransactionManagerCommunicationException.
            throw TransactionManagerCommunicationException.Create(SR.TransactionManagerCommunicationException, ex);
        }
    }
Beispiel #20
0
        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);
        }
        public static Transaction GetTransactionFromDtcTransaction(IDtcTransaction transactionNative)
        {
            ArgumentNullException.ThrowIfNull(transactionNative);

            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetTransactionFromDtcTransaction");
            }

            Transaction transaction = OletxTransactionManager.GetTransactionFromDtcTransaction(transactionNative);

            if (etwLog.IsEnabled())
            {
                etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, "TransactionInterop.GetTransactionFromDtcTransaction");
            }
            return(transaction);
        }
Beispiel #22
0
        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);
        }
 internal DtcTransactionManager(string?nodeName, OletxTransactionManager oletxTm)
 {
     _nodeName         = nodeName;
     _oletxTm          = oletxTm;
     _proxyShimFactory = OletxTransactionManager.ProxyShimFactory;
 }
Beispiel #24
0
        public static Transaction GetTransactionFromDtcTransaction(IDtcTransaction transactionNative)
        {
            ArgumentNullException.ThrowIfNull(transactionNative, nameof(transactionNative));

            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromDtcTransaction)}");
            }

            Transaction?    transaction     = null;
            bool            tooLate         = false;
            TransactionShim?transactionShim = null;
            Guid            txIdentifier    = Guid.Empty;
            OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
            OutcomeEnlistment?   outcomeEnlistment       = null;
            RealOletxTransaction?realTx = null;
            OletxTransaction?    oleTx  = null;

            // Let's get the guid of the transaction from the proxy to see if we already have an object.
            if (transactionNative is not ITransaction myTransactionNative)
            {
                throw new ArgumentException(SR.InvalidArgument, nameof(transactionNative));
            }

            OletxXactTransInfo xactInfo;

            try
            {
                myTransactionNative.GetTransactionInfo(out xactInfo);
            }
            catch (COMException ex) when(ex.ErrorCode == OletxHelper.XACT_E_NOTRANSACTION)
            {
                // 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 (transaction != null)
                {
                    if (etwLog.IsEnabled())
                    {
                        etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromDtcTransaction)}");
                    }

                    return(transaction);
                }

                // We need to create a new RealOletxTransaction...
                oletxTm.DtcTransactionManagerLock.AcquireReaderLock(-1);
                try
                {
                    outcomeEnlistment = new OutcomeEnlistment();
                    oletxTm.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim(
                        transactionNative,
                        outcomeEnlistment,
                        out txIdentifier,
                        out oletxIsoLevel,
                        out transactionShim);
                }
                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 (etwLog.IsEnabled())
            {
                etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromDtcTransaction)}");
            }

            return(transaction);
        }
Beispiel #25
0
        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);
        }
Beispiel #26
0
        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));
        }
        public static Enlistment Reenlist(Guid resourceManagerIdentifier, byte[] recoveryInformation, IEnlistmentNotification enlistmentNotification)
        {
            if (resourceManagerIdentifier == Guid.Empty)
            {
                throw new ArgumentException(System.Transactions.SR.GetString("BadResourceManagerId"), "resourceManagerIdentifier");
            }
            if (recoveryInformation == null)
            {
                throw new ArgumentNullException("recoveryInformation");
            }
            if (enlistmentNotification == null)
            {
                throw new ArgumentNullException("enlistmentNotification");
            }
            if (!_platformValidated)
            {
                ValidatePlatform();
            }
            if (DiagnosticTrace.Verbose)
            {
                MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), "TransactionManager.Reenlist");
            }
            if (DiagnosticTrace.Information)
            {
                ReenlistTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), resourceManagerIdentifier);
            }
            MemoryStream input    = new MemoryStream(recoveryInformation);
            string       nodeName = null;

            byte[] buffer = null;
            try
            {
                BinaryReader reader = new BinaryReader(input);
                if (reader.ReadInt32() != 1)
                {
                    if (DiagnosticTrace.Error)
                    {
                        TransactionExceptionTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), System.Transactions.SR.GetString("UnrecognizedRecoveryInformation"));
                    }
                    throw new ArgumentException(System.Transactions.SR.GetString("UnrecognizedRecoveryInformation"), "recoveryInformation");
                }
                nodeName = reader.ReadString();
                buffer   = reader.ReadBytes(recoveryInformation.Length - ((int)input.Position));
            }
            catch (EndOfStreamException exception2)
            {
                if (DiagnosticTrace.Error)
                {
                    TransactionExceptionTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), System.Transactions.SR.GetString("UnrecognizedRecoveryInformation"));
                }
                throw new ArgumentException(System.Transactions.SR.GetString("UnrecognizedRecoveryInformation"), "recoveryInformation", exception2);
            }
            catch (FormatException exception)
            {
                if (DiagnosticTrace.Error)
                {
                    TransactionExceptionTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), System.Transactions.SR.GetString("UnrecognizedRecoveryInformation"));
                }
                throw new ArgumentException(System.Transactions.SR.GetString("UnrecognizedRecoveryInformation"), "recoveryInformation", exception);
            }
            finally
            {
                input.Close();
            }
            OletxTransactionManager manager = CheckTransactionManager(nodeName);
            object     syncRoot             = new object();
            Enlistment enlistment           = new Enlistment(enlistmentNotification, syncRoot);

            EnlistmentState._EnlistmentStatePromoted.EnterState(enlistment.InternalEnlistment);
            enlistment.InternalEnlistment.PromotedEnlistment = manager.ReenlistTransaction(resourceManagerIdentifier, buffer, (RecoveringInternalEnlistment)enlistment.InternalEnlistment);
            if (DiagnosticTrace.Verbose)
            {
                MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceBase"), "TransactionManager.Reenlist");
            }
            return(enlistment);
        }
Beispiel #28
0
        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);
        }
Beispiel #29
0
        public static Transaction GetTransactionFromExportCookie(byte[] cookie)
        {
            ArgumentNullException.ThrowIfNull(cookie);

            if (cookie.Length < 32)
            {
                throw new ArgumentException(SR.InvalidArgument, nameof(cookie));
            }

            TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;

            if (etwLog.IsEnabled())
            {
                etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromExportCookie)}");
            }

            var cookieCopy = new byte[cookie.Length];

            Buffer.BlockCopy(cookie, 0, cookieCopy, 0, cookie.Length);
            cookie = cookieCopy;

            Transaction?    transaction;
            TransactionShim?transactionShim = null;
            Guid            txIdentifier    = Guid.Empty;
            OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
            OutcomeEnlistment?outcomeEnlistment;
            OletxTransaction? oleTx;

            // Extract the transaction guid from the propagation token to see if we already have a
            // transaction object for the transaction.
            // In a cookie, the transaction guid is preceded by a signature guid.
            var txId = new Guid(cookie.AsSpan(16, 16));

            // 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 (transaction != null)
            {
                if (etwLog.IsEnabled())
                {
                    etwLog.MethodExit(TraceSourceType.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();
                oletxTm.DtcTransactionManager.ProxyShimFactory.Import(cookie, outcomeEnlistment, out txIdentifier, out oletxIsoLevel, out transactionShim);
            }
            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.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 (etwLog.IsEnabled())
            {
                etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetTransactionFromExportCookie)}");
            }

            return(transaction);
        }
Beispiel #30
0
        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);
        }