3.1.4.10 R_MoveMessage (Opnum 10)

The R_MoveMessage method moves a message from one queue to another.<20> The source and destination queues MUST be related as follows:

  • The source is a queue, and the destination is a subqueue of the source queue, or

  • The destination is a queue, and the source is a subqueue of the destination queue, or

  • The source and destination are two subqueues of the same queue.

     HRESULT R_MoveMessage(
       [in] handle_t hBind,
       [in] QUEUE_CONTEXT_HANDLE_NOSERIALIZE phContextFrom,
       [in] ULONGLONG ullContextTo,
       [in] ULONGLONG LookupId,
       [in] XACTUOW* pTransactionId
     );
    

hBind: MUST be an RPC binding handle parameter, as specified in [MS-RPCE] section 2.

phContextFrom: MUST be set by the client to a QUEUE_CONTEXT_HANDLE_NOSERIALIZE (section 2.2.4.1) handle representing the source queue. The handle MUST have been returned by the server in the pphQueue output parameter of a prior call to the R_OpenQueue (Opnum 2) (section 3.1.4.2) method with the dwAccess parameter set to RECEIVE_ACCESS and MUST NOT have been closed through a prior call to the R_CloseQueue (Opnum 3) (section 3.1.4.3) method. This value MUST NOT be NULL.

ullContextTo: MUST be set by the client to a QUEUE_CONTEXT_HANDLE_NOSERIALIZE handle representing the destination queue. The handle MUST have been returned by the server in the pMoveContext output parameter of a prior call to the R_OpenQueueForMove (Opnum 11) (section 3.1.4.11) method and MUST NOT have been closed through a prior call to the R_CloseQueue method. This value MUST NOT be NULL.

LookupId: MUST be set by the client to the lookup identifier of the message to be moved.

pTransactionId: MUST be set by the client as a pointer to a transaction identifier or to a zero value XACTUOW ([MS-MQMQ] section 2.2.18.1.8) structure. If the destination queue is not a transactional queue, this value MUST be a pointer to a zero value XACTUOW structure. If the value of the field is not zero, the transaction identifier MUST have been registered with the server through a prior call to the R_QMEnlistRemoteTransaction (Opnum 12) (section 3.1.4.12) method and MUST NOT be NULL.

Return Values: On success, this method MUST return MQ_OK (0x00000000).

If an error occurs, the server MUST return a failure HRESULT, and the client treat all failure HRESULTs identically.

Exceptions Thrown:

No exceptions are thrown except those thrown by the underlying RPC protocol, as specified in [MS-RPCE].

The R_MoveMessage method provides both transactional and non-transactional operations. When using a transaction identifier, this method provisionally moves a message from the source queue to the destination queue, pending notification of the transaction outcome. See section 3.1.6. The non-transactional operation moves a message from the source queue to the destination queue without enlisting in a transaction.

When processing this call, the server MUST:

  • Find the corresponding OpenQueueDescriptor ADM element instance for the source queue by comparing the phContextFrom parameter with the  Handle ADM attribute for all OpenQueueDescriptor ADM element instances maintained by the local QueueManager ADM element instance, and then declare and set iSourceQueueDescriptor to the instance.

  • If not found, return a failure HRESULT.

  • Find the corresponding OpenQueueDescriptor ADM element instance for the destination queue by comparing the ullContextTo parameter with the Handle ADM attribute for all OpenQueueDescriptor ADM element instances maintained by the local QueueManager ADM element instance, and then declare and set iDestinationQueueDescriptor to that instance.

  • If not found or if iDestinationQueueDescriptor.AccessType is not QueueAccessType.MoveAccess, then return MQ_ERROR_INVALID_HANDLE (0xC00E0007).

  • If none of the following conditions is met, return STATUS_INVALID_PARAMETER (0xC000000D):

    • iSourceQueueDescriptor is part of the collection iDestinationQueueDescriptor.QueueReference.SubqueueCollection.

    • iDestinationQueueDescriptor is part of the collection iSourceQueueDescriptor.QueueReference.SubqueueCollection.

    • iSourceQueueDescriptor.QueueReference.Pathname and iDestinationQueueDescriptor.QueueReference.Pathname have the same parent queue pathname. The parent queue pathname MUST be formed by removing the subqueue portion from the pathname and the preceding ";", as specified in [MS-MQMQ] section 2.1.1.

  • If the method is provided with a nonzero pTransactionId parameter and if iDestinationQueueDescriptor.QueueReference.Transactional is False, return MQ_ERROR_TRANSACTION USAGE (0xC00E0050).

  • Find the corresponding Message ADM element instance by comparing PendingRequestEntry.LookupIdentifier with MessagePosition.MessageReference.Identifier in the iSourceQueueDescriptor.QueueReference.MessagePositionCollection, and then declare and set iFoundMessage to that instance.

  • If not found, then return MQ_ERROR_MESSAGE_NOT_FOUND (0xC00E0088).

  • If the message is already part of another transaction, return MQ_ERROR_MESSAGE_LOCKED_UNDER_TRANSACTION (0xC00E009C).

  • If the method is provided with a nonzero pTransactionId parameter, find the corresponding Transaction ADM element instance by comparing the pTransactionId parameter with the Identifier ADM attribute for all Transaction ADM element instances in the TransactionCollection ADM attribute of the local QueueManager ADM element instance, and then declare and set iFoundTransaction to that instance.

  • If not found, return MQ_ERROR_TRANSACTION_SEQUENCE (0xC00E0051).

  • Generate a Move Message ([MS-MQDMPR] section 3.1.7.1.16) event with the following inputs:

    • iMessagePos := iFoundMessage.MessagePositionReference.

    • iTargetQueue := iDestinationQueueDescriptor.QueueReference.

    • If there is a transaction, iTransaction := iFoundTransaction.

  • Return MQ_OK (0x00000000).