private void TakeContainerLock(OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer, ref bool phase0ContainerLockAcquired)
 {
     if (!phase0ContainerLockAcquired)
     {
         Monitor.Enter(localPhase0VolatileContainer);
         phase0ContainerLockAcquired = true;
     }
 }
 private void ReleaseContainerLock(OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer, ref bool phase0ContainerLockAcquired)
 {
     if (phase0ContainerLockAcquired)
     {
         Monitor.Exit(localPhase0VolatileContainer);
         phase0ContainerLockAcquired = false;
     }
 }
Example #3
0
        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 OletxVolatileEnlistmentContainer AddDependentClone(bool delayCommit)
 {
     IVoterBallotShim voterBallotShim = null;
     IPhase0EnlistmentShim shim2 = null;
     bool flag2 = false;
     bool flag = false;
     OletxVolatileEnlistmentContainer container3 = null;
     OletxPhase0VolatileEnlistmentContainer container = null;
     OletxPhase1VolatileEnlistmentContainer target = null;
     bool flag3 = false;
     bool flag5 = false;
     IntPtr zero = IntPtr.Zero;
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         lock (this)
         {
             if (delayCommit)
             {
                 if (this.phase0EnlistVolatilementContainerList == null)
                 {
                     this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                 }
                 if (this.phase0EnlistVolatilementContainerList.Count == 0)
                 {
                     container = new OletxPhase0VolatileEnlistmentContainer(this);
                     flag = true;
                 }
                 else
                 {
                     container = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;
                     if (container != null)
                     {
                         this.TakeContainerLock(container, ref flag5);
                     }
                     if (!container.NewEnlistmentsAllowed)
                     {
                         this.ReleaseContainerLock(container, ref flag5);
                         container = new OletxPhase0VolatileEnlistmentContainer(this);
                         flag = true;
                     }
                     else
                     {
                         flag = false;
                     }
                 }
                 if (flag)
                 {
                     zero = HandleTable.AllocHandle(container);
                 }
             }
             else if (this.phase1EnlistVolatilementContainer == null)
             {
                 target = new OletxPhase1VolatileEnlistmentContainer(this);
                 flag2 = true;
                 target.voterHandle = HandleTable.AllocHandle(target);
             }
             else
             {
                 flag2 = false;
                 target = this.phase1EnlistVolatilementContainer;
             }
             try
             {
                 if (container != null)
                 {
                     this.TakeContainerLock(container, ref flag5);
                 }
                 if (flag)
                 {
                     this.transactionShim.Phase0Enlist(zero, out shim2);
                     container.Phase0EnlistmentShim = shim2;
                 }
                 if (flag2)
                 {
                     this.OletxTransactionManagerInstance.dtcTransactionManagerLock.AcquireReaderLock(-1);
                     try
                     {
                         this.transactionShim.CreateVoter(target.voterHandle, out voterBallotShim);
                         flag3 = true;
                     }
                     finally
                     {
                         this.OletxTransactionManagerInstance.dtcTransactionManagerLock.ReleaseReaderLock();
                     }
                     target.VoterBallotShim = voterBallotShim;
                 }
                 if (delayCommit)
                 {
                     if (flag)
                     {
                         this.phase0EnlistVolatilementContainerList.Add(container);
                     }
                     container.AddDependentClone();
                     return container;
                 }
                 if (flag2)
                 {
                     this.phase1EnlistVolatilementContainer = target;
                 }
                 target.AddDependentClone();
                 return target;
             }
             catch (COMException exception)
             {
                 OletxTransactionManager.ProxyException(exception);
                 throw;
             }
             return container3;
         }
     }
     finally
     {
         if (container != null)
         {
             this.ReleaseContainerLock(container, ref flag5);
         }
         if ((zero != IntPtr.Zero) && (container.Phase0EnlistmentShim == null))
         {
             HandleTable.FreeHandle(zero);
         }
         if ((!flag3 && (target != null)) && ((target.voterHandle != IntPtr.Zero) && flag2))
         {
             HandleTable.FreeHandle(target.voterHandle);
         }
     }
     return container3;
 }
 private void TakeContainerLock(OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer, ref bool phase0ContainerLockAcquired)
 {
     if (!phase0ContainerLockAcquired)
     {
         Monitor.Enter(localPhase0VolatileContainer);
         phase0ContainerLockAcquired = true;
     }
 }
 private void ReleaseContainerLock(OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer, ref bool phase0ContainerLockAcquired)
 {
     if (phase0ContainerLockAcquired)
     {
         Monitor.Exit(localPhase0VolatileContainer);
         phase0ContainerLockAcquired = false;
     }
 }
 internal IPromotedEnlistment CommonEnlistVolatile(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction)
 {
     OletxVolatileEnlistment enlistment = null;
     bool flag2 = false;
     bool flag = false;
     OletxPhase0VolatileEnlistmentContainer target = null;
     OletxPhase1VolatileEnlistmentContainer container = null;
     IntPtr zero = IntPtr.Zero;
     IVoterBallotShim voterBallotShim = null;
     IPhase0EnlistmentShim shim = null;
     bool flag3 = false;
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         lock (this)
         {
             enlistment = new OletxVolatileEnlistment(enlistmentNotification, enlistmentOptions, oletxTransaction);
             if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
             {
                 if (this.phase0EnlistVolatilementContainerList == null)
                 {
                     this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                 }
                 if (this.phase0EnlistVolatilementContainerList.Count == 0)
                 {
                     target = new OletxPhase0VolatileEnlistmentContainer(this);
                     flag = true;
                 }
                 else
                 {
                     target = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;
                     if (!target.NewEnlistmentsAllowed)
                     {
                         target = new OletxPhase0VolatileEnlistmentContainer(this);
                         flag = true;
                     }
                     else
                     {
                         flag = false;
                     }
                 }
                 if (flag)
                 {
                     zero = HandleTable.AllocHandle(target);
                 }
             }
             else if (this.phase1EnlistVolatilementContainer == null)
             {
                 flag2 = true;
                 container = new OletxPhase1VolatileEnlistmentContainer(this) {
                     voterHandle = HandleTable.AllocHandle(container)
                 };
             }
             else
             {
                 flag2 = false;
                 container = this.phase1EnlistVolatilementContainer;
             }
             try
             {
                 if (flag)
                 {
                     lock (target)
                     {
                         this.transactionShim.Phase0Enlist(zero, out shim);
                         target.Phase0EnlistmentShim = shim;
                     }
                 }
                 if (flag2)
                 {
                     this.transactionShim.CreateVoter(container.voterHandle, out voterBallotShim);
                     flag3 = true;
                     container.VoterBallotShim = voterBallotShim;
                 }
                 if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                 {
                     target.AddEnlistment(enlistment);
                     if (flag)
                     {
                         this.phase0EnlistVolatilementContainerList.Add(target);
                     }
                     return enlistment;
                 }
                 container.AddEnlistment(enlistment);
                 if (flag2)
                 {
                     this.phase1EnlistVolatilementContainer = container;
                 }
                 return enlistment;
             }
             catch (COMException exception)
             {
                 OletxTransactionManager.ProxyException(exception);
                 throw;
             }
             return enlistment;
         }
     }
     finally
     {
         if ((zero != IntPtr.Zero) && (target.Phase0EnlistmentShim == null))
         {
             HandleTable.FreeHandle(zero);
         }
         if ((!flag3 && (container != null)) && ((container.voterHandle != IntPtr.Zero) && flag2))
         {
             HandleTable.FreeHandle(container.voterHandle);
         }
     }
     return enlistment;
 }
