internal void DropOrRejectReceivedMessage(MsmqQueue queue, MsmqMessageProperty messageProperty, bool reject)
 {
     if (this.Transactional)
     {
         TryAbortTransactionCurrent();
         IPostRollbackErrorStrategy  strategy = new SimplePostRollbackErrorStrategy(messageProperty.LookupId);
         MsmqQueue.MoveReceiveResult unknown  = MsmqQueue.MoveReceiveResult.Unknown;
         do
         {
             using (MsmqEmptyMessage message = new MsmqEmptyMessage())
             {
                 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                 {
                     unknown = queue.TryReceiveByLookupId(messageProperty.LookupId, message, MsmqTransactionMode.CurrentOrThrow);
                     if ((MsmqQueue.MoveReceiveResult.Succeeded == unknown) && reject)
                     {
                         queue.MarkMessageRejected(messageProperty.LookupId);
                     }
                     scope.Complete();
                 }
             }
             if (unknown == MsmqQueue.MoveReceiveResult.Succeeded)
             {
                 MsmqDiagnostics.MessageConsumed(this.instanceId, messageProperty.MessageId, Msmq.IsRejectMessageSupported && reject);
             }
         }while ((unknown == MsmqQueue.MoveReceiveResult.MessageLockedUnderTransaction) && strategy.AnotherTryNeeded());
     }
     else
     {
         MsmqDiagnostics.MessageConsumed(this.instanceId, messageProperty.MessageId, false);
     }
 }
        public void DeleteMessage(long lookupId, TimeSpan timeout)
        {
            // operations on the lock subqueue need to be protected from ---- with close
            MoveReceiveResult          receiveResult;
            IPostRollbackErrorStrategy postRollBack = new SimplePostRollbackErrorStrategy(lookupId);

            do
            {
                using (MsmqEmptyMessage emptyMessage = new MsmqEmptyMessage())
                {
                    receiveResult = this.lockQueueForReceive.TryReceiveByLookupId(lookupId, emptyMessage, MsmqTransactionMode.CurrentOrNone);
                }

                if (receiveResult != MsmqQueue.MoveReceiveResult.MessageLockedUnderTransaction)
                {
                    break;
                }

                // We could have failed because of ---- with transaction.abort() for the transaction
                // that had this message locked previously. We will retry in these cases.
            } while (postRollBack.AnotherTryNeeded());

            // We could have failed because of
            //  a) failure in the underlying queue manager
            //  b) expiration of the native message timer
            //  c) ---- with Channel.Close()
            // ..not much we can do in any of these cases
            if (receiveResult != MoveReceiveResult.Succeeded)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MsmqReceiveContextMessageNotReceived, lookupId.ToString(CultureInfo.InvariantCulture))));
            }
        }
 internal void DropOrRejectReceivedMessage(MsmqQueue queue, MsmqMessageProperty messageProperty, bool reject)
 {
     if (this.Transactional)
     {
         TryAbortTransactionCurrent();
         IPostRollbackErrorStrategy strategy = new SimplePostRollbackErrorStrategy(messageProperty.LookupId);
         MsmqQueue.MoveReceiveResult unknown = MsmqQueue.MoveReceiveResult.Unknown;
         do
         {
             using (MsmqEmptyMessage message = new MsmqEmptyMessage())
             {
                 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                 {
                     unknown = queue.TryReceiveByLookupId(messageProperty.LookupId, message, MsmqTransactionMode.CurrentOrThrow);
                     if ((MsmqQueue.MoveReceiveResult.Succeeded == unknown) && reject)
                     {
                         queue.MarkMessageRejected(messageProperty.LookupId);
                     }
                     scope.Complete();
                 }
             }
             if (unknown == MsmqQueue.MoveReceiveResult.Succeeded)
             {
                 MsmqDiagnostics.MessageConsumed(this.instanceId, messageProperty.MessageId, Msmq.IsRejectMessageSupported && reject);
             }
         }
         while ((unknown == MsmqQueue.MoveReceiveResult.MessageLockedUnderTransaction) && strategy.AnotherTryNeeded());
     }
     else
     {
         MsmqDiagnostics.MessageConsumed(this.instanceId, messageProperty.MessageId, false);
     }
 }
