3.17.4.1.48 Send (Opnum 54)

The Send method is received by the server in an RPC_REQUEST packet. In response, the server MUST send a message.

 HRESULT Send(
   [in] IDispatch* DestinationQueue,
   [in, optional] VARIANT* Transaction
 );

DestinationQueue: A pointer to an IDispatch interface that can reference either an MSMQQueue object instance or an MSMQDestination object instance.

Transaction: A pointer to a VARIANT that contains either:

  • A VT_DISPATCH or a VT_DISPATCH | VT_BYREF that points to an MSMQTransaction object.

  • A VT_I4 that references one of the following enumeration values as defined in section 2.2.2.1.

Return Values: The method MUST return S_OK (0x00000000) on success or an implementation-specific error HRESULT on failure.

When processing this call, the server MUST follow these guidelines:

  • If the DestinationQueue input parameter is NULL:

    • Return E_INVALIDARG (0x80000003), and take no further action.

  • If either Message.Class OR Message.SenderIdentifier OR Message.SymmetricKey OR Message.Signature OR Message.AuthenticationProviderName properties of the represented Message were set after this object was initialized AND the represented Message.ConnectorTypeIdentifier equals the NULL GUID ({00000000-0000-0000-0000-000000000000}):

    • Return MQ_ERROR_MISSING_CONNECTOR_TYPE (0xC00E0055), and take no further action.

  • If (the represented Message.AuthenticationProviderType is not NULL AND the represented Message.AuthenticationProviderName is NULL) OR (the represented Message.AuthenticationProviderType is NULL AND the represented Message.AuthenticationProviderName is not NULL):

    • Return MQ_ERROR_INSUFFICIENT_PROPERTIES (0xC00E003F), and take no further action.

  • Define transactionalSend as a Boolean value set to False.

  • If the Transaction input parameter is NOT NULL:

    • If the Transaction input parameter is VT_DISPATCH or VT_DISPATCH | VT_BYREF:

      • Define transactionIdentifier as the value of the TransactionIdentifier instance variable of the ITransaction object obtained by the MSMQTransaction::get_ITransaction method on the MSMQTransaction object obtained from the Transaction input parameter.

      • Set transactionalSend to True.

    • Else, if the Transaction input parameter is VT_I4:

      • If the numeric value represented by the Transaction input parameter equals either MQ_MTS_TRANSACTION (0x00000001) or MQ_XA_TRANSACTION (0x00000002):

        • Define and retrieve transactionIdentifier as described in section 2.2.2.1, using the enum numeric value represented by the Transaction input parameter.

        • Set transactionalSend to True.

    • Else:

      • Return an error HRESULT, and take no further action.

    • If transactionalSend is True:

      • Identify the Transaction of the local QueueManager.TransactionCollection where the Transaction.Identifier equals the value of transactionIdentifier.

      • If a Transaction cannot be located:

        • Generate a Create Transaction event with the following inputs:

          • iTransactionIdentifier = transactionIdentifier

  • If the represented Message.SenderIdentifier equals NULL:

    • If the SenderIdentifierCache instance variable equals NULL:

      • Set the represented Message.SenderIdentifier to the SID of the caller.<151>

    • Else:

      • Set the represented Message.SenderIdentifier to the value of the SenderIdentifierCache instance variable.

  • If the represented Message.SenderCertificate equals NULL:

    • If the SenderCertificateCache instance variable is NOT NULL:

      • Set the represented Message.SenderCertificate to the value of the SenderCertificateCache.

    • Else:

      • Set the represented Message.SenderCertificate to the Certificate ADM attribute of the InternalCertificate ([MS-MQDMPR] section 3.1.1.19) ADM element instance from the InternalCertificateCollection ADM attribute of the local QueueManager ADM element instance whose InternalCertificate.User ADM attribute matches the user identified by the represented Message.SenderIdentifier.

  • Else:

    • If the SenderCertificateCache instance variable equals NULL OR the certificate in the SenderCertificateCache does not match the Message.SenderCertificate:

      • The server MAY impose additional requirements on the represented Message.SenderCertificate for authentication purposes.<152>

  • Set the represented Message.SourceMachineIdentifier to the local QueueManager.Identifier.

  • If the represented Message.ConnectorTypeIdentifier equals the NULL GUID ({00000000-0000-0000-0000-000000000000}):

    • Set the represented Message.Class to MQMSG_CLASS_NORMAL (0x00000000).

  • Set the represented Message.Identifier to a new and unique value as specified by [MS-MQMQ] section 2.2.8.

  • Define queueFormatName as follows:

    • If the DestinationQueue input parameter represents an MSMQQueue object:

      • Set queueFormatName to the result of calling MSMQQueueInfo::get_FormatName on the MSMQQueueInfo object returned as a result of calling the MSMQQueue::get_QueueInfo method on the MSMQQueue object represented by the DestinationQueue input parameter.

    • If the DestinationQueue input parameter represents an MSMQDestination object:

      • Set queueFormatName to the result of calling the MSMQDestination::get_FormatName method on the MSMQDestination object represented by the DestinationQueue input parameter.

  • Set the represented Message.DestinationQueueFormatName to queueFormatName.

  • Set the represented Message.SentTime to the current time.

  • If the represented Message.TimeToReachQueue is greater than Message.TimeToBeReceived:

    • Set the represented Message.TimeToBeReceived to the same value as Message.TimeToReachQueue.

  • If the represented Message.Signature equals NULL:

    • If the RequestedAuthenticationLevel instance variable is NOT equal to MQMSG_AUTH_LEVEL_NONE (0x00000000):

      • Calculate the hash value using the specified represented Message.HashAlgorithm and in the manner identified by the RequestedAuthenticationLevel instance variable.

      • Obtain the private key for the certificate contained in the represented Message.SenderCertificate.

      • Set the represented Message.Signature to the signature calculated using the specified Message.AuthenticationProviderType and Message.SenderCertificate and the obtained private key applied to the calculated hash value.

      • Set the represented Message.AuthenticationLevel to the associated value from the RequestedAuthenticationLevel instance variable. Refer to section 2.2.2.16 for details of the translation.

  • If the SOAPBody instance variable is NOT NULL:

    • Append the SOAPBody instance variable value to the end of the represented Message.SoapBody.

  • If the SOAPHeader instance variable is NOT NULL:

    • Append the SOAPHeader instance variable value to the end of the represented Message.SoapHeader.

  • Define targetQueue as an OpenQueueDescriptor and set it as follows:

    • If the DestinationQueue input parameter represents an MSMQQueue object:

      • Set targetQueue to the value of the OpenQueueDescriptor instance variable of the MSMQQueue object represented by the DestinationQueue input parameter.

    • If the DestinationQueue input parameter represents an MSMQDestination object:

      • Set targetQueue to the value of the DestinationOpenQueueDescriptor instance variable of the MSMQDestination object represented by the DestinationQueue input.

  • Generate an Enqueue Message to an Open Queue event ([MS-MQDMPR] section 3.1.7.1.27) with the following inputs:

    • iOpenQueueDescriptor = targetQueue

    • iMessage = The represented Message

    • iTransaction = The identified Transaction

    • If the rStatus return value is not equal to MQ_OK (0x00000000):

      • Return an error HRESULT, and take no further action.