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);
        }
Example #2
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);
        }
Example #3
0
 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);
         }
     }
 }
Example #4
0
        public void ManualEnlistDistributedTransaction(ITransaction newTransaction)
        {
            Guid newTransactionGuid = Guid.Empty;

            if (null != newTransaction)
            {
                // Obtain Guid for TransactionId from ITransaction.
                XACTTRANSINFO info;
                newTransaction.GetTransactionInfo(out info);
                BOID   boid  = info.uow;
                byte[] bytes = boid.rgb;
                newTransactionGuid = new Guid(bytes);
            }

            EnlistDistributedTransaction(newTransaction, newTransactionGuid);

            if (null != newTransaction)
            {
                _transaction = new TransactionWrapper(newTransaction); // cache ITransaction
            }
        }
        // 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 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 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);
                }
            }
        }
Example #8
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);
            }
        }
Example #9
0
        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);
        }
Example #10
0
 public void Abort(ref BOID pboidReason, int fRetaining, int fAsync)
 {
     throw new NotImplementedException();
 }