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); }
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)); }
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); }
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); }
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); }
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); }
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); }
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)); }
internal static byte[] GetTransmitterPropagationToken(OletxTransaction oletxTx) { byte[]? propagationToken = null; try { propagationToken = oletxTx.RealOletxTransaction.TransactionShim.GetPropagationToken(); } catch (COMException comException) { OletxTransactionManager.ProxyException(comException); throw; } return(propagationToken); }
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); } }
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); }
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; }
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 ) { 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); }
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); }
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) { 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); }
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); }