C-C++ Code Example: Returning Acknowledgment Messages (Connector Applications)
Applies To: Windows 10, Windows 7, Windows 8, Windows 8.1, Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows Server 2012 R2, Windows Server Technical Preview, Windows Vista
This example provides an application-defined function that returns an acknowledgment message to the specified administration queue.
Note
This function should only be called from a connector application when it is sending messages to foreign queues.
For information on connecting to a foreign messaging system, see Connector Services.
Code Example
The following code example requires MSMQ 2.0 or later.
HRESULT CreateAck(
LPWSTR lpstrAdminQueue,
USHORT AckValue,
MQMSGPROPS* pmsgprops,
GUID g_guidConnectorType
)
{
MQMSGPROPS SendMsgProp;
MSGPROPID aPropID[40];
MQPROPVARIANT aPropVar[40];
HRESULT aStatus[40];
HRESULT hr = MQ_OK;
HANDLE hQueue = NULL;
DWORD cProp = 0;
// Validate the input parameters.
if (lpstrAdminQueue == NULL || pmsgprops == NULL)
{
return MQ_ERROR_INVALID_PARAMETER;
}
// 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;
DWORD dwLabelLen = 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] = PROPID_M_JOURNAL;
aPropVar[cProp].vt = VT_UI1;
aPropVar[cProp].bVal = MQMSG_JOURNAL_NONE;
cProp++;
// Set all other message properties to
// the values of the original message.
// Get the size and length of the properties.
for (i = 0; i < pmsgprops->cProp ; i++)
{
switch(pmsgprops->aPropID[i])
{
case PROPID_M_EXTENSION_LEN:
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_BASE);
break;
default:
break;
}
}
for (i = 0; i < pmsgprops->cProp ; i++)
{
switch (pmsgprops->aPropID[i])
{
// Set the 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 the 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 the 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 the 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 the 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 Sender ID information.
case PROPID_M_SENDERID:
aPropID[cProp] = PROPID_M_SENDERID;
aPropVar[cProp].vt = VT_UI1|VT_VECTOR;
aPropVar[cProp].caub.cElems = dwSenderidLen;
aPropVar[cProp].caub.pElems = pmsgprops->aPropVar[i].caub.pElems;
cProp++;
break;
// Set the acknowledgment 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 the message body. If the acknowledgment is negative
// and the original message is not encrypted, add
// the 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:
switch (pmsgprops->aPropID[i]){
// The following fields were handled elsewhere:
case PROPID_M_EXTENSION_LEN:
case PROPID_M_SENDERID_LEN:
case PROPID_M_BODY_SIZE:
case PROPID_M_PRIV_LEVEL:
case PROPID_M_CLASS:
case PROPID_M_ACKNOWLEDGE:
case PROPID_M_TIME_TO_BE_RECEIVED:
case PROPID_M_TIME_TO_REACH_QUEUE:
case PROPID_M_JOURNAL:
case PROPID_M_CONNECTOR_TYPE:
case PROPID_M_CORRELATIONID:
case PROPID_M_RESP_QUEUE:
break;
// If it is a field that does not need special handling,
// simply set it as it is.
default:
aPropID[cProp] = pmsgprops->aPropID[i];
aPropVar[cProp] = pmsgprops->aPropVar[i];
break;
}
break;
}
}
// Set the connector type identifier (GUID) to
// indicate who generated the acknowledgment message.
aPropID[cProp] = PROPID_M_CONNECTOR_TYPE;
aPropVar[cProp].vt = VT_CLSID;
aPropVar[cProp].puuid = &g_guidConnectorType;
cProp++;
SendMsgProp.aStatus = aStatus;
SendMsgProp.aPropID = aPropID;
SendMsgProp.aPropVar = aPropVar;
SendMsgProp.cProp = cProp;
// Send the acknowledgment message back to the
// administration queue specified by the
// original message.
hr = MQSendMessage(
hQueue,
&SendMsgProp,
MQ_NO_TRANSACTION
);
if (FAILED(hr))
{
// Handle failure.
MQCloseQueue(hQueue);
return hr;
}
hr = MQCloseQueue(hQueue);
return hr;
}