3.1.5.3 rpc_ACReceiveMessageEx (Opnum 2)

A client calls rpc_ACReceiveMessageEx to peek or receive a message from a message queue.

 HRESULT rpc_ACReceiveMessageEx(
   [in] handle_t hBind,
   [in] DWORD hQMContext,
   [in, out] struct CACTransferBufferV2* ptb
 );

hBind: MUST be set to an RPC binding handle as described in [MS-RPCE] section 2.

hQMContext: A queue context value obtained from the pdwQMContext parameter of rpc_QMOpenQueueInternal. The queue MUST have been opened with MQ_PEEK_ACCESS or MQ_RECEIVE_ACCESS as the dwDesiredAccess parameter when rpc_QMOpenQueueInternal was called. Prior to this method being invoked, the queue MUST NOT have been deleted, and the queue handle for the open queue MUST NOT have been closed.

ptb: MUST NOT be NULL. The ptb parameter points to a CACTransferBufferV2 (section 2.2.3.3) structure. Constraints for the member fields are defined following. In the sections following, "ptb.old" is used as shorthand to refer to the CACTransferBufferOld member of the CACTransferBufferV2 structure.

ptb.old.uTransferType MUST be CACTB_RECEIVE (0x00000001).

ptb.old.Receive.Action MUST contain one of the following values: 0x00000000 (MQ_ACTION_RECEIVE), 0x80000000 (MQ_ACTION_PEEK_CURRENT) or 0x80000001 (MQ_ACTION_PEEK_NEXT).

On input, ptb.old.Receive.Cursor can be 0x00000000, in which case no cursor is associated with the receive operation. Otherwise, ptb.old.Receive.Cursor MUST contain a Cursor Handle obtained from the pcc.hCursor parameter of rpc_ACCreateCursorEx. The cursor MUST have been created using the queue handle associated with the queue context value provided for the hQMContext parameter, and the cursor MUST NOT have been closed prior to this call. On output, the value of ptb.old.Receive.Cursor MUST be the same as it was on input.

ptb.old.Receive.ulResponseFormatNameLen is used for RPC marshaling of the ppResponseFormatName buffer. On input, the client MUST set this value to the minimum of pulResponseFormatNameLenProp and 1024 bytes. If ptb.old.Receive.ppResponseFormatName is NULL, this value MUST be 0x00000000. On output, the server MUST set this value to the minimum of ulResponseFormatNameLen and pulResponseFormatNameLenProp.

On input, ptb.old.Receive.pulResponseFormatNameLenProp indicates the Unicode character length of the buffer contained in ppResponseFormatName. On output, the server MUST set this value to indicate the full length of the response queue format name associated with the message being retrieved.

On input, ptb.old.Receive.ppResponseFormatName can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message and prior to filling the buffer, the server MUST verify that the pulResponseFormatNameLenProp field indicates that the buffer is large enough to contain the response queue format name for the retrieved message.

ptb.old.Receive.ulAdminFormatNameLen is used for RPC marshaling of the ppAdminFormatName buffer. On input, the client MUST set this value to the minimum of pulAdminFormatNameLenProp and 1024 bytes. If ptb.old.Receive.ppAdminFormatName is NULL, this value MUST be 0x00000000. On output, the server MUST set this value to the minimum of ulAdminFormatNameLen and pulAdminFormatNameLenProp.

On input, ptb.old.Receive.pulAdminFormatNameLenProp indicates the Unicode character length of the buffer contained in ppAdminFormatName. On output, the server MUST set this value to indicate the full length of the administration queue format name associated with the message being retrieved.

On input, ptb.old.Receive.ppAdminFormatName can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message and prior to filling the buffer, the server MUST verify that the pulAdminFormatNameLenProp field indicates that the buffer is large enough to contain the administration queue format name for the retrieved message.

ptb.old.Receive.ulDestFormatNameLen is used for RPC marshaling of the ppDestFormatName buffer. On input, the client MUST set this value to the minimum of pulDestFormatNameLenProp and 1024 bytes. If ptb.old.Receive.ppDestFormatName is NULL, this value MUST be 0x00000000. On output, the server MUST set this value to the minimum of ulDestFormatNameLen and pulDestFormatNameLenProp.

On input, ptb.old.Receive.pulDestFormatNameLenProp indicates the Unicode character length of the buffer contained in ppDestFormatName. On output, the server MUST set this value to indicate the full length of the destination queue format name associated with the message being retrieved.