Example #8
0
        internal OletxVolatileEnlistmentContainer AddDependentClone( bool delayCommit )
        {
            IPhase0EnlistmentShim phase0Shim = null;
            IVoterBallotShim voterShim = null;
            bool needVoterEnlistment = false;
            bool needPhase0Enlistment = false;
            OletxVolatileEnlistmentContainer returnValue = null;
            OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer = null;
            OletxPhase1VolatileEnlistmentContainer localPhase1VolatileContainer = null;
            bool enlistmentSucceeded = false;
            bool phase0ContainerLockAcquired = false;

            IntPtr phase0Handle = IntPtr.Zero;

            // Yes, we are talking to the proxy while holding the lock on the RealOletxTransaction.
            // If we don't then things get real sticky with other threads allocating containers.
            // We only do this the first time we get a depenent clone of a given type (delay vs. non-delay).
            // After that, we don't create a new container, except for Phase0 if we need to create one
            // for a second wave.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                lock ( this )
                {
                    if ( delayCommit )
                    {
                        if ( null == this.phase0EnlistVolatilementContainerList )
                        {
                            // Not using a MemoryBarrier because all access to this member variable is under a lock of the
                            // object.
                            this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                        }
                        // We may have failed the proxy enlistment for the first container, but we would have
                        // allocated the list.  That is why we have this check here.
                        if ( 0 == this.phase0EnlistVolatilementContainerList.Count )
                        {
                            localPhase0VolatileContainer = new OletxPhase0VolatileEnlistmentContainer( this );
                            needPhase0Enlistment = true;
                        }
                        else
                        {
                            localPhase0VolatileContainer = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;

                            if (localPhase0VolatileContainer != null)
                            {
                                //CSDMain 91509 - We now synchronize this call with the shim notification trying to call Phase0Request on this container
                                TakeContainerLock(localPhase0VolatileContainer, ref phase0ContainerLockAcquired);
                            }

                            if ( ! localPhase0VolatileContainer.NewEnlistmentsAllowed )
                            {
                                //It is OK to release the lock at this time because we are creating a new container that has not yet 
                                //been enlisted with DTC. So there is no ---- to worry about
                                ReleaseContainerLock(localPhase0VolatileContainer, ref phase0ContainerLockAcquired);

                                localPhase0VolatileContainer = new OletxPhase0VolatileEnlistmentContainer( this );
                                needPhase0Enlistment = true;
                            }
                            else
                            {
                                needPhase0Enlistment = false;
                            }
                        }
                        
                        if ( needPhase0Enlistment )
                        {
                            // We need to create a VoterNotifyShim if native threads are not allowed to enter managed code.
                            phase0Handle = HandleTable.AllocHandle( localPhase0VolatileContainer );
                        }
                    }

                    else // ! delayCommit
                    {
                        if ( null == this.phase1EnlistVolatilementContainer )
                        {
                            localPhase1VolatileContainer = new OletxPhase1VolatileEnlistmentContainer( this );
                            needVoterEnlistment = true;

                            // We need to create a VoterNotifyShim.
                            localPhase1VolatileContainer.voterHandle = 
                                HandleTable.AllocHandle( localPhase1VolatileContainer );
                        }
                        else
                        {
                            needVoterEnlistment = false;
                            localPhase1VolatileContainer = this.phase1EnlistVolatilementContainer;
                        }
                    }

                    try
                    {
                        //At this point, we definitely need the lock on the phase0 container so that it doesnt ---- with shim notifications from unmanaged code
                        //corrupting state while we are in the middle of an AddDependentClone processing
                        if (localPhase0VolatileContainer != null)
                        {
                            TakeContainerLock(localPhase0VolatileContainer, ref phase0ContainerLockAcquired);
                        }

                        // If enlistDuringPrepareRequired is true, we need to ask the proxy to create a Phase0 enlistment.
                        if ( needPhase0Enlistment )
                        {
                            // We need to use shims if native threads are not allowed to enter managed code.
                            this.transactionShim.Phase0Enlist(
                                phase0Handle,
                                out phase0Shim );
                            localPhase0VolatileContainer.Phase0EnlistmentShim = phase0Shim;
                        }

                        if ( needVoterEnlistment )
                        {
                            // We need to use shims if native threads are not allowed to enter managed code.
                            OletxTransactionManagerInstance.dtcTransactionManagerLock.AcquireReaderLock( -1 );
                            try
                            {
                                this.transactionShim.CreateVoter(
                                    localPhase1VolatileContainer.voterHandle,
                                    out voterShim );

                                enlistmentSucceeded = true;
                            }
                            finally
                            {
                                OletxTransactionManagerInstance.dtcTransactionManagerLock.ReleaseReaderLock();
                            }
                        
                            localPhase1VolatileContainer.VoterBallotShim = voterShim;
                        }

                        if ( delayCommit )
                        {
                            // if we needed a Phase0 enlistment, we need to add the container to the
                            // list.
                            if ( needPhase0Enlistment )
                            {
                                this.phase0EnlistVolatilementContainerList.Add( localPhase0VolatileContainer );
                            }
                            localPhase0VolatileContainer.AddDependentClone();                           
                            returnValue = localPhase0VolatileContainer;
                        }
                        else
                        {
                            // If we needed a voter enlistment, we need to save the container as THE
                            // phase1 container for this transaction.
                            if ( needVoterEnlistment )
                            {
                                Debug.Assert( ( null == this.phase1EnlistVolatilementContainer ),
                                    "RealOletxTransaction.AddDependentClone - phase1VolContainer not null when expected" );
                                this.phase1EnlistVolatilementContainer = localPhase1VolatileContainer;
                            }
                            localPhase1VolatileContainer.AddDependentClone();
                            returnValue = localPhase1VolatileContainer;
                        }

                    }
                    catch (COMException comException)
                    {
                        OletxTransactionManager.ProxyException( comException );
                        throw;
                    }
                }
            }
            finally
            {
                //First release the lock on the phase 0 container if it was acquired. Any work on localPhase0VolatileContainer
                //that needs its state to be consistent while processing should do so before this statement is executed.
                if (localPhase0VolatileContainer != null)
                {
                    ReleaseContainerLock(localPhase0VolatileContainer, ref phase0ContainerLockAcquired);
                }

                if ( phase0Handle != IntPtr.Zero && localPhase0VolatileContainer.Phase0EnlistmentShim == null )
                {
                    HandleTable.FreeHandle( phase0Handle );
                }
                
                if ( !enlistmentSucceeded && 
                    null != localPhase1VolatileContainer && 
                    localPhase1VolatileContainer.voterHandle != IntPtr.Zero &&
                    needVoterEnlistment )
                {
                    HandleTable.FreeHandle( localPhase1VolatileContainer.voterHandle );
                }
            }
            return returnValue;

        }
