3.1.5.2 rpc_ACSendMessageEx (Opnum 1)

A client calls the rpc_ACSendMessageEx method to place a message into a message queue for delivery.

 HRESULT rpc_ACSendMessageEx(
   [in] RPC_QUEUE_HANDLE hQueue,
   [in] struct CACTransferBufferV2* ptb,
   [in, out, unique] OBJECTID* pMessageID
 );

hQueue:  MUST be an RPC_QUEUE_HANDLE (section 2.2.1.1.2) obtained from the phQueue parameter of the rpc_QMOpenQueueInternal (section 3.1.4.17) method called with the dwDesiredAccess parameter set to MQ_SEND_ACCESS. Prior to this method being invoked, the queue MUST NOT have been deleted, and the queue handle MUST NOT have been closed.

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

ptb.old.uTransferType MUST be CACTB_SEND (0x00000000).

ptb.old.Send.pAdminQueueFormat can be NULL, in which case no administration queue format name is associated with the message. If not NULL, ptb.old.Send.pAdminQueueFormat MUST point to a QUEUE_FORMAT ([MS-MQMQ] section 2.2.7) structure.

ptb.old.Send.pResponseQueueFormat can be NULL, in which case no response queue format name is associated with the message. If not NULL, ptb.old.Send.pResponseQueueFormat MUST point to a QUEUE_FORMAT structure.

If the queue identified hQueue was opened using a direct format name, as specified in [MS-MQMQ] section 2.1.2, ptb.old.pulPrivLevel MUST be NULL or, if not NULL, MUST point to the value MQMSG_PRIV_LEVEL_NONE (0x00000000). Encryption MUST NOT be requested for queues opened with direct format name.

If the queue identified by hQueue is not an outgoing queue (rather, it is a queue which is local to the supporting server), and ptb.bEncrypted is not 0x00, the server MAY return STATUS_RETRY (0xc000022d) and take no action.<68>

ptb.old.pPriority can be NULL; otherwise, the value MUST be from 0x00 to 0x07 inclusive. If the value is NULL, the server MUST substitute the default value of 0x03.

ptb.old.pTrace can be NULL, in which case the server MUST substitute the default value of 0x00.

If ptb.old.ulAbsoluteTimeToQueue is 0x00000000, the server MUST substitute the default value of 0xffffffff.

ptb.old.ppMessageID can be NULL. If not NULL, the server MUST ignore the in-value.

ptb.old.ppConnectorType can be NULL. If NULL, then no connector type value is associated with the message.

ptb.old.pDelivery can be NULL, in which case the server MUST substitute the default value of 0x00. However, if ptb.old.pUow contains a nonzero value, the server MUST substitute the value 0x01 for ptb.old.pDelivery, since transactional messages are by definition stored as recoverable.

ptb.old.pAuditing can be NULL, in which case the server MUST substitute the default value of 0x00.

ptb.old.pClass can be NULL, in which case the server MUST substitute the default value of 0x0000. This field can be used by connector applications to produce acknowledgment messages. Typical applications will always specify MQMSG_CLASS_NORMAL (0x0000).

ptb.old.ppCorrelationID can be NULL, in which case the server MUST substitute the default value by filling the array of bytes with hexadecimal zeros (0x00).

ptb.old.pAcknowledge can be NULL, in which case the server MUST substitute the default value of 0x00.

ptb.old.pApplicationTag can be NULL, in which case the server MUST substitute the default value of 0x00000000.

ptb.old.ppTitle can be NULL, in which case the server MUST treat the value as an empty string and MUST ignore the value of ptb.old.ulTitleBufferSizeInWCHARs. If ptb.old.ppTitle is NOT NULL, the server MUST take the number of Unicode characters indicated by ptb.old.ulTitleBufferSizeInWCHARs. If ptb.old.ulTitleBufferSizeInWCHARs is greater than 250, the value MUST be truncated to 250. The server MUST null-terminate the resulting character array.