On input, ptb.old.Receive.ppDestFormatName can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message and prior to filling the buffer, the server MUST verify that the pulDestFormatNameLenProp field indicates that the buffer is large enough to contain the destination queue format name for the retrieved message.

ptb.old.Receive.ulOrderingFormatNameLen is used for RPC marshaling of the ppOrderingFormatName buffer. On input, the client MUST set this value to the minimum of pulOrderingFormatNameLenProp and 1024 bytes. If ptb.old.Receive.ppOrderingFormatName is NULL, this value MUST be 0x00000000. On output, the server MUST set this value to the minimum of ulOrderingFormatNameLen and pulOrderingFormatNameLenProp.

On input, ptb.old.Receive.pulOrderingFormatNameLenProp indicates the Unicode character length of the buffer contained in ppOrderingFormatName. On output, the server MUST set this value to indicate the full length of the order queue format name associated with the message being retrieved.

On input, ptb.old.Receive.ppOrderingFormatName can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message and prior to filling the buffer, the server MUST verify that the pulOrderingFormatNameLenProp field indicates that the buffer is large enough to contain the order queue format name for the retrieved message.

On input, ptb.old.ppBody can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message, prior to filling the buffer, the server MUST verify that the ulBodyBufferSizeInBytes field indicates that the buffer is large enough to contain the message body for the retrieved message. On output, the byte length of the complete body for the retrieved message MUST be returned in the pBodySize field, if it is not NULL.

On input, ptb.old.ulBodyBufferSizeInBytes MUST be 0x00000000 if ptb.old.ppBody is NULL. On output, the value of ptb.old.ulBodyBufferSizeInBytes MUST be the same as it was on input.

ptb.old.ulAllocBodyBufferInBytes is used for RPC marshaling of the ppBody buffer. If ppBody is NULL, this value MUST be 0x00000000.

On input, ptb.old.pBodySize can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message, the server MUST set this value to the byte length of the message body.

ptb.old.ulTitleBufferSizeInWCHARs is used for RPC marshaling of the ptb.old.ppTitle buffer. On input, the client MUST set this value to the minimum of pulTitleBufferSizeInWCHARs and 250. If ptb.old.ppTitle is NULL, this value MUST be 0x00000000. On output, the server MUST set this value to the minimum of ulTitleBufferSizeInWCHARs and pulTitleBufferSizeInWCHARs.

On input, ptb.old.pulTitleBufferSizeInWCHARs indicates the Unicode character length of the buffer contained in ppTitle. On output, the server MUST set this value to indicate the full length of the message label associated with the message being retrieved.

On input, ptb.old.ppTitle can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message, prior to filling the buffer, the server MUST verify that the pulTitleBufferSizeInWCHARs field indicates that the buffer is large enough to contain the message label for the retrieved message.

On input, ptb.old.ppMsgExtension can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message, prior to filling the buffer, the server MUST verify that the ptb.old.ulMsgExtensionBufferInBytes field indicates that the buffer is large enough to contain the message extension array for the retrieved message.

On input, ptb.old.ulMsgExtensionBufferInBytes MUST be 0x00000000 if ptb.old.ppMsgExtension is NULL. On output, the value of ptb.old.ulMsgExtensionBufferInBytes MUST be the same as it was on input.

On input, ptb.old.pMsgExtensionSize can be NULL, in which case it MUST be NULL on output. Otherwise, the server MUST return the full length of the retrieved message extension array in ptb.old.pMsgExtensionSize.

On input, ptb.old.pUow can be NULL, in which case the Receive operation is not associated with a transaction. Otherwise, ptb.old.pUow MUST contain a 16-byte transaction identifier which has been enlisted by a prior call to R_QMEnlistTransaction or R_QMEnlistInternalTransaction. On output, the value of ptb.old.pUow MUST be the same as it was on input.

On input, ptb.old.ppSenderID can be NULL, in which case it MUST be NULL on output. Otherwise, on successful retrieval of a message and prior to filling the buffer, the server MUST verify that the ptb.old.uSenderIDLen field indicates that the buffer is large enough to contain the sender ID buffer for the retrieved message.

On input, ptb.old.pulSenderIDLenProp can be NULL; otherwise, on output, the server MUST return the full length of the sender ID buffer for the retrieved message in ptb.old.pulSenderIDLenProp, or 0x00000000 if the value was not included in the retrieved message.