Example #9
0
        internal IPromotedEnlistment CommonEnlistVolatile(
            IEnlistmentNotificationInternal enlistmentNotification,
            EnlistmentOptions enlistmentOptions,
            OletxTransaction oletxTransaction
            )
        {
            OletxVolatileEnlistment enlistment = null;
            bool needVoterEnlistment = false;
            bool needPhase0Enlistment = false;
            OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer = null;
            OletxPhase1VolatileEnlistmentContainer localPhase1VolatileContainer = null;
            IntPtr phase0Handle = IntPtr.Zero;
            IVoterBallotShim voterShim = null;
            IPhase0EnlistmentShim phase0Shim = null;
            bool enlistmentSucceeded = false;

            // Yes, we are talking to the proxy while holding the lock on the RealOletxTransaction.
            // If we don't then things get real sticky with other threads allocating containers.
            // We only do this the first time we get a depenent clone of a given type (delay vs. non-delay).
            // After that, we don't create a new container, except for Phase0 if we need to create one
            // for a second wave.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                lock ( this )
                {
                    enlistment = new OletxVolatileEnlistment(
                        enlistmentNotification,
                        enlistmentOptions,
                        oletxTransaction
                        );

                    if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 )
                    {
                        if ( null == this.phase0EnlistVolatilementContainerList )
                        {
                            // Not using a MemoryBarrier because all access to this member variable is done when holding
                            // a lock on the object.
                            this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                        }
                        // We may have failed the proxy enlistment for the first container, but we would have
                        // allocated the list.  That is why we have this check here.
                        if ( 0 == this.phase0EnlistVolatilementContainerList.Count )
                        {
                            localPhase0VolatileContainer = new OletxPhase0VolatileEnlistmentContainer( this );
                            needPhase0Enlistment = true;
                        }
                        else
                        {
                            localPhase0VolatileContainer = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;
                            if ( ! localPhase0VolatileContainer.NewEnlistmentsAllowed )
                            {
                                localPhase0VolatileContainer = new OletxPhase0VolatileEnlistmentContainer( this );
                                needPhase0Enlistment = true;
                            }
                            else
                            {
                                needPhase0Enlistment = false;
                            }
                        }

                        if ( needPhase0Enlistment )
                        {
                            // We need to create a VoterNotifyShim if native threads are not allowed to enter managed code.
                            phase0Handle = HandleTable.AllocHandle( localPhase0VolatileContainer );
                        }
                    }
                    else  // not EDPR = TRUE - may need a voter... 
                    {
                        if ( null == this.phase1EnlistVolatilementContainer )
                        {
                            needVoterEnlistment = true;
                            localPhase1VolatileContainer = new OletxPhase1VolatileEnlistmentContainer( this );

                            // We need to create a VoterNotifyShim.
                            localPhase1VolatileContainer.voterHandle = 
                                HandleTable.AllocHandle( localPhase1VolatileContainer );
                        }
                        else
                        {
                            needVoterEnlistment = false;
                            localPhase1VolatileContainer = this.phase1EnlistVolatilementContainer;
                        }
                    }


                    try
                    {
                        // If enlistDuringPrepareRequired is true, we need to ask the proxy to create a Phase0 enlistment.
                        if ( needPhase0Enlistment )
                        {
                            lock ( localPhase0VolatileContainer )
                            {
                                transactionShim.Phase0Enlist(
                                    phase0Handle,
                                    out phase0Shim );

                                localPhase0VolatileContainer.Phase0EnlistmentShim = phase0Shim;
                            }

                        }

                        if ( needVoterEnlistment )
                        {
                            this.transactionShim.CreateVoter(
                                localPhase1VolatileContainer.voterHandle,
                                out voterShim );

                            enlistmentSucceeded = true;
                            localPhase1VolatileContainer.VoterBallotShim = voterShim;
                        }
                
                        if ( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 )
                        {
                            localPhase0VolatileContainer.AddEnlistment(
                                enlistment
                                );
                            if ( needPhase0Enlistment )
                            {
                                this.phase0EnlistVolatilementContainerList.Add( localPhase0VolatileContainer );
                            }
                        }
                        else
                        {
                            localPhase1VolatileContainer.AddEnlistment(
                                enlistment
                                );

                            if ( needVoterEnlistment )
                            {
                                Debug.Assert( ( null == this.phase1EnlistVolatilementContainer ),
                                    "RealOletxTransaction.CommonEnlistVolatile - phase1VolContainer not null when expected." );
                                this.phase1EnlistVolatilementContainer = localPhase1VolatileContainer;
                            }
                        }
                    }
                    catch (COMException comException)
                    {
                        OletxTransactionManager.ProxyException( comException );
                        throw;
                    }
                }
            }
            finally
            {
                if ( phase0Handle != IntPtr.Zero && localPhase0VolatileContainer.Phase0EnlistmentShim == null )
                {
                    HandleTable.FreeHandle( phase0Handle );
                }

                if ( !enlistmentSucceeded && 
                    null != localPhase1VolatileContainer && 
                    localPhase1VolatileContainer.voterHandle != IntPtr.Zero &&
                    needVoterEnlistment )
                {
                    HandleTable.FreeHandle( localPhase1VolatileContainer.voterHandle );
                }
            }

            return enlistment;
        }
