public TransactionScope( TransactionScopeOption scopeOption, TimeSpan scopeTimeout, TransactionScopeAsyncFlowOption asyncFlowOption ) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceBase, this); } ValidateScopeTimeout(nameof(scopeTimeout), scopeTimeout); TimeSpan txTimeout = TransactionManager.ValidateTimeout(scopeTimeout); ValidateAndSetAsyncFlowOption(asyncFlowOption); if (NeedToCreateTransaction(scopeOption)) { _committableTransaction = new CommittableTransaction(txTimeout); _expectedCurrent = _committableTransaction.Clone(); } if ((null != _expectedCurrent) && (null == _committableTransaction) && (TimeSpan.Zero != scopeTimeout)) { // BUGBUG: Scopes should not use individual timers _scopeTimer = new Timer( TimerCallback, this, scopeTimeout, TimeSpan.Zero); } if (null == _expectedCurrent) { if (etwLog.IsEnabled()) { etwLog.TransactionScopeCreated(TransactionTraceIdentifier.Empty, TransactionScopeResult.NoTransaction); } } else { TransactionScopeResult scopeResult; if (null == _committableTransaction) { scopeResult = TransactionScopeResult.UsingExistingCurrent; } else { scopeResult = TransactionScopeResult.CreatedTransaction; } if (etwLog.IsEnabled()) { etwLog.TransactionScopeCreated(_expectedCurrent.TransactionTraceId, scopeResult); } } PushScope(); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceBase, this); } }
public TransactionScope( TransactionScopeOption scopeOption, TransactionOptions transactionOptions, EnterpriseServicesInteropOption interopOption) { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log; if (etwLog.IsEnabled()) { etwLog.MethodEnter(TraceSourceType.TraceSourceBase, this); } ValidateScopeTimeout("transactionOptions.Timeout", transactionOptions.Timeout); TimeSpan scopeTimeout = transactionOptions.Timeout; transactionOptions.Timeout = TransactionManager.ValidateTimeout(transactionOptions.Timeout); TransactionManager.ValidateIsolationLevel(transactionOptions.IsolationLevel); ValidateInteropOption(interopOption); _interopModeSpecified = true; _interopOption = interopOption; if (NeedToCreateTransaction(scopeOption)) { _committableTransaction = new CommittableTransaction(transactionOptions); _expectedCurrent = _committableTransaction.Clone(); } else { if (null != _expectedCurrent) { // If the requested IsolationLevel is stronger than that of the specified transaction, throw. if ((IsolationLevel.Unspecified != transactionOptions.IsolationLevel) && (_expectedCurrent.IsolationLevel != transactionOptions.IsolationLevel)) { throw new ArgumentException(SR.TransactionScopeIsolationLevelDifferentFromTransaction, nameof(transactionOptions)); } } } if ((null != _expectedCurrent) && (null == _committableTransaction) && (TimeSpan.Zero != scopeTimeout)) { // BUGBUG: Scopes should use a shared timer _scopeTimer = new Timer( TimerCallback, this, scopeTimeout, TimeSpan.Zero); } if (null == _expectedCurrent) { if (etwLog.IsEnabled()) { etwLog.TransactionScopeCreated(TransactionTraceIdentifier.Empty, TransactionScopeResult.NoTransaction); } } else { TransactionScopeResult scopeResult; if (null == _committableTransaction) { scopeResult = TransactionScopeResult.UsingExistingCurrent; } else { scopeResult = TransactionScopeResult.CreatedTransaction; } if (etwLog.IsEnabled()) { etwLog.TransactionScopeCreated(_expectedCurrent.TransactionTraceId, scopeResult); } } PushScope(); if (etwLog.IsEnabled()) { etwLog.MethodExit(TraceSourceType.TraceSourceBase, this); } }
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); }
static public Enlistment Reenlist( Guid resourceManagerIdentifier, byte[] recoveryInformation, IEnlistmentNotification enlistmentNotification ) { if (resourceManagerIdentifier == Guid.Empty) { throw new ArgumentException(SR.GetString(SR.BadResourceManagerId), "resourceManagerIdentifier"); } if (null == recoveryInformation) { throw new ArgumentNullException("recoveryInformation"); } if (null == enlistmentNotification) { throw new ArgumentNullException("enlistmentNotification"); } if (!TransactionManager._platformValidated) { TransactionManager.ValidatePlatform(); } if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(SR.GetString(SR.TraceSourceBase), "TransactionManager.Reenlist" ); } if (DiagnosticTrace.Information) { ReenlistTraceRecord.Trace(SR.GetString(SR.TraceSourceBase), resourceManagerIdentifier ); } // Put the recovery information into a stream. MemoryStream stream = new MemoryStream(recoveryInformation); int recoveryInformationVersion = 0; string nodeName = null; byte[] resourceManagerRecoveryInformation = null; try { BinaryReader reader = new BinaryReader(stream); recoveryInformationVersion = reader.ReadInt32(); if (recoveryInformationVersion == TransactionManager.recoveryInformationVersion1) { nodeName = reader.ReadString(); resourceManagerRecoveryInformation = reader.ReadBytes(recoveryInformation.Length - checked ((int)stream.Position)); } else { if (DiagnosticTrace.Error) { TransactionExceptionTraceRecord.Trace(SR.GetString(SR.TraceSourceBase), SR.GetString(SR.UnrecognizedRecoveryInformation) ); } throw new ArgumentException(SR.GetString(SR.UnrecognizedRecoveryInformation), "recoveryInformation"); } } catch (System.IO.EndOfStreamException e) { if (DiagnosticTrace.Error) { TransactionExceptionTraceRecord.Trace(SR.GetString(SR.TraceSourceBase), SR.GetString(SR.UnrecognizedRecoveryInformation) ); } throw new ArgumentException(SR.GetString(SR.UnrecognizedRecoveryInformation), "recoveryInformation", e); } catch (System.FormatException e) { if (DiagnosticTrace.Error) { TransactionExceptionTraceRecord.Trace(SR.GetString(SR.TraceSourceBase), SR.GetString(SR.UnrecognizedRecoveryInformation) ); } throw new ArgumentException(SR.GetString(SR.UnrecognizedRecoveryInformation), "recoveryInformation", e); } finally { stream.Close(); } Oletx.OletxTransactionManager transactionManager = CheckTransactionManager(nodeName); // Now ask the Transaction Manager to reenlist. object syncRoot = new object(); Enlistment returnValue = new Enlistment(enlistmentNotification, syncRoot); EnlistmentState._EnlistmentStatePromoted.EnterState(returnValue.InternalEnlistment); returnValue.InternalEnlistment.PromotedEnlistment = transactionManager.ReenlistTransaction( resourceManagerIdentifier, resourceManagerRecoveryInformation, (RecoveringInternalEnlistment)returnValue.InternalEnlistment ); if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(SR.GetString(SR.TraceSourceBase), "TransactionManager.Reenlist" ); } return(returnValue); }
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 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); }
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 Transaction GetTransactionFromExportCookie(byte[] cookie) { if (!TransactionManager._platformValidated) { TransactionManager.ValidatePlatform(); } if (cookie == null) { throw new ArgumentNullException("cookie"); } if (cookie.Length < 0x20) { throw new ArgumentException(System.Transactions.SR.GetString("InvalidArgument"), "cookie"); } if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie"); } byte[] destinationArray = new byte[cookie.Length]; Array.Copy(cookie, destinationArray, cookie.Length); cookie = destinationArray; Transaction transaction = null; ITransactionShim transactionShim = null; Guid empty = Guid.Empty; OletxTransactionIsolationLevel isolationLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment target = null; OletxTransaction oletx = null; byte[] b = new byte[0x10]; for (int i = 0; i < b.Length; i++) { b[i] = cookie[i + 0x10]; } Guid transactionIdentifier = new Guid(b); transaction = TransactionManager.FindPromotedTransaction(transactionIdentifier); if (null != transaction) { if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie"); } return(transaction); } RealOletxTransaction realOletxTransaction = null; OletxTransactionManager distributedTransactionManager = TransactionManager.DistributedTransactionManager; distributedTransactionManager.dtcTransactionManagerLock.AcquireReaderLock(-1); try { target = new OutcomeEnlistment(); IntPtr zero = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { zero = HandleTable.AllocHandle(target); distributedTransactionManager.DtcTransactionManager.ProxyShimFactory.Import(Convert.ToUInt32(cookie.Length), cookie, zero, out empty, out isolationLevel, 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(); } realOletxTransaction = new RealOletxTransaction(distributedTransactionManager, transactionShim, target, empty, isolationLevel, false); oletx = new OletxTransaction(realOletxTransaction); transaction = TransactionManager.FindOrCreatePromotedTransaction(transactionIdentifier, oletx); if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "TransactionInterop.GetTransactionFromExportCookie"); } 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); }