On input, ptb.old.ppwcsProvName can be NULL, in which case it MUST be NULL on output. Otherwise, prior to filling the buffer, the server MUST verify that the ptb.old.ulProvNameLen field indicates that the buffer is large enough to contain the null-terminated CSP name string. If the retrieved message does not include a CSP name buffer, the server MUST return 0x00000000 for ptb.old.pulAuthProvNameLenProp if the pulAuthProvNameLenProp pointer is not NULL.

On input, ptb.old.pulAuthProvNameLenProp can be NULL, in which case it MUST be NULL on output. Otherwise, the server MUST return the length of the CSP name buffer for the retrieved message in ptb.old.pulAuthProvNameLenProp, or 0x00000000 if the value was not included in the retrieved message.

On input, ptb.old.ppSenderCert can be NULL, in which case it MUST be NULL on output. Otherwise, prior to filling the buffer, the server MUST verify that the ptb.old.ulSenderCertLen field indicates that the buffer is large enough to contain the sender certificate buffer. If the retrieved message does not include a sender certificate, the server MUST return 0x00000000 for ptb.old.pulSenderCertLenProp if the pulSenderCertLenProp pointer is not NULL.

On input, ptb.old.pulSenderCertLenProp can be NULL, in which case it MUST be NULL on output. Otherwise, the server MUST return the length of the sender certificate buffer for the retrieved message in ptb.old.pulSenderCertLenProp, or 0x00000000 if the value is not included in the retrieved message.

On input, ptb.old.ppSymmKeys can be NULL, in which case it MUST be NULL on output. Otherwise, prior to filling the buffer, the server MUST verify that the ptb.old.ulSymmKeysSize field indicates that the buffer is large enough to contain the symmetric key buffer. If the retrieved message does not include a symmetric key, the server MUST return 0x00000000 for ptb.old.pulSymmKeysSizeProp if the pulSymmKeysSizeProp pointer is not NULL.

On input, ptb.old.pulSymmKeysSizeProp can be NULL, in which case it MUST be NULL on output. Otherwise, the server MUST return the length of the symmetric key buffer for the retrieved message in ptb.old.pulSymmKeysSizeProp or 0x00000000 if the value is not included in the retrieved message.

On input, ptb.old.ppSignature can be NULL, in which case it MUST be NULL on output. Otherwise, prior to filling the buffer, the server MUST verify that the ptb.old.ulSignatureSize field indicates that the buffer is large enough to contain the signed hash buffer. If the retrieved message does not include a signed hash, the server MUST return 0x00000000 for ptb.old.pulSignatureSizeProp if the pulSignatureSizeProp pointer is not NULL.

On input, ptb.old.pulSignatureSizeProp can be NULL, in which case it MUST be NULL on output. Otherwise, the server MUST return the length of the signed hash buffer for the retrieved message in ptb.old.pulSignatureSizeProp, or 0x00000000 if the value is not included in the retrieved message.

The following fields can be NULL, in which case the server MUST ignore them. On successful retrieval of a message, the server MUST return the appropriate message property value into each non-NULL field. See section 2.2.3.2 for definitions of these fields:

  • ptb.old.pClass

  • ptb.old.ppMessageID

  • ptb.old.ppCorrelationID

  • ptb.old.pSentTime

  • ptb.old.pArrivedTime

  • ptb.old.pPriority

  • ptb.old.pDelivery

  • ptb.old.pAcknowledge

  • ptb.old.pAuditing

  • ptb.old.pApplicationTag

  • ptb.old.pulRelativeTimeToQueue

  • ptb.old.pulRelativeTimeToLive

  • ptb.old.pTrace

  • ptb.old.pulPrivLevel

  • ptb.old.pAuthenticated

  • ptb.old.pulHashAlg

  • ptb.old.pulEncryptAlg

  • ptb.old.pulProvType

  • ptb.old.pulSenderIDType

  • ptb.old.ppSrcQMID

  • ptb.old.ppConnectorType

  • ptb.old.pulBodyType

  • ptb.old.pulVersion

  • ptb.pbFirstInXact

  • ptb.pbLastInXact

  • ptb.ppXactID