Example #10
0
        void TakeContainerLock(OletxPhase0VolatileEnlistmentContainer localPhase0VolatileContainer, ref bool phase0ContainerLockAcquired)
        {
            if (!phase0ContainerLockAcquired)
            {
#pragma warning disable 0618
                //@
                Monitor.Enter(localPhase0VolatileContainer);
#pragma warning restore 0618
                phase0ContainerLockAcquired = true;
            }
        }
        internal OletxVolatileEnlistmentContainer AddDependentClone(bool delayCommit)
        {
            IVoterBallotShim      voterBallotShim = null;
            IPhase0EnlistmentShim shim2           = null;
            bool flag2 = false;
            bool flag  = false;
            OletxVolatileEnlistmentContainer       container3 = null;
            OletxPhase0VolatileEnlistmentContainer container  = null;
            OletxPhase1VolatileEnlistmentContainer target     = null;
            bool   flag3 = false;
            bool   flag5 = false;
            IntPtr zero  = IntPtr.Zero;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                lock (this)
                {
                    if (delayCommit)
                    {
                        if (this.phase0EnlistVolatilementContainerList == null)
                        {
                            this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                        }
                        if (this.phase0EnlistVolatilementContainerList.Count == 0)
                        {
                            container = new OletxPhase0VolatileEnlistmentContainer(this);
                            flag      = true;
                        }
                        else
                        {
                            container = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;
                            if (container != null)
                            {
                                this.TakeContainerLock(container, ref flag5);
                            }
                            if (!container.NewEnlistmentsAllowed)
                            {
                                this.ReleaseContainerLock(container, ref flag5);
                                container = new OletxPhase0VolatileEnlistmentContainer(this);
                                flag      = true;
                            }
                            else
                            {
                                flag = false;
                            }
                        }
                        if (flag)
                        {
                            zero = HandleTable.AllocHandle(container);
                        }
                    }
                    else if (this.phase1EnlistVolatilementContainer == null)
                    {
                        target             = new OletxPhase1VolatileEnlistmentContainer(this);
                        flag2              = true;
                        target.voterHandle = HandleTable.AllocHandle(target);
                    }
                    else
                    {
                        flag2  = false;
                        target = this.phase1EnlistVolatilementContainer;
                    }
                    try
                    {
                        if (container != null)
                        {
                            this.TakeContainerLock(container, ref flag5);
                        }
                        if (flag)
                        {
                            this.transactionShim.Phase0Enlist(zero, out shim2);
                            container.Phase0EnlistmentShim = shim2;
                        }
                        if (flag2)
                        {
                            this.OletxTransactionManagerInstance.dtcTransactionManagerLock.AcquireReaderLock(-1);
                            try
                            {
                                this.transactionShim.CreateVoter(target.voterHandle, out voterBallotShim);
                                flag3 = true;
                            }
                            finally
                            {
                                this.OletxTransactionManagerInstance.dtcTransactionManagerLock.ReleaseReaderLock();
                            }
                            target.VoterBallotShim = voterBallotShim;
                        }
                        if (delayCommit)
                        {
                            if (flag)
                            {
                                this.phase0EnlistVolatilementContainerList.Add(container);
                            }
                            container.AddDependentClone();
                            return(container);
                        }
                        if (flag2)
                        {
                            this.phase1EnlistVolatilementContainer = target;
                        }
                        target.AddDependentClone();
                        return(target);
                    }
                    catch (COMException exception)
                    {
                        OletxTransactionManager.ProxyException(exception);
                        throw;
                    }
                    return(container3);
                }
            }
            finally
            {
                if (container != null)
                {
                    this.ReleaseContainerLock(container, ref flag5);
                }
                if ((zero != IntPtr.Zero) && (container.Phase0EnlistmentShim == null))
                {
                    HandleTable.FreeHandle(zero);
                }
                if ((!flag3 && (target != null)) && ((target.voterHandle != IntPtr.Zero) && flag2))
                {
                    HandleTable.FreeHandle(target.voterHandle);
                }
            }
            return(container3);
        }
        internal IPromotedEnlistment CommonEnlistVolatile(IEnlistmentNotificationInternal enlistmentNotification, EnlistmentOptions enlistmentOptions, OletxTransaction oletxTransaction)
        {
            OletxVolatileEnlistment enlistment = null;
            bool flag2 = false;
            bool flag  = false;
            OletxPhase0VolatileEnlistmentContainer target    = null;
            OletxPhase1VolatileEnlistmentContainer container = null;
            IntPtr                zero            = IntPtr.Zero;
            IVoterBallotShim      voterBallotShim = null;
            IPhase0EnlistmentShim shim            = null;
            bool flag3 = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                lock (this)
                {
                    enlistment = new OletxVolatileEnlistment(enlistmentNotification, enlistmentOptions, oletxTransaction);
                    if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                    {
                        if (this.phase0EnlistVolatilementContainerList == null)
                        {
                            this.phase0EnlistVolatilementContainerList = new ArrayList(1);
                        }
                        if (this.phase0EnlistVolatilementContainerList.Count == 0)
                        {
                            target = new OletxPhase0VolatileEnlistmentContainer(this);
                            flag   = true;
                        }
                        else
                        {
                            target = this.phase0EnlistVolatilementContainerList[this.phase0EnlistVolatilementContainerList.Count - 1] as OletxPhase0VolatileEnlistmentContainer;
                            if (!target.NewEnlistmentsAllowed)
                            {
                                target = new OletxPhase0VolatileEnlistmentContainer(this);
                                flag   = true;
                            }
                            else
                            {
                                flag = false;
                            }
                        }
                        if (flag)
                        {
                            zero = HandleTable.AllocHandle(target);
                        }
                    }
                    else if (this.phase1EnlistVolatilementContainer == null)
                    {
                        flag2     = true;
                        container = new OletxPhase1VolatileEnlistmentContainer(this)
                        {
                            voterHandle = HandleTable.AllocHandle(container)
                        };
                    }
                    else
                    {
                        flag2     = false;
                        container = this.phase1EnlistVolatilementContainer;
                    }
                    try
                    {
                        if (flag)
                        {
                            lock (target)
                            {
                                this.transactionShim.Phase0Enlist(zero, out shim);
                                target.Phase0EnlistmentShim = shim;
                            }
                        }
                        if (flag2)
                        {
                            this.transactionShim.CreateVoter(container.voterHandle, out voterBallotShim);
                            flag3 = true;
                            container.VoterBallotShim = voterBallotShim;
                        }
                        if ((enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != EnlistmentOptions.None)
                        {
                            target.AddEnlistment(enlistment);
                            if (flag)
                            {
                                this.phase0EnlistVolatilementContainerList.Add(target);
                            }
                            return(enlistment);
                        }
                        container.AddEnlistment(enlistment);
                        if (flag2)
                        {
                            this.phase1EnlistVolatilementContainer = container;
                        }
                        return(enlistment);
                    }
                    catch (COMException exception)
                    {
                        OletxTransactionManager.ProxyException(exception);
                        throw;
                    }
                    return(enlistment);
                }
            }
            finally
            {
                if ((zero != IntPtr.Zero) && (target.Phase0EnlistmentShim == null))
                {
                    HandleTable.FreeHandle(zero);
                }
                if ((!flag3 && (container != null)) && ((container.voterHandle != IntPtr.Zero) && flag2))
                {
                    HandleTable.FreeHandle(container.voterHandle);
                }
            }
            return(enlistment);
        }
Example #13
0
        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"
                                              );
            }
        }