ptb.old.ppMsgExtension can be NULL, in which case no extension array is associated with the message and the server MUST ignore the value of ptb.old.ulMsgExtensionBufferInBytes. If ptb.old.ppMsgExtension is NOT NULL, the server MUST take the number of bytes indicated by ptb.old.ulMsgExtensionBufferInBytes. The buffer is an opaque array of bytes and a terminating null character is not required.

ptb.old.ppBody can be NULL, in which case no body array is associated with the message and the server MUST ignore the values of ptb.old.ulBodyBufferSizeInBytes and ptb.old.ulAllocBodyBufferInBytes. If ptb.old.ppBody is NOT NULL, the server MUST take the number of bytes indicated by ptb.old.ulBodyBufferSizeInBytes, and allocate body storage for the number of bytes indicated by ptb.old.ulAllocBodyBufferInBytes. The message body is an opaque array of bytes and a terminating null character is not required.

ptb.old.pulPrivLevel can be NULL, in which case the server MUST substitute the default value of 0x00000000.

ptb.old.pulHashAlg can be NULL if ptb.old.ulSignatureSize is 0x00000000; otherwise, it MUST be set to the hash algorithm used to produce the signature of the message, as specified in section 2.2.3.2.<69> If it is set to NULL, the server MUST substitute the value of 0x00000000.

ptb.old.pulEncryptAlg can be NULL if ptb.old.pulPrivLevel is set to NULL; otherwise, it MUST be set to the encryption algorithm associated with ptb.old.pulPrivLevel, as specified in section 2.2.3.2.<70> If it is set to NULL, the server MUST substitute the value of 0x00000000.

ptb.old.pulBodyType can be NULL, in which case the server MUST substitute the default value of 0x00000000.

ptb.old.ppSenderCert can be NULL if ptb.old.ulSenderCertLen is 0x00000000, in which case an X509 certificate for the sender is not associated with the message.

ptb.old.pulSenderIDType MUST NOT be NULL if ptb.old.uSenderIDLen is nonzero.

ptb.old.pSenderID can be NULL if ptb.old.uSenderIDLen is zero and ptb.old.pulSenderIDType is MQMSG_SENDERID_TYPE_NONE (0x00000000), in which case a SID is not associated with the message.

ptb.old.ppSymmKeys can be NULL if ptb.old.ulSymmKeysSize is zero (0x00000000), in which case an encrypted symmetric key is not associated with the message. Otherwise, ptb.old.ppSymKeys MUST contain the symmetric key used to encrypt the message body. The symmetric key MUST be encrypted with the public key of the recipient QM. The manner by which the public key for the recipient QM is obtained is beyond the scope of this network protocol.

If ptb.old.ulSignatureSize is 0x00000000: no digital signature is associated with the message.

Else, if ptb.old.ulSignatureSize is not 0x00000000:

  • If ptb.old.fDefaultProvider is 0x00000000, ptb.old.ppwcsProvName MUST NOT be NULL. If ptb.old.pulProvType is NOT NULL, it MUST specify the provider type of the CSP named by ptb.old.ppwcsProvName; otherwise, the server MUST substitute the value of 0x00000000. Note that ptb.old.ulProvNameLen is used only to affect RPC marshaling of the ptb.old.ppwcsProvName buffer. The server MUST otherwise ignore ptb.old.ulProvNameLen and treat ptb.old.ppwcsProvName as a null-terminated string.

  • If ptb.old.fDefaultProvider is not 0x00000000, ptb.old.pulProvType MUST NOT be NULL, and MUST contain PROV_RSA_FULL (0x00000001).

  • If ptb.old.pulAuthProvNameLenProp is NULL:

    • If not NULL, the ptb.old.ppSignature buffer contains a simple array of bytes containing the MSMQ 1.0 digital signature. The byte length of the buffer is indicated by ptb.old.ulSignatureSize.

  • Else, if ptb.old.pulAuthProvNameLenProp is NOT NULL:

    • If not NULL, the ptb.old.ppSignature buffer contains two distinct byte array parts. The first part MUST be ignored by the server. The second part contains an MSMQ 2.0 digital signature.

    • The byte length of the first part is indicated by subtracting the length of the second part from ptb.old.ulSignatureSize. (Thus, length( [first part] ) + length( [second part] ) = ptb.old.ulSignatureSize.)

    • The byte length of the second part is indicated by subtracting ptb.old.ulProvNameLen from ptb.old.pulAuthProvNameLenProp.

    • The second part begins immediately after the first.