Exemple #4
0
 // WaitForMessage
 internal bool WaitForMessage(TimeSpan timeout)
 {
     using (MsmqEmptyMessage message = new MsmqEmptyMessage())
     {
         return(MsmqQueue.ReceiveResult.Timeout != this.queue.TryPeek(message, timeout));
     }
 }
Exemple #5
0
 public WaitForMessageAsyncResult(MsmqQueue msmqQueue, TimeSpan timeout, AsyncCallback callback, object state)
     : base(callback, state)
 {
     this.msmqMessage = new MsmqEmptyMessage();
     this.msmqQueue   = msmqQueue;
     this.msmqQueue.BeginPeek(this.msmqMessage, timeout, onCompleteStatic, this);
 }
        unsafe int TryRelockMessage(long lookupId)
        {
            int          retCode = 0;
            ITransaction internalTrans;

            using (MsmqEmptyMessage message = new MsmqEmptyMessage())
            {
                IntPtr nativePropertiesPointer = message.Pin();
                try
                {
                    // don't want other threads receiving the message we want to relock
                    lock (this.receiveLock)
                    {
                        MsmqQueueHandle handle = GetHandle();

                        TransactionLookupEntry entry;

                        lock (this.internalStateLock)
                        {
                            if (!this.lockMap.TryGetValue(lookupId, out entry))
                            {
                                // should never get here
                                return(retCode);
                            }

                            if (entry.MsmqInternalTransaction == null)
                            {
                                retCode = UnsafeNativeMethods.MQBeginTransaction(out internalTrans);
                                if (retCode != 0)
                                {
                                    return(retCode);
                                }

                                retCode = UnsafeNativeMethods.MQReceiveMessageByLookupId(handle, lookupId, UnsafeNativeMethods.MQ_LOOKUP_RECEIVE_CURRENT,
                                                                                         nativePropertiesPointer, null, IntPtr.Zero, internalTrans);
                                if (retCode != 0)
                                {
                                    BOID boid = new BOID();
                                    internalTrans.Abort(
                                        ref boid, // pboidReason
                                        0,        // fRetaining
                                        0         // fAsync
                                        );

                                    return(retCode);
                                }
                                entry.MsmqInternalTransaction = internalTrans;
                            }
                        }
                    }
                }
                finally
                {
                    message.Unpin();
                }
            }

            return(retCode);
        }
Exemple #7
0
        private int TryRelockMessage(long lookupId)
        {
            int num = 0;

            using (MsmqEmptyMessage message = new MsmqEmptyMessage())
            {
                IntPtr properties = message.Pin();
                try
                {
                    lock (this.receiveLock)
                    {
                        MsmqQueueHandle handle = base.GetHandle();
                        lock (this.internalStateLock)
                        {
                            TransactionLookupEntry entry;
                            if (this.lockMap.TryGetValue(lookupId, out entry))
                            {
                                ITransaction transaction;
                                if (entry.MsmqInternalTransaction != null)
                                {
                                    return(num);
                                }
                                num = UnsafeNativeMethods.MQBeginTransaction(out transaction);
                                if (num != 0)
                                {
                                    return(num);
                                }
                                num = UnsafeNativeMethods.MQReceiveMessageByLookupId(handle, lookupId, 0x40000020, properties, null, IntPtr.Zero, transaction);
                                if (num != 0)
                                {
                                    BOID pboidReason = new BOID();
                                    transaction.Abort(ref pboidReason, 0, 0);
                                    return(num);
                                }
                                entry.MsmqInternalTransaction = transaction;
                            }
                            return(num);
                        }
                        return(num);
                    }
                    return(num);
                }
                finally
                {
                    message.Unpin();
                }
            }
            return(num);
        }
