Acknowledgment messages returned by the connector application must be sent to the administration queue specified by the original message. Several properties must be set to the acknowledgment message values shown below, and others should be set to the values specified by the original message.
The following properties must be set to acknowledgment message values shown below.
Property | Setting |
---|---|
PROPID_M_ACKNOWLEDGE | MQMSG_ACKNOWLEDGMENT_NONE |
PROPID_M_AUTH_LEVEL | MQMSG_AUTH_LEVEL_NONE |
PROPID_M_BODY | For positive acknowledgments set to NULL. For negative acknowledgments (with the exception of encrypted message bodies), set to the body of the original message. |
PROPID_M_CORRELATIONID | Message identifier of original message. |
PROPID_M_CLASS | Appropriate acknowledgment class. |
PROPID_M_JOURNAL | MQMSG_JOURNAL_NONE |
PROPID_M_RESP_QUEUE | Destination queue of the original message. |
PROPID_M_TIME_TO_BE_RECEIVED | INFINITE |
PROPID_M_TIME_TO_REACH_QUEUE | INFINITE |
All the other properties are set to the same values as the original message.
hr = MQOpenQueue(lpstrAdminQueue,MQ_SEND_ACCESS,0, &hQueue);
if (FAILED(hr))
{
// Handle failure
// Return hr;
}
aPropID[cProp] = PROPID_M_CLASS;
aPropVar[cProp].vt = VT_UI2;
aPropVar[cProp].uiVal = AckValue;
cProp++;
aPropID[cProp] = PROPID_M_ACKNOWLEDGE;
aPropVar[cProp].vt = VT_UI1;
aPropVar[cProp].bVal = MQMSG_ACKNOWLEDGMENT_NONE;
cProp++;
aPropID[cProp] = PROPID_M_TIME_TO_BE_RECEIVED;
aPropVar[cProp].vt = VT_UI4;
aPropVar[cProp].ulVal = INFINITE;
cProp++;
aPropID[cProp] = PROPID_M_TIME_TO_REACH_QUEUE;
aPropVar[cProp].vt = VT_UI4;
aPropVar[cProp].ulVal = INFINITE;
cProp++;
aPropID[cProp] = MQMSG_JOURNAL_NONE;
aPropVar[cProp].vt = VT_UI1;
aPropVar[cProp].bVal = pMsgProps->aPropVar[i].bVal;
cProp++;
aPropID[cProp] = PROPID_M_CONNECTOR_TYPE;
aPropVar[cProp].vt = VT_CLSID;
aPropVar[cProp].puuid = &g_gConnectorType;
cProp++;
hr = MQSendMessage(hQueue, &SendMsgProp, NULL);
The following example creates an acknowledgment message and sends it back to the administration queue specified by the original message. It assumes that the format name of the administration queue (lpstrAdimQueue), all original message properties (pMsgProps), and the value of the acknowledgment (ackValue) are all available.
HRESULT CreateAck(LPWSTR lpstrAdminQueue,
USHORT AckValue,
MQMSGPROPS* pMsgProps
)
{
MQMSGPROPS SendMsgProp;
MSGPROPID aPropID[40];
MQPROPVARIANT aPropVar[40];
HRESULT aStatus[40];
HRESULT hr;
HANDLE hQueue = NULL;
DWORD cProp = 0;
//////////////////////////////////
// Open the administration queue
// specified by the original message.
/////////////////////////////////
hr = MQOpenQueue(lpstrAdminQueue,MQ_SEND_ACCESS,0, &hQueue);
if (FAILED(hr))
{
// Handle failure
// Return hr;
}
DWORD dwExtensionMsgSize = 0;
DWORD dwSenderidLen = 0;
DWORD dwBodySize = 0;
BOOL fEncrypted = FALSE;
DWORD i;
//////////////////////////////////////////////////
// Set the acknowledgment message default values.
//////////////////////////////////////////////////
aPropID[cProp] = PROPID_M_CLASS;
aPropVar[cProp].vt = VT_UI2;
aPropVar[cProp].uiVal = AckValue;
cProp++;
aPropID[cProp] = PROPID_M_ACKNOWLEDGE;
aPropVar[cProp].vt = VT_UI1;
aPropVar[cProp].bVal = MQMSG_ACKNOWLEDGMENT_NONE;
cProp++;
aPropID[cProp] = PROPID_M_TIME_TO_BE_RECEIVED;
aPropVar[cProp].vt = VT_UI4;
aPropVar[cProp].ulVal = INFINITE;
cProp++;
aPropID[cProp] = PROPID_M_TIME_TO_REACH_QUEUE;
aPropVar[cProp].vt = VT_UI4;
aPropVar[cProp].ulVal = INFINITE;
cProp++;
aPropID[cProp] = MQMSG_JOURNAL_NONE;
aPropVar[cProp].vt = VT_UI1;
aPropVar[cProp].bVal = pMsgProps->aPropVar[i].bVal;
cProp++;
//////////////////////////////////////
// Set all other message properties to
// the values of the original message.
//////////////////////////////////////
// Get size and length of properties.
for (i = 0; i < pMsgProps->cProp ; i++)
{
switch(pMsgProps->aPropID[i])
{
case PROPID_M_EXTENSION:
dwExtensionMsgSize = pMsgProps->aPropVar[i].ulVal;
break;
case PROPID_M_SENDERID_LEN:
dwSenderidLen = pMsgProps->aPropVar[i].ulVal;
break;
case PROPID_M_BODY_SIZE:
dwBodySize = pMsgProps->aPropVar[i].ulVal;
break;
case PROPID_M_PRIV_LEVEL:
fEncrypted = (pMsgProps->aPropVar[i].ulVal == MQMSG_PRIV_LEVEL_BODY);
break;
default:
break;
}
}
for (i = 0; i < pMsgProps->cProp ; i++)
{
switch (pMsgProps->aPropID[i])
{
// Set correlation identifier
case PROPID_M_MSGID:
aPropID[cProp] = PROPID_M_CORRELATIONID;
aPropVar[cProp].vt = VT_UI1|VT_VECTOR;
aPropVar[cProp].caub.cElems = pMsgProps->aPropVar[i].caub.cElems;
aPropVar[cProp].caub.pElems = pMsgProps->aPropVar[i].caub.pElems;
cProp++;
break;
// Set message priority.
case PROPID_M_PRIORITY:
aPropID[cProp] = PROPID_M_PRIORITY;
aPropVar[cProp].vt = VT_UI1;
aPropVar[cProp].bVal = pMsgProps->aPropVar[i].bVal;
cProp++;
break;
// Set delivery mode.
case PROPID_M_DELIVERY:
aPropID[cProp] = PROPID_M_DELIVERY;
aPropVar[cProp].vt = VT_UI1;
aPropVar[cProp].bVal = pMsgProps->aPropVar[i].bVal;
cProp++;
break;
// Set application specific information
case PROPID_M_APPSPECIFIC:
aPropID[cProp] = PROPID_M_APPSPECIFIC;
aPropVar[cProp].vt = VT_UI4;
aPropVar[cProp].ulVal = pMsgProps->aPropVar[i].ulVal;
cProp++;
break;
// Set message label to the same
case PROPID_M_LABEL:
aPropID[cProp] = PROPID_M_LABEL;
aPropVar[cProp].vt = VT_LPWSTR;
aPropVar[cProp].pwszVal = pMsgProps->aPropVar[i].pwszVal;
cProp++;
break;
//
// Set extension information.
case PROPID_M_EXTENSION:
aPropID[cProp] = PROPID_M_EXTENSION;
aPropVar[cProp].vt = VT_UI1|VT_VECTOR;
aPropVar[cProp].caub.cElems = dwExtensionMsgSize;
aPropVar[cProp].caub.pElems = pMsgProps->aPropVar[i].caub.pElems;
cProp++;
break;
// Set acknowledge message response queue to
// the destination queue of the original message.
case PROPID_M_DEST_QUEUE:
aPropID[cProp] = PROPID_M_RESP_QUEUE;
aPropVar[cProp].vt = VT_LPWSTR;
aPropVar[cProp].pwszVal = pMsgProps->aPropVar[i].pwszVal;
cProp++;
break;
//////////////////////////////////////////////
// Set message body. If acknowledge is negative
// and the original message isn't encrypted, add
// message body of original message.
//////////////////////////////////////////////
case PROPID_M_BODY:
if (MQCLASS_NACK(AckValue) && ! fEncrypted)
{
aPropID[cProp] = PROPID_M_BODY;
aPropVar[cProp].vt = VT_UI1|VT_VECTOR;
aPropVar[cProp].caub.cElems = dwBodySize;
aPropVar[cProp].caub.pElems = pMsgProps->aPropVar[i].caub.pElems;
cProp++;
}
break;
default:
break;
}
}
//////////////////////////////////////////////////
// Set the connector type identifier (GUID) to
// indicate who generated the acknowledge message.
//////////////////////////////////////////////////
aPropID[cProp] = PROPID_M_CONNECTOR_TYPE;
aPropVar[cProp].vt = VT_CLSID;
aPropVar[cProp].puuid = &g_gConnectorType;
cProp++;
SendMsgProp.aStatus = aStatus;
SendMsgProp.aPropID = aPropID;
SendMsgProp.aPropVar = aPropVar;
SendMsgProp.cProp =cProp;
////////////////////////////////////////////////
// Send the acknowledge message back to the
// administration queue specified by the
// original message.
/////////////////////////////////////////////////
hr = MQSendMessage(hQueue, &SendMsgProp, NULL);
MQCloseQueue(hQueue);
return hr;
}