unsafe int PeekLockCore(MsmqQueueHandle handle, MsmqInputMessage message, TimeSpan timeout)
        {
            int retCode = 0;
            ITransaction internalTrans;

            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);

            IntPtr nativePropertiesPointer = message.Pin();
            try
            {
                bool receivedMessage = false;

                while (!receivedMessage)
                {
                    retCode = UnsafeNativeMethods.MQBeginTransaction(out internalTrans);
                    if (retCode != 0)
                    {
                        return retCode;
                    }

                    int timeoutInMilliseconds = TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime());

                    // no timeout interval if timeout has been set to 0 otherwise a minimum of 100
                    int timeoutIntervalInMilliseconds = (timeoutInMilliseconds == 0) ? 0 : 100;

                    // receive until timeout but let go of receive lock for other contenders periodically
                    while (true)
                    {
                        lock (this.receiveLock)
                        {
                            retCode = UnsafeNativeMethods.MQReceiveMessage(handle.DangerousGetHandle(), timeoutIntervalInMilliseconds,
                                        UnsafeNativeMethods.MQ_ACTION_RECEIVE, nativePropertiesPointer, null, IntPtr.Zero, IntPtr.Zero, internalTrans);
                            if (retCode == UnsafeNativeMethods.MQ_ERROR_IO_TIMEOUT)
                            {
                                // keep trying until we timeout
                                timeoutInMilliseconds = TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime());
                                if (timeoutInMilliseconds == 0)
                                {
                                    return retCode;
                                }
                            }
                            else if (retCode != 0)
                            {
                                BOID boid = new BOID();
                                internalTrans.Abort(
                                    ref boid, // pboidReason
                                    0,  // fRetaining
                                    0   // fAsync
                                    );

                                return retCode;
                                // we don't need to release the ITransaction as MSMQ does not increment the ref counter
                                // in MQBeginTransaction
                            }
                            else
                            {
                                // we got a message within the specified time out
                                break;
                            }
                        }
                    }

                    TransactionLookupEntry entry;

                    lock (this.internalStateLock)
                    {
                        if (!this.lockMap.TryGetValue(message.LookupId.Value, out entry))
                        {
                            this.lockMap.Add(message.LookupId.Value, new TransactionLookupEntry(message.LookupId.Value, internalTrans));
                            receivedMessage = true;
                        }
                        else
                        {
                            // this was a message that was in the process of being handed off
                            // from some app trans to some internal MSMQ transaction
                            // and we grabbed it before the Abort() could finish
                            // need to be a good citizen and finish that Abort() job for it
                            entry.MsmqInternalTransaction = internalTrans;
                        }
                    }
                }
            }
            finally
            {
                message.Unpin();
            }

            return retCode;
        }
        // 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 UnlockMessage(long lookupId, TimeSpan timeout)
        {
            TransactionLookupEntry entry;

            lock (this.internalStateLock)
            {
                if (this.lockMap.TryGetValue(lookupId, out entry))
                {
                    if (entry.MsmqInternalTransaction != null)
                    {
                        BOID boid = new BOID();

                        entry.MsmqInternalTransaction.Abort(
                            ref boid, // pboidReason
                            0,  // fRetaining
                            0   // fAsync
                            );
                    }
                    this.lockMap.Remove(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;
        }
        // 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);
                }
            }
        }
 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 UnlockMessage(long lookupId, TimeSpan timeout)
 {
     lock (this.internalStateLock)
     {
         TransactionLookupEntry entry;
         if (this.lockMap.TryGetValue(lookupId, out entry))
         {
             if (entry.MsmqInternalTransaction != null)
             {
                 BOID pboidReason = new BOID();
                 entry.MsmqInternalTransaction.Abort(ref pboidReason, 0, 0);
             }
             this.lockMap.Remove(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;
 }
 private int PeekLockCore(MsmqQueueHandle handle, MsmqInputMessage message, TimeSpan timeout)
 {
     int num = 0;
     TimeoutHelper helper = new TimeoutHelper(timeout);
     IntPtr properties = message.Pin();
     try
     {
         bool flag = false;
         while (!flag)
         {
             ITransaction transaction;
             bool flag2;
             object obj2;
             num = UnsafeNativeMethods.MQBeginTransaction(out transaction);
             if (num != 0)
             {
                 return num;
             }
             int num3 = (TimeoutHelper.ToMilliseconds(helper.RemainingTime()) == 0) ? 0 : 100;
         Label_0045:
             flag2 = false;
             try
             {
                 Monitor.Enter(obj2 = this.receiveLock, ref flag2);
                 num = UnsafeNativeMethods.MQReceiveMessage(handle.DangerousGetHandle(), num3, 0, properties, null, IntPtr.Zero, IntPtr.Zero, transaction);
                 if (num == -1072824293)
                 {
                     if (TimeoutHelper.ToMilliseconds(helper.RemainingTime()) == 0)
                     {
                         return num;
                     }
                     goto Label_0045;
                 }
                 if (num != 0)
                 {
                     BOID pboidReason = new BOID();
                     transaction.Abort(ref pboidReason, 0, 0);
                     return num;
                 }
             }
             finally
             {
                 if (flag2)
                 {
                     Monitor.Exit(obj2);
                 }
             }
             lock (this.internalStateLock)
             {
                 TransactionLookupEntry entry;
                 if (!this.lockMap.TryGetValue(message.LookupId.Value, out entry))
                 {
                     this.lockMap.Add(message.LookupId.Value, new TransactionLookupEntry(message.LookupId.Value, transaction));
                     flag = true;
                 }
                 else
                 {
                     entry.MsmqInternalTransaction = transaction;
                 }
                 continue;
             }
         }
     }
     finally
     {
         message.Unpin();
     }
     return num;
 }