Exemple #8
0
        public void DeleteMessage(long lookupId, TimeSpan timeout)
        {
            MsmqQueue.MoveReceiveResult result;
            IPostRollbackErrorStrategy  strategy = new SimplePostRollbackErrorStrategy(lookupId);

            do
            {
                using (MsmqEmptyMessage message = new MsmqEmptyMessage())
                {
                    result = this.lockQueueForReceive.TryReceiveByLookupId(lookupId, message, MsmqTransactionMode.CurrentOrNone);
                }
            }while ((result == MsmqQueue.MoveReceiveResult.MessageLockedUnderTransaction) && strategy.AnotherTryNeeded());
            if (result != MsmqQueue.MoveReceiveResult.Succeeded)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MsmqReceiveContextMessageNotReceived", new object[] { lookupId.ToString(CultureInfo.InvariantCulture) })));
            }
        }
Exemple #9
0
        internal void DropOrRejectReceivedMessage(MsmqQueue queue, MsmqMessageProperty messageProperty, bool reject)
        {
            if (this.Transactional)
            {
                TryAbortTransactionCurrent();
                IPostRollbackErrorStrategy  postRollback = new SimplePostRollbackErrorStrategy(messageProperty.LookupId);
                MsmqQueue.MoveReceiveResult result       = MsmqQueue.MoveReceiveResult.Unknown;
                do
                {
                    using (MsmqEmptyMessage emptyMessage = new MsmqEmptyMessage())
                    {
                        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                        {
                            result = queue.TryReceiveByLookupId(messageProperty.LookupId, emptyMessage, MsmqTransactionMode.CurrentOrThrow);
                            if (MsmqQueue.MoveReceiveResult.Succeeded == result && reject)
                            {
                                queue.MarkMessageRejected(messageProperty.LookupId);
                            }
                            scope.Complete();
                        }
                    }

                    if (result == MsmqQueue.MoveReceiveResult.Succeeded)
                    {
                        // If 'Reject' supported and 'Reject' requested, put reject in the trace, otherwise put 'Drop'
                        MsmqDiagnostics.MessageConsumed(instanceId, messageProperty.MessageId, (Msmq.IsRejectMessageSupported && reject));
                    }

                    if (result != MsmqQueue.MoveReceiveResult.MessageLockedUnderTransaction)
                    {
                        break;
                    }
                }while (postRollback.AnotherTryNeeded());
            }
            else
            {
                MsmqDiagnostics.MessageConsumed(instanceId, messageProperty.MessageId, false);
            }
        }
