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 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); }
public static Transaction GetTransactionFromDtcTransaction(IDtcTransaction transactionNative) { OletxXactTransInfo info; if (!TransactionManager._platformValidated) { TransactionManager.ValidatePlatform(); } bool flag = false; ITransactionShim transactionShim = null; Guid empty = Guid.Empty; OletxTransactionIsolationLevel isolationLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment target = null; RealOletxTransaction realOletxTransaction = null; OletxTransaction oletx = null; if (transactionNative == null) { throw new ArgumentNullException("transactionNative"); } Transaction transaction = null; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtc"); } ITransactionNativeInternal internal2 = transactionNative as ITransactionNativeInternal; if (internal2 == null) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "transactionNative"); } try { internal2.GetTransactionInfo(out info); } catch (COMException exception2) { if (System.Transactions.Oletx.NativeMethods.XACT_E_NOTRANSACTION != exception2.ErrorCode) { throw; } flag = true; info.uow = Guid.Empty; } OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager; if (!flag) { transaction = TransactionManager.FindPromotedTransaction(info.uow); if (null != transaction) { if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtcTransaction"); } return(transaction); } distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1); try { target = new OutcomeEnlistment(); IntPtr zero = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { zero = HandleTable.AllocHandle(target); distributedTransactionManager.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim(transactionNative, zero, out empty, out isolationLevel, out transactionShim); } finally { if ((transactionShim == null) && (zero != IntPtr.Zero)) { HandleTable.FreeHandle(zero); } } } catch (COMException exception) { OletxTransactionManager.ProxyException(exception); throw; } finally { distributedTransactionManager.dtcTransactionManagerLock.ReleaseReaderLock(); } realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, transactionShim, target, empty, isolationLevel, false); oletx = new OletxTransaction(realOletxTransaction); transaction = TransactionManager.FindOrCreatePromotedTransaction(info.uow, oletx); } else { realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, null, null, empty, OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE, false); oletx = new OletxTransaction(realOletxTransaction); transaction = new Transaction(oletx); TransactionManager.FireDistributedTransactionStarted(transaction); oletx.savedLtmPromotedTransaction = transaction; InternalTransaction.DistributedTransactionOutcome(transaction.internalTransaction, TransactionStatus.InDoubt); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromDtc"); } return(transaction); }