Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / tx / System / Transactions / TransactionInterop.cs / 1305376 / TransactionInterop.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System; using System.Configuration; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Transactions.Oletx; using System.Transactions.Configuration; using System.Transactions.Diagnostics; namespace System.Transactions { // This is here for the "DTC" in the name. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] [ ComImport, Guid("0fb15084-af41-11ce-bd2b-204c4f4f5020"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown) ] public interface IDtcTransaction { void Commit(int retaining, [MarshalAs(UnmanagedType.I4)] int commitType, int reserved); void Abort(IntPtr reason, int retaining, int async); void GetTransactionInfo( IntPtr transactionInformation); } [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Name="FullTrust")] public static class TransactionInterop { internal static OletxTransaction ConvertToOletxTransaction( Transaction transaction ) { if ( null == transaction ) { throw new ArgumentNullException( "transaction" ); } if ( transaction.Disposed ) { throw new ObjectDisposedException( "Transaction" ); } if ( transaction.complete ) { throw TransactionException.CreateTransactionCompletedException( SR.GetString( SR.TraceSourceLtm ) ); } OletxTransaction oletxTx = transaction.Promote(); System.Diagnostics.Debug.Assert( oletxTx != null, "transaction.Promote returned null instead of throwing." ); return oletxTx; } // This is here for the DangerousGetHandle call. We need to do it. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] public static byte[] GetExportCookie( Transaction transaction, byte[] whereabouts ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); byte[] cookie = null; if ( null == transaction ) { throw new ArgumentNullException( "transaction" ); } if ( null == whereabouts ) { throw new ArgumentNullException( "whereabouts" ); } if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetExportCookie" ); } // Copy the whereabouts so that it cannot be modified later. byte[] whereaboutsCopy = new byte[whereabouts.Length]; Array.Copy(whereabouts, whereaboutsCopy, whereabouts.Length); whereabouts = whereaboutsCopy; int cookieIndex = 0; UInt32 cookieSize = 0; CoTaskMemHandle cookieBuffer = null; // First, make sure we are working with an OletxTransaction. OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); try { oletxTx.realOletxTransaction.TransactionShim.Export( Convert.ToUInt32(whereabouts.Length), whereabouts, out cookieIndex, out cookieSize, out cookieBuffer ); // allocate and fill in the cookie cookie = new byte[cookieSize]; Marshal.Copy( cookieBuffer.DangerousGetHandle(), cookie, 0, Convert.ToInt32(cookieSize) ); } catch (COMException comException) { OletxTransactionManager.ProxyException( comException ); // We are unsure of what the exception may mean. It is possible that // we could get E_FAIL when trying to contact a transaction manager that is // being blocked by a fire wall. On the other hand we may get a COMException // based on bad data. The more common situation is that the data is fine // (since it is generated by Microsoft code) and the problem is with // communication. So in this case we default for unknown exceptions to // assume that the problem is with communication. throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException ); } finally { if ( null != cookieBuffer ) { cookieBuffer.Close(); } } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetExportCookie" ); } return cookie; } public static Transaction GetTransactionFromExportCookie( byte[] cookie ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if ( null == cookie ) { throw new ArgumentNullException( "cookie" ); } if ( cookie.Length < 32 ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "cookie" ); } if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromExportCookie" ); } byte[] cookieCopy = new byte [cookie.Length]; Array.Copy(cookie, cookieCopy, cookie.Length); cookie = cookieCopy; Transaction transaction = null; ITransactionShim transactionShim = null; Guid txIdentifier = Guid.Empty; OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment outcomeEnlistment = null; OletxTransaction oleTx = null; // Extract the transaction guid from the propagation token to see if we already have a // transaction object for the transaction. byte[] guidByteArray = new byte[16]; for (int i = 0; i < guidByteArray.Length; i++ ) { // In a cookie, the transaction guid is preceeded by a signature guid. guidByteArray[i] = cookie[i+16]; } Guid txId = new Guid( guidByteArray ); // First check to see if there is a promoted LTM transaction with the same ID. If there // is, just return that. transaction = TransactionManager.FindPromotedTransaction( txId ); if ( null != transaction ) { if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromExportCookie" ); } return transaction; } // We need to create a new transaction RealOletxTransaction realTx = null; OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); try { outcomeEnlistment = new OutcomeEnlistment(); IntPtr outcomeEnlistmentHandle = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); oletxTm.DtcTransactionManager.ProxyShimFactory.Import( Convert.ToUInt32(cookie.Length), cookie, outcomeEnlistmentHandle, out txIdentifier, out oletxIsoLevel, out transactionShim ); } finally { if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) { HandleTable.FreeHandle( outcomeEnlistmentHandle ); } } } catch ( COMException comException ) { OletxTransactionManager.ProxyException( comException ); // We are unsure of what the exception may mean. It is possible that // we could get E_FAIL when trying to contact a transaction manager that is // being blocked by a fire wall. On the other hand we may get a COMException // based on bad data. The more common situation is that the data is fine // (since it is generated by Microsoft code) and the problem is with // communication. So in this case we default for unknown exceptions to // assume that the problem is with communication. throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException ); } finally { oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); } // We need to create a new RealOletxTransaction. realTx = new RealOletxTransaction( oletxTm, transactionShim, outcomeEnlistment, txIdentifier, oletxIsoLevel, false ); // Now create the associated OletxTransaction. oleTx = new OletxTransaction( realTx ); // If a transaction is found then FindOrCreate will Dispose the oletx // created. transaction = TransactionManager.FindOrCreatePromotedTransaction( txId, oleTx ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromExportCookie" ); } return transaction; } public static byte[] GetTransmitterPropagationToken( Transaction transaction ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if ( null == transaction ) { throw new ArgumentNullException( "transaction" ); } if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransmitterPropagationToken" ); } // First, make sure we are working with an OletxTransaction. OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); byte [] token = GetTransmitterPropagationToken( oletxTx ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransmitterPropagationToken" ); } return token; } // This is here for the DangerousGetHandle call. We need to do it. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] internal static byte[] GetTransmitterPropagationToken( OletxTransaction oletxTx ) { byte[] propagationToken = null; CoTaskMemHandle propagationTokenBuffer = null; UInt32 tokenSize = 0; try { oletxTx.realOletxTransaction.TransactionShim.GetPropagationToken( out tokenSize, out propagationTokenBuffer ); propagationToken = new byte[ tokenSize ]; Marshal.Copy( propagationTokenBuffer.DangerousGetHandle(), propagationToken, 0, Convert.ToInt32(tokenSize) ); } catch (COMException comException) { OletxTransactionManager.ProxyException( comException ); throw; } finally { if ( null != propagationTokenBuffer ) { propagationTokenBuffer.Close(); } } return propagationToken; } public static Transaction GetTransactionFromTransmitterPropagationToken( byte[] propagationToken ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); Transaction returnValue = null; if ( null == propagationToken ) { throw new ArgumentNullException( "propagationToken" ); } if ( propagationToken.Length < 24 ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "propagationToken" ); } if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromTransmitterPropagationToken" ); } // Extract the transaction guid from the propagation token to see if we already have a // transaction object for the transaction. byte[] guidByteArray = new byte[16]; for (int i = 0; i < guidByteArray.Length; i++ ) { // In a propagation token, the transaction guid is preceeded by two version DWORDs. guidByteArray[i] = propagationToken[i+8]; } Guid txId = new Guid( guidByteArray ); // First check to see if there is a promoted LTM transaction with the same ID. If there // is, just return that. Transaction tx = TransactionManager.FindPromotedTransaction( txId ); if ( null != tx ) { if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromTransmitterPropagationToken" ); } return tx; } OletxTransaction oleTx = TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken( propagationToken ); // If a transaction is found then FindOrCreate will Dispose the oletx // created. returnValue = TransactionManager.FindOrCreatePromotedTransaction( txId, oleTx ); if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromTransmitterPropagationToken" ); } return returnValue; } internal static OletxTransaction GetOletxTransactionFromTransmitterPropigationToken( byte[] propagationToken ) { Guid identifier; OletxTransactionIsolationLevel oletxIsoLevel; OutcomeEnlistment outcomeEnlistment; ITransactionShim transactionShim = null; if ( null == propagationToken ) { throw new ArgumentNullException( "propagationToken" ); } if ( propagationToken.Length < 24 ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "propagationToken" ); } byte [] propagationTokenCopy = new byte [propagationToken.Length]; Array.Copy(propagationToken, propagationTokenCopy, propagationToken.Length); propagationToken = propagationTokenCopy; // First we need to create an OletxTransactionManager from Config. OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); try { outcomeEnlistment = new OutcomeEnlistment(); IntPtr outcomeEnlistmentHandle = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); oletxTm.DtcTransactionManager.ProxyShimFactory.ReceiveTransaction( Convert.ToUInt32(propagationToken.Length), propagationToken, outcomeEnlistmentHandle, out identifier, out oletxIsoLevel, out transactionShim ); } finally { if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) { HandleTable.FreeHandle( outcomeEnlistmentHandle ); } } } catch ( COMException comException ) { OletxTransactionManager.ProxyException( comException ); // We are unsure of what the exception may mean. It is possible that // we could get E_FAIL when trying to contact a transaction manager that is // being blocked by a fire wall. On the other hand we may get a COMException // based on bad data. The more common situation is that the data is fine // (since it is generated by Microsoft code) and the problem is with // communication. So in this case we default for unknown exceptions to // assume that the problem is with communication. throw TransactionManagerCommunicationException.Create( SR.GetString( SR.TraceSourceOletx ), comException ); } finally { oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); } RealOletxTransaction realTx = null; realTx = new RealOletxTransaction( oletxTm, transactionShim, outcomeEnlistment, identifier, oletxIsoLevel, false ); return new OletxTransaction( realTx ); } // This is here for the "Dtc" in the name. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] public static IDtcTransaction GetDtcTransaction( Transaction transaction ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); if ( null == transaction ) { throw new ArgumentNullException( "transaction" ); } if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetDtcTransaction" ); } IDtcTransaction transactionNative = null; // First, make sure we are working with an OletxTransaction. OletxTransaction oletxTx = TransactionInterop.ConvertToOletxTransaction( transaction ); try { oletxTx.realOletxTransaction.TransactionShim.GetITransactionNative( out transactionNative ); } catch( COMException comException ) { OletxTransactionManager.ProxyException( comException ); throw; } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetDtcTransaction" ); } return transactionNative; } // This is here for the "DTC" in the name. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")] public static Transaction GetTransactionFromDtcTransaction( IDtcTransaction transactionNative ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); bool tooLate = false; ITransactionShim transactionShim = null; Guid txIdentifier = Guid.Empty; OletxTransactionIsolationLevel oletxIsoLevel = OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; OutcomeEnlistment outcomeEnlistment = null; RealOletxTransaction realTx = null; OletxTransaction oleTx = null; if ( null == transactionNative ) { throw new ArgumentNullException( "transactionNative" ); } Transaction transaction = null; if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromDtc" ); } // Let's get the guid of the transaction from the proxy to see if we already // have an object. ITransactionNativeInternal myTransactionNative = transactionNative as ITransactionNativeInternal; if ( null == myTransactionNative ) { throw new ArgumentException( SR.GetString( SR.InvalidArgument ), "transactionNative" ); } OletxXactTransInfo xactInfo; try { myTransactionNative.GetTransactionInfo( out xactInfo ); } catch ( COMException ex ) { if ( Oletx.NativeMethods.XACT_E_NOTRANSACTION != ex.ErrorCode ) { throw; } // If we get here, the transaction has appraently already been committed or aborted. Allow creation of the // OletxTransaction, but it will be marked with a status of InDoubt and attempts to get its Identifier // property will result in a TransactionException. tooLate = true; xactInfo.uow = Guid.Empty; } OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; if ( ! tooLate ) { // First check to see if there is a promoted LTM transaction with the same ID. If there // is, just return that. transaction = TransactionManager.FindPromotedTransaction( xactInfo.uow ); if ( null != transaction ) { if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromDtcTransaction" ); } return transaction; } // We need to create a new RealOletxTransaction... oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); try { outcomeEnlistment = new OutcomeEnlistment(); IntPtr outcomeEnlistmentHandle = IntPtr.Zero; RuntimeHelpers.PrepareConstrainedRegions(); try { outcomeEnlistmentHandle = HandleTable.AllocHandle( outcomeEnlistment ); oletxTm.DtcTransactionManager.ProxyShimFactory.CreateTransactionShim( transactionNative, outcomeEnlistmentHandle, out txIdentifier, out oletxIsoLevel, out transactionShim ); } finally { if ( transactionShim == null && outcomeEnlistmentHandle != IntPtr.Zero ) { HandleTable.FreeHandle( outcomeEnlistmentHandle ); } } } catch ( COMException comException ) { OletxTransactionManager.ProxyException( comException ); throw; } finally { oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); } // We need to create a new RealOletxTransaction. realTx = new RealOletxTransaction( oletxTm, transactionShim, outcomeEnlistment, txIdentifier, oletxIsoLevel, false ); oleTx = new OletxTransaction( realTx ); // If a transaction is found then FindOrCreate will Dispose the oletx // created. transaction = TransactionManager.FindOrCreatePromotedTransaction( xactInfo.uow, oleTx ); } else { // It was too late to do a clone of the provided ITransactionNative, so we are just going to // create a RealOletxTransaction without a transaction shim or outcome enlistment. realTx = new RealOletxTransaction( oletxTm, null, null, txIdentifier, OletxTransactionIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE, false ); oleTx = new OletxTransaction( realTx ); transaction = new Transaction( oleTx ); TransactionManager.FireDistributedTransactionStarted( transaction ); oleTx.savedLtmPromotedTransaction = transaction; InternalTransaction.DistributedTransactionOutcome(transaction.internalTransaction, TransactionStatus.InDoubt); } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetTransactionFromDtc" ); } return transaction; } public static byte[] GetWhereabouts( ) { if( !TransactionManager._platformValidated ) TransactionManager.ValidatePlatform(); byte[] returnValue = null; if ( DiagnosticTrace.Verbose ) { MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetWhereabouts" ); } OletxTransactionManager oletxTm = TransactionManager.DistributedTransactionManager; if ( null == oletxTm ) { throw new ArgumentException( SR.GetString( SR.ArgumentWrongType ), "transactionManager" ); } oletxTm.dtcTransactionManagerLock.AcquireReaderLock( -1 ); try { returnValue = oletxTm.DtcTransactionManager.Whereabouts; } finally { oletxTm.dtcTransactionManagerLock.ReleaseReaderLock(); } if ( DiagnosticTrace.Verbose ) { MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), "TransactionInterop.GetWhereabouts" ); } return returnValue; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DeleteMemberBinder.cs
- InkCanvasFeedbackAdorner.cs
- RectAnimation.cs
- X509SecurityTokenProvider.cs
- MainMenu.cs
- CollectionsUtil.cs
- Literal.cs
- SelectedGridItemChangedEvent.cs
- DataContractJsonSerializer.cs
- thaishape.cs
- MarkupWriter.cs
- AmbientProperties.cs
- GridEntryCollection.cs
- SoapExtensionStream.cs
- HyperLink.cs
- XmlDownloadManager.cs
- GridView.cs
- TextBoxDesigner.cs
- PhysicalAddress.cs
- EntityTypeBase.cs
- AuthorizationSection.cs
- XmlIlTypeHelper.cs
- ProfilePropertySettings.cs
- Camera.cs
- WorkflowDurableInstance.cs
- EdmValidator.cs
- DataTableMappingCollection.cs
- CurrentTimeZone.cs
- NativeActivityMetadata.cs
- ComponentRenameEvent.cs
- RuleSettingsCollection.cs
- EncoderParameters.cs
- DiscreteKeyFrames.cs
- TextTreePropertyUndoUnit.cs
- InstanceDescriptor.cs
- RtfNavigator.cs
- CodeGenerator.cs
- FolderBrowserDialog.cs
- XmlValidatingReader.cs
- EventLogEntryCollection.cs
- CryptoStream.cs
- Stream.cs
- QilValidationVisitor.cs
- CompensationHandlingFilter.cs
- Scalars.cs
- HttpRequest.cs
- ImmutableCollection.cs
- RSAPKCS1SignatureDeformatter.cs
- SafeSystemMetrics.cs
- ObjectToken.cs
- SoapReflectionImporter.cs
- RegisteredScript.cs
- XmlFormatReaderGenerator.cs
- IntranetCredentialPolicy.cs
- SoapFormatExtensions.cs
- WeakReferenceKey.cs
- AttachInfo.cs
- CodeSubDirectoriesCollection.cs
- DataList.cs
- TypefaceMetricsCache.cs
- DataKeyCollection.cs
- TimelineClockCollection.cs
- EncoderParameters.cs
- DataGridViewRowContextMenuStripNeededEventArgs.cs
- QueryContinueDragEventArgs.cs
- AllMembershipCondition.cs
- EventEntry.cs
- EncodingTable.cs
- DrawToolTipEventArgs.cs
- Popup.cs
- WebControl.cs
- Part.cs
- WebPartAuthorizationEventArgs.cs
- DataGridViewAutoSizeModeEventArgs.cs
- GACIdentityPermission.cs
- CommandSet.cs
- DataGridColumnsPage.cs
- InheritedPropertyChangedEventArgs.cs
- BinaryParser.cs
- DelegatedStream.cs
- TimeSpanParse.cs
- PageParser.cs
- Certificate.cs
- RowUpdatingEventArgs.cs
- BaseCollection.cs
- ImmutableAssemblyCacheEntry.cs
- FaultCode.cs
- NumberSubstitution.cs
- MergePropertyDescriptor.cs
- TypeSystemHelpers.cs
- SQLInt64.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- _ContextAwareResult.cs
- CacheAxisQuery.cs
- Menu.cs
- ExpressionHelper.cs
- FixedLineResult.cs
- ParserStreamGeometryContext.cs
- HtmlProps.cs
- DateTimeFormatInfo.cs