private void Initialize() { if (!this.initialized) { OletxInternalResourceManager internalResourceManager = this.oletxTm.internalResourceManager; IntPtr zero = IntPtr.Zero; IResourceManagerShim resourceManagerShim = null; bool nodeNameMatches = false; CoTaskMemHandle whereaboutsBuffer = null; RuntimeHelpers.PrepareConstrainedRegions(); try { zero = HandleTable.AllocHandle(internalResourceManager); this.proxyShimFactory.ConnectToProxy(this.nodeName, internalResourceManager.Identifier, zero, out nodeNameMatches, out this.whereaboutsSize, out whereaboutsBuffer, out resourceManagerShim); if (!nodeNameMatches) { throw new NotSupportedException(System.Transactions.SR.GetString("ProxyCannotSupportMultipleNodeNames")); } if ((whereaboutsBuffer != null) && (this.whereaboutsSize != 0)) { this.whereabouts = new byte[this.whereaboutsSize]; Marshal.Copy(whereaboutsBuffer.DangerousGetHandle(), this.whereabouts, 0, Convert.ToInt32(this.whereaboutsSize)); } internalResourceManager.resourceManagerShim = resourceManagerShim; internalResourceManager.CallReenlistComplete(); this.initialized = true; } catch (COMException exception) { if (System.Transactions.Oletx.NativeMethods.XACT_E_NOTSUPPORTED == exception.ErrorCode) { throw new NotSupportedException(System.Transactions.SR.GetString("CannotSupportNodeNameSpecification")); } OletxTransactionManager.ProxyException(exception); throw TransactionManagerCommunicationException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("TransactionManagerCommunicationException"), exception); } finally { if (whereaboutsBuffer != null) { whereaboutsBuffer.Close(); } if (!this.initialized) { if ((zero != IntPtr.Zero) && (resourceManagerShim == null)) { HandleTable.FreeHandle(zero); } if (this.whereabouts != null) { this.whereabouts = null; this.whereaboutsSize = 0; } } } } }
internal OletxTransactionManager(string nodeName) { lock (ClassSyncObject) { if (proxyShimFactory == null) { if (System.Transactions.Oletx.NativeMethods.GetNotificationFactory(ShimWaitHandle.SafeWaitHandle, out proxyShimFactory) != 0) { throw TransactionException.Create(System.Transactions.SR.GetString("TraceSourceOletx"), System.Transactions.SR.GetString("UnableToGetNotificationShimFactory"), null); } ThreadPool.UnsafeRegisterWaitForSingleObject(ShimWaitHandle, new WaitOrTimerCallback(OletxTransactionManager.ShimNotificationCallback), null, -1, false); } } this.dtcTransactionManagerLock = new ReaderWriterLock(); this.nodeNameField = nodeName; if ((this.nodeNameField != null) && (this.nodeNameField.Length == 0)) { this.nodeNameField = null; } if (DiagnosticTrace.Verbose) { DistributedTransactionManagerCreatedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), base.GetType(), this.nodeNameField); } this.configuredTransactionOptions.IsolationLevel = this.isolationLevelProperty = TransactionManager.DefaultIsolationLevel; this.configuredTransactionOptions.Timeout = this.timeoutProperty = TransactionManager.DefaultTimeout; this.internalResourceManager = new OletxInternalResourceManager(this); this.dtcTransactionManagerLock.AcquireWriterLock(-1); try { this.dtcTransactionManager = new System.Transactions.Oletx.DtcTransactionManager(this.nodeNameField, this); } finally { this.dtcTransactionManagerLock.ReleaseWriterLock(); } if (resourceManagerHashTable == null) { resourceManagerHashTable = new Hashtable(2); resourceManagerHashTableLock = new ReaderWriterLock(); } }
internal static void ShimNotificationCallback(object state, bool timeout) { IntPtr zero = IntPtr.Zero; ShimNotificationType none = ShimNotificationType.None; bool isSinglePhase = false; bool abortingHint = false; uint prepareInfoSize = 0; CoTaskMemHandle prepareInfo = null; bool releaseRequired = false; bool flag3 = false; IDtcProxyShimFactory factory = null; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxTransactionManager.ShimNotificationCallback"); } Thread.BeginCriticalRegion(); try { Label_003D: factory = proxyShimFactory; try { object obj2; OletxResourceManager manager2; byte[] buffer; Thread.BeginThreadAffinity(); RuntimeHelpers.PrepareConstrainedRegions(); try { factory.GetNotification(out zero, out none, out isSinglePhase, out abortingHint, out releaseRequired, out prepareInfoSize, out prepareInfo); } finally { if (releaseRequired) { if (HandleTable.FindHandle(zero) is OletxInternalResourceManager) { processingTmDown = true; Monitor.Enter(proxyShimFactory); } else { releaseRequired = false; } factory.ReleaseNotificationLock(); } Thread.EndThreadAffinity(); } if (processingTmDown) { lock (proxyShimFactory) { } } if (none != ShimNotificationType.None) { obj2 = HandleTable.FindHandle(zero); switch (none) { case ShimNotificationType.Phase0RequestNotify: try { OletxPhase0VolatileEnlistmentContainer container5 = obj2 as OletxPhase0VolatileEnlistmentContainer; if (container5 != null) { DiagnosticTrace.SetActivityId(container5.TransactionIdentifier); container5.Phase0Request(abortingHint); } else { OletxEnlistment enlistment8 = obj2 as OletxEnlistment; if (enlistment8 != null) { DiagnosticTrace.SetActivityId(enlistment8.TransactionIdentifier); enlistment8.Phase0Request(abortingHint); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } break; case ShimNotificationType.VoteRequestNotify: break; case ShimNotificationType.PrepareRequestNotify: goto Label_02B0; case ShimNotificationType.CommitRequestNotify: goto Label_031A; case ShimNotificationType.AbortRequestNotify: goto Label_0358; case ShimNotificationType.CommittedNotify: try { OutcomeEnlistment enlistment7 = obj2 as OutcomeEnlistment; if (enlistment7 != null) { DiagnosticTrace.SetActivityId(enlistment7.TransactionIdentifier); enlistment7.Committed(); } else { OletxPhase1VolatileEnlistmentContainer container3 = obj2 as OletxPhase1VolatileEnlistmentContainer; if (container3 != null) { DiagnosticTrace.SetActivityId(container3.TransactionIdentifier); container3.Committed(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } goto Label_0203; case ShimNotificationType.AbortedNotify: goto Label_0203; case ShimNotificationType.InDoubtNotify: goto Label_0251; case ShimNotificationType.EnlistmentTmDownNotify: goto Label_0396; case ShimNotificationType.ResourceManagerTmDownNotify: goto Label_03CD; default: goto Label_0410; } OletxPhase1VolatileEnlistmentContainer container4 = obj2 as OletxPhase1VolatileEnlistmentContainer; if (container4 != null) { DiagnosticTrace.SetActivityId(container4.TransactionIdentifier); container4.VoteRequest(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; Label_0203 :; try { OutcomeEnlistment enlistment6 = obj2 as OutcomeEnlistment; if (enlistment6 != null) { DiagnosticTrace.SetActivityId(enlistment6.TransactionIdentifier); enlistment6.Aborted(); } else { OletxPhase1VolatileEnlistmentContainer container2 = obj2 as OletxPhase1VolatileEnlistmentContainer; if (container2 != null) { DiagnosticTrace.SetActivityId(container2.TransactionIdentifier); container2.Aborted(); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_0251 :; try { OutcomeEnlistment enlistment5 = obj2 as OutcomeEnlistment; if (enlistment5 != null) { DiagnosticTrace.SetActivityId(enlistment5.TransactionIdentifier); enlistment5.InDoubt(); } else { OletxPhase1VolatileEnlistmentContainer container = obj2 as OletxPhase1VolatileEnlistmentContainer; if (container != null) { DiagnosticTrace.SetActivityId(container.TransactionIdentifier); container.InDoubt(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_02B0: buffer = new byte[prepareInfoSize]; Marshal.Copy(prepareInfo.DangerousGetHandle(), buffer, 0, Convert.ToInt32(prepareInfoSize)); bool flag2 = true; try { OletxEnlistment enlistment4 = obj2 as OletxEnlistment; if (enlistment4 != null) { DiagnosticTrace.SetActivityId(enlistment4.TransactionIdentifier); flag2 = enlistment4.PrepareRequest(isSinglePhase, buffer); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } goto Label_0444; } finally { if (flag2) { HandleTable.FreeHandle(zero); } } Label_031A :; try { OletxEnlistment enlistment3 = obj2 as OletxEnlistment; if (enlistment3 != null) { DiagnosticTrace.SetActivityId(enlistment3.TransactionIdentifier); enlistment3.CommitRequest(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_0358 :; try { OletxEnlistment enlistment2 = obj2 as OletxEnlistment; if (enlistment2 != null) { DiagnosticTrace.SetActivityId(enlistment2.TransactionIdentifier); enlistment2.AbortRequest(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_0396 :; try { OletxEnlistment enlistment = obj2 as OletxEnlistment; if (enlistment != null) { DiagnosticTrace.SetActivityId(enlistment.TransactionIdentifier); enlistment.TMDown(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_03CD: manager2 = obj2 as OletxResourceManager; try { if (manager2 != null) { manager2.TMDown(); } else { OletxInternalResourceManager manager = obj2 as OletxInternalResourceManager; if (manager != null) { manager.TMDown(); } else { Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } } goto Label_0444; } finally { HandleTable.FreeHandle(zero); } Label_0410: Environment.FailFast(System.Transactions.SR.GetString("InternalError")); } finally { if (prepareInfo != null) { prepareInfo.Close(); } if (releaseRequired) { releaseRequired = false; processingTmDown = false; Monitor.Exit(proxyShimFactory); } } Label_0444: if (none != ShimNotificationType.None) { goto Label_003D; } flag3 = true; } finally { if (releaseRequired) { releaseRequired = false; processingTmDown = false; Monitor.Exit(proxyShimFactory); } if (!flag3 && (zero != IntPtr.Zero)) { HandleTable.FreeHandle(zero); } Thread.EndCriticalRegion(); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(System.Transactions.SR.GetString("TraceSourceOletx"), "OletxTransactionManager.ShimNotificationCallback"); } }
internal static void ShimNotificationCallback(object state, bool timeout) { // First we need to get the notification from the shim factory. IntPtr enlistmentHandleIntPtr = IntPtr.Zero; ShimNotificationType shimNotificationType = ShimNotificationType.None; bool isSinglePhase = false; bool abortingHint = false; UInt32 prepareInfoSize = 0; CoTaskMemHandle prepareInfoBuffer = null; bool holdingNotificationLock = false; bool cleanExit = false; IDtcProxyShimFactory localProxyShimFactory = null; if (DiagnosticTrace.Verbose) { MethodEnteredTraceRecord.Trace(SR.GetString(SR.TraceSourceOletx), "OletxTransactionManager.ShimNotificationCallback" ); } // This lock doesn't really protect any of our data. It is here so that if an exception occurs // while calling out to the app, we get an escalation to AppDomainUnload. Thread.BeginCriticalRegion(); try { do { // Take a local copy of the proxyShimFactory because if we get an RM TMDown notification, // we will still hold the critical section in that factory, but processing of the TMDown will // cause replacement of the OletxTransactionManager.proxyShimFactory. localProxyShimFactory = OletxTransactionManager.proxyShimFactory; try { Thread.BeginThreadAffinity(); RuntimeHelpers.PrepareConstrainedRegions(); try { localProxyShimFactory.GetNotification( out enlistmentHandleIntPtr, out shimNotificationType, out isSinglePhase, out abortingHint, out holdingNotificationLock, out prepareInfoSize, out prepareInfoBuffer ); } finally { if (holdingNotificationLock) { if ((HandleTable.FindHandle(enlistmentHandleIntPtr)) is OletxInternalResourceManager) { // In this case we know that the TM has gone down and we need to exchange // the native lock for a managed lock. processingTmDown = true; #pragma warning disable 0618 //@ System.Threading.Monitor.Enter(OletxTransactionManager.proxyShimFactory); #pragma warning restore 0618 } else { holdingNotificationLock = false; } localProxyShimFactory.ReleaseNotificationLock(); } Thread.EndThreadAffinity(); } // If a TM down is being processed it is possible that the native lock // has been exchanged for a managed lock. In that case we need to attempt // to take a lock to hold up processing more events until the TM down // processing is complete. if (processingTmDown) { lock (OletxTransactionManager.proxyShimFactory) { // We don't do any work under this lock just make sure that we // can take it. } } if (ShimNotificationType.None != shimNotificationType) { Object target = HandleTable.FindHandle(enlistmentHandleIntPtr); // Next, based on the notification type, cast the Handle accordingly and make // the appropriate call on the enlistment. switch (shimNotificationType) { case ShimNotificationType.Phase0RequestNotify: { try { OletxPhase0VolatileEnlistmentContainer ph0VolEnlistContainer = target as OletxPhase0VolatileEnlistmentContainer; if (null != ph0VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph0VolEnlistContainer.TransactionIdentifier); //CSDMain 91509 - We now synchronize this call with the AddDependentClone call in RealOleTxTransaction ph0VolEnlistContainer.Phase0Request(abortingHint); } else { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistment.Phase0Request(abortingHint); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.VoteRequestNotify: { OletxPhase1VolatileEnlistmentContainer ph1VolEnlistContainer = target as OletxPhase1VolatileEnlistmentContainer; if (null != ph1VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph1VolEnlistContainer.TransactionIdentifier); ph1VolEnlistContainer.VoteRequest(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } break; } case ShimNotificationType.CommittedNotify: { try { OutcomeEnlistment outcomeEnlistment = target as OutcomeEnlistment; if (null != outcomeEnlistment) { DiagnosticTrace.SetActivityId( outcomeEnlistment.TransactionIdentifier); outcomeEnlistment.Committed(); } else { OletxPhase1VolatileEnlistmentContainer ph1VolEnlistContainer = target as OletxPhase1VolatileEnlistmentContainer; if (null != ph1VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph1VolEnlistContainer.TransactionIdentifier); ph1VolEnlistContainer.Committed(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.AbortedNotify: { try { OutcomeEnlistment outcomeEnlistment = target as OutcomeEnlistment; if (null != outcomeEnlistment) { DiagnosticTrace.SetActivityId( outcomeEnlistment.TransactionIdentifier); outcomeEnlistment.Aborted(); } else { OletxPhase1VolatileEnlistmentContainer ph1VolEnlistContainer = target as OletxPhase1VolatileEnlistmentContainer; if (null != ph1VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph1VolEnlistContainer.TransactionIdentifier); ph1VolEnlistContainer.Aborted(); } // else // Voters may receive notifications even // in cases where they therwise respond // negatively to the vote request. It is // also not guaranteed that we will get a // notification if we do respond negatively. // The only safe thing to do is to free the // Handle when we abort the transaction // with a voter. These two things together // mean that we cannot guarantee that this // Handle will be alive when we get this // notification. } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.InDoubtNotify: { try { OutcomeEnlistment outcomeEnlistment = target as OutcomeEnlistment; if (null != outcomeEnlistment) { DiagnosticTrace.SetActivityId( outcomeEnlistment.TransactionIdentifier); outcomeEnlistment.InDoubt(); } else { OletxPhase1VolatileEnlistmentContainer ph1VolEnlistContainer = target as OletxPhase1VolatileEnlistmentContainer; if (null != ph1VolEnlistContainer) { DiagnosticTrace.SetActivityId( ph1VolEnlistContainer.TransactionIdentifier); ph1VolEnlistContainer.InDoubt(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.PrepareRequestNotify: { byte[] prepareInfo = new byte[prepareInfoSize]; Marshal.Copy(prepareInfoBuffer.DangerousGetHandle(), prepareInfo, 0, Convert.ToInt32(prepareInfoSize)); bool enlistmentDone = true; try { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistmentDone = enlistment.PrepareRequest( isSinglePhase, prepareInfo ); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } finally { if (enlistmentDone) { HandleTable.FreeHandle(enlistmentHandleIntPtr); } } break; } case ShimNotificationType.CommitRequestNotify: { try { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistment.CommitRequest(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.AbortRequestNotify: { try { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistment.AbortRequest(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.EnlistmentTmDownNotify: { try { OletxEnlistment enlistment = target as OletxEnlistment; if (null != enlistment) { DiagnosticTrace.SetActivityId( enlistment.TransactionIdentifier); enlistment.TMDown(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } finally { // We aren't going to get any more notifications on this. HandleTable.FreeHandle(enlistmentHandleIntPtr); } break; } case ShimNotificationType.ResourceManagerTmDownNotify: { OletxResourceManager resourceManager = target as OletxResourceManager; try { if (null != resourceManager) { resourceManager.TMDown(); } else { OletxInternalResourceManager internalResourceManager = target as OletxInternalResourceManager; if (null != internalResourceManager) { internalResourceManager.TMDown(); } else { Environment.FailFast(SR.GetString(SR.InternalError)); } } } finally { HandleTable.FreeHandle(enlistmentHandleIntPtr); } // Note that we don't free the gchandle on the OletxResourceManager. These objects // are not going to go away. break; } default: { Environment.FailFast(SR.GetString(SR.InternalError)); break; } } } } finally { if (null != prepareInfoBuffer) { prepareInfoBuffer.Close(); } if (holdingNotificationLock) { holdingNotificationLock = false; processingTmDown = false; System.Threading.Monitor.Exit(OletxTransactionManager.proxyShimFactory); } } }while (ShimNotificationType.None != shimNotificationType); cleanExit = true; } finally { if (holdingNotificationLock) { holdingNotificationLock = false; processingTmDown = false; System.Threading.Monitor.Exit(OletxTransactionManager.proxyShimFactory); } if (!cleanExit && enlistmentHandleIntPtr != IntPtr.Zero) { HandleTable.FreeHandle(enlistmentHandleIntPtr); } Thread.EndCriticalRegion(); } if (DiagnosticTrace.Verbose) { MethodExitedTraceRecord.Trace(SR.GetString(SR.TraceSourceOletx), "OletxTransactionManager.ShimNotificationCallback" ); } }
internal OletxTransactionManager( string nodeName ) { lock ( ClassSyncObject ) { // If we have not already initialized the shim factory and started the notification // thread, do so now. if (null == OletxTransactionManager.proxyShimFactory) { Int32 error = NativeMethods.GetNotificationFactory( OletxTransactionManager.ShimWaitHandle.SafeWaitHandle, out OletxTransactionManager.proxyShimFactory ); if (0 != error) { throw TransactionException.Create(SR.GetString(SR.TraceSourceOletx), SR.GetString(SR.UnableToGetNotificationShimFactory), null); } ThreadPool.UnsafeRegisterWaitForSingleObject( OletxTransactionManager.ShimWaitHandle, new WaitOrTimerCallback(OletxTransactionManager.ShimNotificationCallback), null, -1, false ); } } this.dtcTransactionManagerLock = new ReaderWriterLock(); this.nodeNameField = nodeName; // The DTC proxy doesn't like an empty string for node name on 64-bit platforms when // running as WOW64. It treats any non-null node name as a "remote" node and turns off // the WOW64 bit, causing problems when reading the registry. So if we got on empty // string for the node name, just treat it as null. if ((null != this.nodeNameField) && (0 == this.nodeNameField.Length)) { this.nodeNameField = null; } if (DiagnosticTrace.Verbose) { DistributedTransactionManagerCreatedTraceRecord.Trace(SR.GetString(SR.TraceSourceOletx), this.GetType(), this.nodeNameField ); } // Initialize the properties from config. configuredTransactionOptions.IsolationLevel = isolationLevelProperty = TransactionManager.DefaultIsolationLevel; configuredTransactionOptions.Timeout = timeoutProperty = TransactionManager.DefaultTimeout; this.internalResourceManager = new OletxInternalResourceManager(this); dtcTransactionManagerLock.AcquireWriterLock(-1); try { this.dtcTransactionManager = new DtcTransactionManager(this.nodeNameField, this); } finally { dtcTransactionManagerLock.ReleaseWriterLock(); } if (resourceManagerHashTable == null) { resourceManagerHashTable = new Hashtable(2); resourceManagerHashTableLock = new System.Threading.ReaderWriterLock(); } }
internal OletxTransactionManager( string nodeName ) { lock ( ClassSyncObject ) { // If we have not already initialized the shim factory and started the notification // thread, do so now. if (null == OletxTransactionManager.proxyShimFactory ) { Int32 error = NativeMethods.GetNotificationFactory( OletxTransactionManager.ShimWaitHandle.SafeWaitHandle, out OletxTransactionManager.proxyShimFactory ); if ( 0 != error ) { throw TransactionException.Create( SR.GetString( SR.TraceSourceOletx ), SR.GetString( SR.UnableToGetNotificationShimFactory ), null ); } ThreadPool.UnsafeRegisterWaitForSingleObject( OletxTransactionManager.ShimWaitHandle, new WaitOrTimerCallback( OletxTransactionManager.ShimNotificationCallback ), null, -1, false ); } } this.dtcTransactionManagerLock = new ReaderWriterLock(); this.nodeNameField = nodeName; // The DTC proxy doesn't like an empty string for node name on 64-bit platforms when // running as WOW64. It treats any non-null node name as a "remote" node and turns off // the WOW64 bit, causing problems when reading the registry. So if we got on empty // string for the node name, just treat it as null. if (( null != this.nodeNameField ) && ( 0 == this.nodeNameField.Length )) { this.nodeNameField = null; } if ( DiagnosticTrace.Verbose ) { DistributedTransactionManagerCreatedTraceRecord.Trace( SR.GetString( SR.TraceSourceOletx ), this.GetType(), this.nodeNameField ); } // Initialize the properties from config. configuredTransactionOptions.IsolationLevel = isolationLevelProperty = TransactionManager.DefaultIsolationLevel; configuredTransactionOptions.Timeout = timeoutProperty = TransactionManager.DefaultTimeout; this.internalResourceManager = new OletxInternalResourceManager( this ); dtcTransactionManagerLock.AcquireWriterLock( -1 ); try { this.dtcTransactionManager = new DtcTransactionManager( this.nodeNameField, this ); } finally { dtcTransactionManagerLock.ReleaseWriterLock(); } if (resourceManagerHashTable == null) { resourceManagerHashTable = new Hashtable(2); resourceManagerHashTableLock = new System.Threading.ReaderWriterLock(); } }
void Initialize() { if (this.initialized) { return; } OletxInternalResourceManager internalRM = this.oletxTm.internalResourceManager; IntPtr handle = IntPtr.Zero; IResourceManagerShim resourceManagerShim = null; bool nodeNameMatches = false; CoTaskMemHandle whereaboutsBuffer = null; RuntimeHelpers.PrepareConstrainedRegions(); try { handle = HandleTable.AllocHandle(internalRM); this.proxyShimFactory.ConnectToProxy( this.nodeName, internalRM.Identifier, handle, out nodeNameMatches, out this.whereaboutsSize, out whereaboutsBuffer, out resourceManagerShim ); // If the node name does not match, throw. if (!nodeNameMatches) { throw new NotSupportedException(SR.GetString(SR.ProxyCannotSupportMultipleNodeNames)); } // Make a managed copy of the whereabouts. if ((null != whereaboutsBuffer) && (0 != this.whereaboutsSize)) { this.whereabouts = new byte[this.whereaboutsSize]; Marshal.Copy(whereaboutsBuffer.DangerousGetHandle(), this.whereabouts, 0, Convert.ToInt32(this.whereaboutsSize)); } // Give the IResourceManagerShim to the internalRM and tell it to call ReenlistComplete. internalRM.resourceManagerShim = resourceManagerShim; internalRM.CallReenlistComplete(); this.initialized = true; } catch (COMException ex) { if (NativeMethods.XACT_E_NOTSUPPORTED == ex.ErrorCode) { throw new NotSupportedException(SR.GetString(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.GetString(SR.TraceSourceOletx), SR.GetString(SR.TransactionManagerCommunicationException), ex ); } finally { if (null != whereaboutsBuffer) { whereaboutsBuffer.Close(); } // If we weren't successful at initializing ourself, clear things out // for next time around. if (!this.initialized) { if (handle != IntPtr.Zero && null == resourceManagerShim) { HandleTable.FreeHandle(handle); } if (null != this.whereabouts) { this.whereabouts = null; this.whereaboutsSize = 0; } } } }