The following fields MUST be ignored by the server:

  • ptb.old.Send

  • ptb.old.CreateCursor

  • ptb.old.Receive.Asynchronous

  • ptb.old.ulAbsoluteTimeToQueue

  • ptb.old.ulRelativeTimeToLive

  • ptb.old.ulAuthLevel

  • ptb.old.bEncrypted

  • ptb.old.bAuthenticated

  • ptb.old.fDefaultProvider

Return Values:  On success, this method MUST return MQ_OK (0x00000000); otherwise, the server MUST return a failure HRESULT,<73><74> and the client MUST treat all failure HRESULTs identically. Additionally, if a failure HRESULT is returned, the client MUST disregard all out-parameter values.

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

This method is invoked at the dynamically assigned endpoint returned by the R_QMGetRTQMServerPort method when IP_HANDSHAKE (0x00000000) or IPX_HANDSHAKE (0x00000002) is the interface specified by the fIP parameter.

When processing this call, the server MUST:

  • Determine if the input parameter values violate the constraints previously specified. If an invalid parameter is detected, the server MUST take no further action and return a failure HRESULT.

  • If ptb.old.pUow is non-NULL:

    • Look up a Transaction ([MS-MQDMPR] section 3.1.1.14) ADM element instance in the server's LocalQueueManager.TransactionCollection where ptb.old.pUow matches Transaction.Identifier.

    • If no such Transaction ADM element instance exists, take no further action and return a failure HRESULT.

  • Locate a RemoteQueueProxyHandle (section 3.1.1.5) ADM element instance in the server's iRemoteQueueProxyHandleTable (section 3.1.1.4) where the Context attribute of the RemoteQueueProxyHandle ADM element instance equals hQMContext.

  • If such a RemoteQueueProxyHandle ADM element instance exists:

    • Declare iLocatedRemoteQueueProxyHandle and set it to a reference to the located RemoteQueueProxyHandle ADM element instance.

    • If ptb.old.pUow is non-NULL, take no further action and return a failure HRESULT.

    • If ptb.old.Receive.Cursor is not zero (0x00000000):

      • Locate a CursorProxy ADM element instance in iLocatedRemoteQueueProxyHandle.CursorProxyCollection where the value of the Handle attribute of the CursorProxy ADM element instance equals ptb.old.Receive.Cursor.

      • If no such CursorProxy ADM element instance exists, take no further action and return a failure HRESULT.

    • Declare iLocatedCursorProxy and set it to a reference to the located CursorProxy ADM element instance.

    • Using iLocatedRemoteQueueProxyHandle.RemoteBindingHandle, invoke the RemoteQMStartReceive method of the qm2qm RPC interface specified in [MS-MQQP] section 3.1.4.1. Specify the following input values in the REMOTEREADDESC structure ([MS-MQQP] section 2.2.2.1):

      • hRemoteQueue := iLocatedRemoteQueueProxyHandle.RemoteContext

      • hCursor := If ptb.old.Receive.Cursor is not zero (0x00000000), iLocatedCursorProxy.RemoteCursorHandle; otherwise, zero (0x00000000).

      • ulAction := ptb.old.Receive.Action

      • ulTimeout := ptb.old.Receive.RequestTimeout

      • dwpQueue := iLocatedRemoteQueueProxyHandle.RemoteContext

      • dwRequestID := Create a DWORD value to uniquely identify this invocation of the RemoteQMStartReceive method among any other simultaneous invocations occurring between this RPC client (the Message Queuing (MSMQ): Queue Manager Client Protocol server) and the Message Queuing (MSMQ): Queue Manager to Queue Manager Protocol server. This DWORD value is used to correlate the call to RemoteQMStartReceive with an associated call to RemoteQMEndReceive following.

      • Reserved := 0x00000000

      • eAckNack := RR_UNKNOWN (0x0000)

    • If RemoteQMStartReceive did not return MQ_OK (0x00000000), take no further action and return the value returned by RemoteQMStartReceive.

    • Generate the Get Message Data Element From Buffer event ([MS-MQQB] section 3.1.7.10) with the following argument:

      • iBuffer: MUST be set to REMOTEREADDESC.lpBuffer

    • Copy the contents of the returned rMessage into the ptb structure using the defined translation rules.

    • Using iLocatedRemoteQueueProxyHandle.RemoteBindingHandle, invoke the RemoteQMEndReceive method of the qm2qm RPC interface specified in [MS-MQQP] section 3.1.4.2. Specify the following parameter values:

      • pphContext := Set to the value returned from the pphContext out-parameter of RemoteQMStartReceive previously invoked.

      • dwAck := If the process of converting the content of REMOTEREADDESC.lpBuffer to a Message ([MS-MQDMPR] section 3.1.1.12) ADM element instance and then to ptb was successful, specify RR_ACK (0x00000002); otherwise, specify RR_NACK (0x00000001).

    • Take no further action and return the result of RemoteQMEndReceive.

  • Else (hQMContext did not match a RemoteQueueProxyHandle ADM element instance):

    • Locate a LocalQueueContextHandle (section 3.1.1.3) ADM element instance in the server's iLocalQueueContextHandleTable where the value of the Handle attribute of the LocalQueueContextHandle ADM element instance equals hQueue.

    •  If no such LocalQueueContextHandle ADM element instance exists, take no further action and return a failure HRESULT.

    • Declare iLocalQueueContextHandle and set it to a reference to the located LocalQueueContextHandle ADM element instance.

    • If the iLocalQueueContextHandle.OpenQueueDescriptorReference.AccessMode value is SendAccess, take no further action and return a failure HRESULT.

    • If the iLocalQueueContextHandle.OpenQueueDescriptorReference.AccessMode value is PeekAccess, confirm that ptb.old.Receive.Action is not MQ_ACTION_RECEIVE (0x00000000); otherwise, return a failure HRESULT.

    • If ptb.old.Receive.Cursor is not zero (0x00000000):

      • Locate a Cursor ([MS-MQDMPR] section 3.2) ADM element instance in iLocalQueueContextHandle.OpenQueueDescriptorReference.CursorCollection where the value of the Handle attribute of the Cursor ADM element instance equals ptb.old.Receive.Cursor.

      • If no such Cursor ADM element instance exists, take no further action and return a failure HRESULT.

    • If ptb.old.Receive.Action is MQ_ACTION_RECEIVE (0x00000000):

      • Generate a Dequeue Message ([MS-MQDMPR] section 3.1.7.1.10) event with the following argument values:

        • iQueueDesc := iLocalQueueContextHandle.OpenQueueDescriptorReference

        • iTimeout := ptb.old.Receive.RequestTimeout

        • iCursor := If ptb.old.Receive.Cursor is not zero, the Cursor ADM element instance resolved preceding; otherwise, this optional argument is not specified.

        • iTransaction := If ptb.old.pUow is non-NULL, the Transaction ADM element instance resolved preceding; otherwise, this optional argument is not specified.

        • iTag := Optional argument not specified.

        • iTwoPhaseRead := False

      • If the rStatus return value from the Dequeue Message event is not MQ_OK (0x00000000), take no further action and return rStatus.

      • Copy the contents of the rMessage return value from the Dequeue Message event to the ptb structure using the defined translation rules.

      • Take no further action and return MQ_OK (0x00000000).

    • Else, if ptb.old.Receive.Action is MQ_ACTION_PEEK_CURRENT (0x80000000):

      • Generate a Peek Message ([MS-MQDMPR] section 3.1.7.1.15) event with the following argument values:

        • iQueueDesc := iLocalQueueContextHandle.OpenQueueDescriptorReference

        • iTimeout := ptb.old.Receive.RequestTimeout

        • iCursor := If ptb.old.Receive.Cursor is not zero, the Cursor ADM element instance resolved preceding; otherwise, this optional argument is not specified.

      • If the rStatus return value from the Peek Message event is not MQ_OK (0x00000000), take no further action and return rStatus.

      • Copy the contents of the rMessage return value from the Peek Message event to the ptb structure using the defined translation rules.

      • Take no further action and return MQ_OK (0x00000000).

    • Else, if ptb.old.Receive.Action is MQ_ACTION_PEEK_NEXT (0x80000001):

      • Generate a Peek Next Message ([MS-MQDMPR] section 3.1.7.1.14) event with the following argument values:

        • iQueueDesc := iLocalQueueContextHandle.OpenQueueDescriptorReference

        • iTimeout := ptb.old.Receive.RequestTimeout

        • iCursor := If ptb.old.Receive.Cursor is not zero, the Cursor ADM element instance resolved preceding; otherwise, this optional argument is not specified.

      • If the rStatus return value from the Peek Next Message event is not MQ_OK (0x00000000), take no further action and return rStatus.

      • Copy the contents of the rMessage return value from the Peek Next Message event to the ptb structure using the defined translation rules.