C-C++ Code Example: Acknowledgment Class Filter
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 retrieves all the messages in an administration queue that have a given acknowledgment message class provided by the caller.
Filtering is done by peeking at the PROPID_M_CLASS property of each acknowledgment message in the queue and removing only those messages whose property value matches the acknowledgment class provided by the caller.
To filter acknowledgment messages
Define the maximum number of queue properties to be specified and the queue property counter.
Define the MQMSGPROPS structure.
Specify PROPID_M_CLASS.
Initialize the MQMSGPROPS structure.
Call MQOpenQueue to open the queue with receive access. Receive access allows the application to peek at or remove the messages in the queue.
Call MQCreateCursor to create the cursor for navigating the queue. The returned cursor handle is used in the calls to read messages.
Call MQReceiveMessage with peek access to peek at the first message in the queue. This call also initializes the cursor so that the cursor points at the first message in the queue.
In a loop structure, continue to call MQReceiveMessage to peek at and remove the messages in the queue. Note that the receive action of each call varies depending on if the previous message was or was not removed from the queue.
If the current message has the correct acknowledgment message class, set dwRecAction to MQ_ACTION_RECEIVE, call MQReceiveMessage to remove the message, then reset dwRecAction to MQ_ACTION_PEEK_CURRENT to process the next message. This will remove the current message and Message Queuing moves the cursor to the next message.
If the message does not have the correct acknowledgment message class, set dwRecAction to MQ_ACTION_PEEK_NEXT to move the cursor to test the next message. In this case, the application must move the cursor to the next message.
Call MQCloseQueue and MQCloseCursor to free the resources.
Code Example
The following code example can be run on all versions of Message Queuing.
HRESULT FilterAckClass(
LPCWSTR wszQueueFormatName,
unsigned short usAckClass
)
{
// Validate the input string.
if (wszQueueFormatName == NULL)
{
return MQ_ERROR_INVALID_PARAMETER;
}
// Define the required constants and variables for the filter.
const int NUMBEROFPROPERTIES = 5; // Number of properties
DWORD cPropId = 0; // Property counter
//Define an MQMSGPROPS structure.
MQMSGPROPS msgprops;
MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];
PROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];
HRESULT aMsgStatus[NUMBEROFPROPERTIES];
HANDLE hQueue = NULL; // Queue handle
HANDLE hCursor = NULL; // Cursor handle
HRESULT hr = MQ_OK; // Define results
DWORD dwRecAction = 0; // Receive action mode
// Specify the message properties to be retrieved.
aMsgPropId[cPropId] = PROPID_M_CLASS; // Property ID
aMsgPropVar[cPropId].vt = VT_UI2; // Type indicator
cPropId++;
// Initialize the MQMSGPROPS structure.
msgprops.cProp = cPropId; // Number of message properties
msgprops.aPropID = aMsgPropId; // IDs of message properties
msgprops.aPropVar = aMsgPropVar; // Values of message properties
msgprops.aStatus = aMsgStatus; // Error reports
// Open the queue to filter messages.
hr = MQOpenQueue(
wszQueueFormatName, // Format name of the queue
MQ_RECEIVE_ACCESS, // Access mode
MQ_DENY_RECEIVE_SHARE, // Share mode
&hQueue // OUT: Queue handle
);
if (FAILED(hr))
{
return hr;
}
// Create the cursor used to navigate through the queue.
hr = MQCreateCursor(
hQueue, // Queue handle
&hCursor // OUT: Cursor handle
);
if (FAILED(hr))
{
MQCloseQueue(hQueue);
return hr;
}
// Peek at the first message in the queue.
hr = MQReceiveMessage(
hQueue, // Queue handle
0, // Maximum time (msec)
MQ_ACTION_PEEK_CURRENT, // Receive action
&msgprops, // Message property structure
NULL, // No OVERLAPPED structure
NULL, // No callback function
hCursor, // Cursor handle
NULL // No transaction
);
if (FAILED(hr))
{
MQCloseCursor(hCursor);
MQCloseQueue(hQueue);
return hr;
}
// Filter messages from the queue.
do
{
if (msgprops.aPropVar[0].uiVal == usAckClass)
{
dwRecAction = MQ_ACTION_RECEIVE; // Receive action
hr = MQReceiveMessage(
hQueue, // Queue handle
0, // Maximum time (msec)
dwRecAction, // Receive action
&msgprops, // Message property structure
NULL, // No OVERLAPPED structure
NULL, // No callback function
hCursor, // Cursor handle
NULL // No transaction
);
if (FAILED(hr))
{
break;
}
//
// Process the acknowledgment message.
//
dwRecAction = MQ_ACTION_PEEK_CURRENT; // Reset to peek at the current cursor position.
}
else
{
dwRecAction = MQ_ACTION_PEEK_NEXT; // Reset receive action mode.
}
hr = MQReceiveMessage(
hQueue, // Queue handle
0, // Maximum time (msec)
dwRecAction, // Receive action
&msgprops, // Message property structure
NULL, // No OVERLAPPED structure
NULL, // No callback function
hCursor, // Cursor handle
NULL // No transaction
);
if (FAILED(hr))
{
break;
}
} while (SUCCEEDED(hr));
// Close the cursor and queue to free resources.
hr = MQCloseCursor(hCursor);
if (FAILED(hr))
{
MQCloseQueue(hQueue);
return hr;
}
hr = MQCloseQueue(hQueue);
return hr;
}