The following members MUST be ignored by the server:

  • ptb.old.Receive

  • ptb.old.CreateCursor

  • ptb.old.pSentTime

  • ptb.old.pArrivedTime

  • ptb.old.pBodySize

  • ptb.old.pulTitleBufferSizeInWCHARs

  • ptb.old.pulRelativeTimeToQueue

  • ptb.old.pulRelativeTimeToLive

  • ptb.old.pulSenderIDLenProp

  • ptb.old.ulAuthLevel

  • ptb.old.pAuthenticated

  • ptb.old.bAuthenticated

  • ptb.old.pulSenderCertLenProp

  • ptb.old.pulSymmKeysSizeProp

  • ptb.old.pulSignatureSizeProp

  • ptb.old.ppSrcQMID

  • ptb.old.pMsgExtensionSize

  • ptb.old.pulVersion

  • ptb.pbFirstInXact

  • ptb.pbLastInXact

  • ptb.ppXactID

The ptb.old.pulAuthProvNameLenProp field SHOULD be interpreted as specified in section 3.1.5.2.<71>

pMessageID: An OBJECTID as defined in [MS-MQMQ] section 2.2.8. This value can be NULL. If not NULL, the server MUST return a message identifier for the new message if this method succeeds.

Return Values: On success, this method MUST return MQ_OK (0x00000000); otherwise, the server MUST return a failure HRESULT,<72> 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 (section 3.1.4.24) method when IP_HANDSHAKE (0x00000000) or IPX_HANDSHAKE (0x00000002) is the interface specified by the fIP parameter.

 Security Considerations: The caller can request that the server perform security related operations such as signing and encrypting the message. These operations are requested by setting members of the ptb.CACTransferBufferOld structure.

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.

  • Locate a LocalQueueContextHandle (section 3.1.1.3) ADM element instance in the server's iLocalQueueContextHandleTable (section 3.1.1.2) 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 iLocatedLocalQueueContextHandle and set it to a reference to the located LocalQueueContextHandle ADM element instance.

  • 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 with an identifier matching ptb.old.pUow. If no such entry exists, the client did not enlist the transaction before attempting to perform a transactional send operation. In this event, return a failure HRESULT.

  • Create a new Message ([MS-MQDMPR] section 3.1.1.12) ADM element instance with contents from ptb using the defined translation table.

  • If the message body is encrypted (ptb.old.bEncrypted is not 0x00, ppSymmKeys is not NULL, and ppSymmKeysSize is not 0x00000000) and the destination queue is located on the supporting server, the message body MUST be decrypted. Using the algorithm indicated by ptb.old.pulEncryptAlg, decrypt the symmetric key that is contained in ppSymmKeysSize with the server's private key. Finally, use the decrypted symmetric key to decrypt the message body.

  • Generate an Enqueue Message To An Open Queue ([MS-MQDMPR] section 3.1.7.1.27) event with the following argument values:

    • iOpenQueueDescriptor := iLocatedLocalQueueContextHandle.OpenQueueDescriptorReference

    • iMessage := The Message ADM element instance previously created.

    • iTransaction := The Transaction ADM element instance previously resolved; or, if ptb.old.pUow is NULL, this optional argument is not specified.

  • If the rStatus result of the  Enqueue Message To An Open Queue event is zero, return MQ_OK (0x00000000); otherwise, return a failure HRESULT.