Exemple #10
0
        public void DeleteMessage(long lookupId, TimeSpan timeout)
        {
            TransactionLookupEntry entry;

            if ((Transaction.Current != null) && (Transaction.Current.TransactionInformation.Status != System.Transactions.TransactionStatus.Active))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MsmqAmbientTransactionInactive")));
            }
            lock (this.internalStateLock)
            {
                if (!this.lockMap.TryGetValue(lookupId, out entry))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MessageNotInLockedState", new object[] { lookupId })));
                }
                if (entry.MsmqInternalTransaction == null)
                {
                    this.lockMap.Remove(entry.LookupId);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MessageNotInLockedState", new object[] { lookupId })));
                }
            }
            if (Transaction.Current == null)
            {
                entry.MsmqInternalTransaction.Commit(0, 0, 0);
                lock (this.internalStateLock)
                {
                    this.lockMap.Remove(lookupId);
                    return;
                }
            }
            lock (this.receiveLock)
            {
                MsmqQueueHandle handle      = base.GetHandle();
                BOID            pboidReason = new BOID();
                entry.MsmqInternalTransaction.Abort(ref pboidReason, 0, 0);
                entry.MsmqInternalTransaction = null;
                using (MsmqEmptyMessage message = new MsmqEmptyMessage())
                {
                    int error = 0;
                    try
                    {
                        error = base.ReceiveByLookupIdCoreDtcTransacted(handle, lookupId, message, MsmqTransactionMode.CurrentOrThrow, 0x40000020);
                    }
                    catch (ObjectDisposedException exception)
                    {
                        MsmqDiagnostics.ExpectedException(exception);
                    }
                    if (error != 0)
                    {
                        if (MsmqQueue.IsErrorDueToStaleHandle(error))
                        {
                            base.HandleIsStale(handle);
                        }
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MsmqCannotReacquireLock"), error));
                    }
                }
            }
            lock (this.internalStateLock)
            {
                List <long> list;
                if (!this.dtcTransMap.TryGetValue(Transaction.Current.TransactionInformation.DistributedIdentifier, out list))
                {
                    list = new List <long>();
                    this.dtcTransMap.Add(Transaction.Current.TransactionInformation.DistributedIdentifier, list);
                    Transaction.Current.TransactionCompleted += this.transactionCompletedHandler;
                }
                list.Add(lookupId);
            }
        }
        unsafe int TryRelockMessage(long lookupId)
        {
            int retCode = 0;
            ITransaction internalTrans;

            using (MsmqEmptyMessage message = new MsmqEmptyMessage())
            {
                IntPtr nativePropertiesPointer = message.Pin();
                try
                {
                    // don't want other threads receiving the message we want to relock
                    lock (this.receiveLock)
                    {
                        MsmqQueueHandle handle = GetHandle();

                        TransactionLookupEntry entry;

                        lock (this.internalStateLock)
                        {
                            if (!this.lockMap.TryGetValue(lookupId, out entry))
                            {
                                // should never get here
                                return retCode;
                            }

                            if (entry.MsmqInternalTransaction == null)
                            {
                                retCode = UnsafeNativeMethods.MQBeginTransaction(out internalTrans);
                                if (retCode != 0)
                                {
                                    return retCode;
                                }

                                retCode = UnsafeNativeMethods.MQReceiveMessageByLookupId(handle, lookupId, UnsafeNativeMethods.MQ_LOOKUP_RECEIVE_CURRENT,
                                            nativePropertiesPointer, null, IntPtr.Zero, internalTrans);
                                if (retCode != 0)
                                {
                                    BOID boid = new BOID();
                                    internalTrans.Abort(
                                        ref boid, // pboidReason
                                        0,  // fRetaining
                                        0   // fAsync
                                        );

                                    return retCode;
                                }
                                entry.MsmqInternalTransaction = internalTrans;
                            }
                        }
                    }
                }
                finally
                {
                    message.Unpin();
                }
            }

            return retCode;
        }
 public void DeleteMessage(long lookupId, TimeSpan timeout)
 {
     TransactionLookupEntry entry;
     if ((Transaction.Current != null) && (Transaction.Current.TransactionInformation.Status != System.Transactions.TransactionStatus.Active))
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MsmqAmbientTransactionInactive")));
     }
     lock (this.internalStateLock)
     {
         if (!this.lockMap.TryGetValue(lookupId, out entry))
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MessageNotInLockedState", new object[] { lookupId })));
         }
         if (entry.MsmqInternalTransaction == null)
         {
             this.lockMap.Remove(entry.LookupId);
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MessageNotInLockedState", new object[] { lookupId })));
         }
     }
     if (Transaction.Current == null)
     {
         entry.MsmqInternalTransaction.Commit(0, 0, 0);
         lock (this.internalStateLock)
         {
             this.lockMap.Remove(lookupId);
             return;
         }
     }
     lock (this.receiveLock)
     {
         MsmqQueueHandle handle = base.GetHandle();
         BOID pboidReason = new BOID();
         entry.MsmqInternalTransaction.Abort(ref pboidReason, 0, 0);
         entry.MsmqInternalTransaction = null;
         using (MsmqEmptyMessage message = new MsmqEmptyMessage())
         {
             int error = 0;
             try
             {
                 error = base.ReceiveByLookupIdCoreDtcTransacted(handle, lookupId, message, MsmqTransactionMode.CurrentOrThrow, 0x40000020);
             }
             catch (ObjectDisposedException exception)
             {
                 MsmqDiagnostics.ExpectedException(exception);
             }
             if (error != 0)
             {
                 if (MsmqQueue.IsErrorDueToStaleHandle(error))
                 {
                     base.HandleIsStale(handle);
                 }
                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MsmqCannotReacquireLock"), error));
             }
         }
     }
     lock (this.internalStateLock)
     {
         List<long> list;
         if (!this.dtcTransMap.TryGetValue(Transaction.Current.TransactionInformation.DistributedIdentifier, out list))
         {
             list = new List<long>();
             this.dtcTransMap.Add(Transaction.Current.TransactionInformation.DistributedIdentifier, list);
             Transaction.Current.TransactionCompleted += this.transactionCompletedHandler;
         }
         list.Add(lookupId);
     }
 }
        public void DeleteMessage(long lookupId, TimeSpan timeout)
        {
            // operations on the lock subqueue need to be protected from ---- with close
            MoveReceiveResult receiveResult;
            IPostRollbackErrorStrategy postRollBack = new SimplePostRollbackErrorStrategy(lookupId);
            do
            {
                using (MsmqEmptyMessage emptyMessage = new MsmqEmptyMessage())
                {
                    receiveResult = this.lockQueueForReceive.TryReceiveByLookupId(lookupId, emptyMessage, MsmqTransactionMode.CurrentOrNone);
                }

                if (receiveResult != MsmqQueue.MoveReceiveResult.MessageLockedUnderTransaction)
                    break;

                // We could have failed because of ---- with transaction.abort() for the transaction 
                // that had this message locked previously. We will retry in these cases.
            } while (postRollBack.AnotherTryNeeded());

            // We could have failed because of
            //  a) failure in the underlying queue manager
            //  b) expiration of the native message timer
            //  c) ---- with Channel.Close()
            // ..not much we can do in any of these cases
            if (receiveResult != MoveReceiveResult.Succeeded)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MsmqReceiveContextMessageNotReceived, lookupId.ToString(CultureInfo.InvariantCulture))));
            }
        }
 public void DeleteMessage(long lookupId, TimeSpan timeout)
 {
     MsmqQueue.MoveReceiveResult result;
     IPostRollbackErrorStrategy strategy = new SimplePostRollbackErrorStrategy(lookupId);
     do
     {
         using (MsmqEmptyMessage message = new MsmqEmptyMessage())
         {
             result = this.lockQueueForReceive.TryReceiveByLookupId(lookupId, message, MsmqTransactionMode.CurrentOrNone);
         }
     }
     while ((result == MsmqQueue.MoveReceiveResult.MessageLockedUnderTransaction) && strategy.AnotherTryNeeded());
     if (result != MsmqQueue.MoveReceiveResult.Succeeded)
     {
         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(System.ServiceModel.SR.GetString("MsmqReceiveContextMessageNotReceived", new object[] { lookupId.ToString(CultureInfo.InvariantCulture) })));
     }
 }
 public WaitForMessageAsyncResult(MsmqQueue msmqQueue, TimeSpan timeout, AsyncCallback callback, object state)
     : base(callback, state)
 {
     this.msmqMessage = new MsmqEmptyMessage();
     this.msmqQueue = msmqQueue;
     this.msmqQueue.BeginPeek(this.msmqMessage, timeout, onCompleteStatic, this);
 }
 // WaitForMessage
 internal bool WaitForMessage(TimeSpan timeout)
 {
     using (MsmqEmptyMessage message = new MsmqEmptyMessage())
     {
         return (MsmqQueue.ReceiveResult.Timeout != this.queue.TryPeek(message, timeout));
     }
 }
        internal void DropOrRejectReceivedMessage(MsmqQueue queue, MsmqMessageProperty messageProperty, bool reject)
        {
            if (this.Transactional)
            {
                TryAbortTransactionCurrent();
                IPostRollbackErrorStrategy postRollback = new SimplePostRollbackErrorStrategy(messageProperty.LookupId);
                MsmqQueue.MoveReceiveResult result = MsmqQueue.MoveReceiveResult.Unknown;
                do
                {
                    using (MsmqEmptyMessage emptyMessage = new MsmqEmptyMessage())
                    {
                        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                        {
                            result = queue.TryReceiveByLookupId(messageProperty.LookupId, emptyMessage, MsmqTransactionMode.CurrentOrThrow);
                            if (MsmqQueue.MoveReceiveResult.Succeeded == result && reject)
                                queue.MarkMessageRejected(messageProperty.LookupId);
                            scope.Complete();
                        }
                    }

                    if (result == MsmqQueue.MoveReceiveResult.Succeeded)
                        // If 'Reject' supported and 'Reject' requested, put reject in the trace, otherwise put 'Drop'
                        MsmqDiagnostics.MessageConsumed(instanceId, messageProperty.MessageId, (Msmq.IsRejectMessageSupported && reject));

                    if (result != MsmqQueue.MoveReceiveResult.MessageLockedUnderTransaction)
                        break;
                }
                while (postRollback.AnotherTryNeeded());
            }
            else
            {
                MsmqDiagnostics.MessageConsumed(instanceId, messageProperty.MessageId, false);
            }
        }
        // The demand is not added now (in 4.5), to avoid a breaking change. To be considered in the next version.

        /*
         * // We demand full trust because we call code from a non-APTCA assembly.
         * // MSMQ is not enabled in partial trust, so this demand should not break customers.
         * [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
         */
        public void DeleteMessage(long lookupId, TimeSpan timeout)
        {
            TransactionLookupEntry entry;

            if (Transaction.Current != null && Transaction.Current.TransactionInformation.Status != System.Transactions.TransactionStatus.Active)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MsmqAmbientTransactionInactive)));
            }

            lock (this.internalStateLock)
            {
                if (!this.lockMap.TryGetValue(lookupId, out entry))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MessageNotInLockedState, lookupId)));
                }

                // a failed relock is the same as not having a lock
                if (entry.MsmqInternalTransaction == null)
                {
                    this.lockMap.Remove(entry.LookupId);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MessageNotInLockedState, lookupId)));
                }
            }

            if (Transaction.Current == null)
            {
                entry.MsmqInternalTransaction.Commit(
                    0,                   // fRetaining
                    0,                   // grfTC
                    0                    // grfRM
                    );

                lock (this.internalStateLock)
                {
                    this.lockMap.Remove(lookupId);
                }
            }
            else
            {
                // we don't want any thread receiving the message we are trying to re-receive in a new transaction
                lock (this.receiveLock)
                {
                    MsmqQueueHandle handle = GetHandle();

                    // abort internal transaction and re-receive in the ambient transaction
                    BOID boid = new BOID();
                    entry.MsmqInternalTransaction.Abort(
                        ref boid, // pboidReason
                        0,        // fRetaining
                        0         // fAsync
                        );
                    // null indicates that the associated internal tx was aborted and the message is now
                    // unlocked as far as the native queue manager is concerned
                    entry.MsmqInternalTransaction = null;

                    using (MsmqEmptyMessage emptyMessage = new MsmqEmptyMessage())
                    {
                        int error = 0;
                        try
                        {
                            error = base.ReceiveByLookupIdCoreDtcTransacted(handle, lookupId, emptyMessage,
                                                                            MsmqTransactionMode.CurrentOrThrow, UnsafeNativeMethods.MQ_LOOKUP_RECEIVE_CURRENT);
                        }
                        catch (ObjectDisposedException ex)
                        {
                            // ---- with Close
                            MsmqDiagnostics.ExpectedException(ex);
                        }

                        if (error != 0)
                        {
                            if (IsErrorDueToStaleHandle(error))
                            {
                                HandleIsStale(handle);
                            }

                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MsmqCannotReacquireLock), error));
                        }
                    }
                }

                List <long> transMsgs;
                lock (this.internalStateLock)
                {
                    if (!this.dtcTransMap.TryGetValue(Transaction.Current.TransactionInformation.DistributedIdentifier, out transMsgs))
                    {
                        transMsgs = new List <long>();
                        this.dtcTransMap.Add(Transaction.Current.TransactionInformation.DistributedIdentifier, transMsgs);
                        // only need to attach the tx complete handler once per transaction
                        Transaction.Current.TransactionCompleted += this.transactionCompletedHandler;
                    }
                    transMsgs.Add(lookupId);
                }
            }
        }
        // The demand is not added now (in 4.5), to avoid a breaking change. To be considered in the next version.
        /*
        // We demand full trust because we call code from a non-APTCA assembly.
        // MSMQ is not enabled in partial trust, so this demand should not break customers.
        [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
        */
        public void DeleteMessage(long lookupId, TimeSpan timeout)
        {
            TransactionLookupEntry entry;

            if (Transaction.Current != null && Transaction.Current.TransactionInformation.Status != System.Transactions.TransactionStatus.Active)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MsmqAmbientTransactionInactive)));
            }

            lock (this.internalStateLock)
            {
                if (!this.lockMap.TryGetValue(lookupId, out entry))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MessageNotInLockedState, lookupId)));
                }

                // a failed relock is the same as not having a lock
                if (entry.MsmqInternalTransaction == null)
                {
                    this.lockMap.Remove(entry.LookupId);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MessageNotInLockedState, lookupId)));
                }
            }

            if (Transaction.Current == null)
            {
                entry.MsmqInternalTransaction.Commit(
                                       0, // fRetaining
                                       0, // grfTC
                                       0 // grfRM
                                       );

                lock (this.internalStateLock)
                {
                    this.lockMap.Remove(lookupId);
                }
            }
            else
            {
                // we don't want any thread receiving the message we are trying to re-receive in a new transaction
                lock (this.receiveLock)
                {
                    MsmqQueueHandle handle = GetHandle();

                    // abort internal transaction and re-receive in the ambient transaction
                    BOID boid = new BOID();
                    entry.MsmqInternalTransaction.Abort(
                        ref boid, // pboidReason
                        0,  // fRetaining
                        0   // fAsync
                        );
                    // null indicates that the associated internal tx was aborted and the message is now
                    // unlocked as far as the native queue manager is concerned
                    entry.MsmqInternalTransaction = null;

                    using (MsmqEmptyMessage emptyMessage = new MsmqEmptyMessage())
                    {
                        int error = 0;
                        try
                        {
                            error = base.ReceiveByLookupIdCoreDtcTransacted(handle, lookupId, emptyMessage,
                                MsmqTransactionMode.CurrentOrThrow, UnsafeNativeMethods.MQ_LOOKUP_RECEIVE_CURRENT);
                        }
                        catch (ObjectDisposedException ex)
                        {
                            // ---- with Close
                            MsmqDiagnostics.ExpectedException(ex);

                        }

                        if (error != 0)
                        {
                            if (IsErrorDueToStaleHandle(error))
                            {
                                HandleIsStale(handle);
                            }

                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MsmqException(SR.GetString(SR.MsmqCannotReacquireLock), error));
                        }
                    }
                }

                List<long> transMsgs;
                lock (this.internalStateLock)
                {
                    if (!this.dtcTransMap.TryGetValue(Transaction.Current.TransactionInformation.DistributedIdentifier, out transMsgs))
                    {
                        transMsgs = new List<long>();
                        this.dtcTransMap.Add(Transaction.Current.TransactionInformation.DistributedIdentifier, transMsgs);
                        // only need to attach the tx complete handler once per transaction
                        Transaction.Current.TransactionCompleted += this.transactionCompletedHandler;
                    }
                    transMsgs.Add(lookupId);
                }
            }
        }
 private int TryRelockMessage(long lookupId)
 {
     int num = 0;
     using (MsmqEmptyMessage message = new MsmqEmptyMessage())
     {
         IntPtr properties = message.Pin();
         try
         {
             lock (this.receiveLock)
             {
                 MsmqQueueHandle handle = base.GetHandle();
                 lock (this.internalStateLock)
                 {
                     TransactionLookupEntry entry;
                     if (this.lockMap.TryGetValue(lookupId, out entry))
                     {
                         ITransaction transaction;
                         if (entry.MsmqInternalTransaction != null)
                         {
                             return num;
                         }
                         num = UnsafeNativeMethods.MQBeginTransaction(out transaction);
                         if (num != 0)
                         {
                             return num;
                         }
                         num = UnsafeNativeMethods.MQReceiveMessageByLookupId(handle, lookupId, 0x40000020, properties, null, IntPtr.Zero, transaction);
                         if (num != 0)
                         {
                             BOID pboidReason = new BOID();
                             transaction.Abort(ref pboidReason, 0, 0);
                             return num;
                         }
                         entry.MsmqInternalTransaction = transaction;
                     }
                     return num;
                 }
                 return num;
             }
             return num;
         }
         finally
         {
             message.Unpin();
         }
     }
     return num;
 }