Cursors allow you to read a message that is not at the front of the queue. The cursor always maintains its position relative to the message to which it points.
The two functions used to manage the cursor are MQCreateCursor and MQCloseCursor. MQCreateCursor returns a cursor handle that is used in MQReceiveMessage, and MQCloseCursor releases the cursor's resources.
hr = MQOpenQueue(
wszFormatNameBuffer,
MQ_RECEIVE_ACCESS,
0,
&hQueue
);
hr = MQCreateCursor(
hQueue, //Queue handle
&hCursor
);
MQMSGPROPS MsgProps;
MQPROPVARIANT aVariant[10];
MSGPROPID aPropId[10];
DWORD PropIdCount = 0;
#define MSG_BODY_LEN 500
unsigned char ucMsgBody[MSG_BODY_LEN];
DWORD dwAppspecificIndex;
// Set the PROPID_M_BODY property.
aPropId[PropIdCount] = PROPID_M_BODY; //PropId
aVariant[PropIdCount].vt = VT_VECTOR|VT_UI1; //Type
aVariant[PropIdCount].caub.cElems = MSG_BODY_LEN; //Value
aVariant[PropIdCount].caub.pElems = ucMsgBody;
PropIdCount++;
//Set the PROPID_M_APPSPECIFIC property.
aPropId[PropIdCount] = PROPID_M_APPSPECIFIC; //PropId
aVariant[PropIdCount].vt = VT_UI4; //Type
dwAppspecificIndex = PropIdCount;
PropIdCount++;
//Set the MQMSGPROPS structure.
MsgProps.cProp = PropIdCount; //Number of properties.
MsgProps.aPropID = aPropId; //Ids of properties.
MsgProps.aPropVar = aVariant; //Values of properties.
MsgProps.aStatus = NULL; //No Error report.
DWORD dwAction = MQ_ACTION_PEEK_CURRENT; //Peek at first msg.
do
{
hr = MQReceiveMessage(
hQueue, // handle to the Queue.
5 * 60 * 1000, // Max time (msec) to wait for msg.
dwAction, // Action.
&MsgProps, // properties to retrieve.
NULL, // No overlapped structure.
NULL, // No callback function.
hCursor, // Cursor handle.
NULL // No transaction.
);
if (FAILED(hr))
{
// Handle failure
}
dwAction = MQ_ACTION_PEEK_NEXT; //Peek at next message.
} while (MsgProps.aPropVar[dwAppspecificIndex].ulVal != 1);
hr = MQCloseCursor(
hCursor //Cursor handle
);
The following example locates a message whose application-specific property is equal to 1. It uses MQ_PEEK_CURRENT to look at the first message in the queue and uses MQ_PEEK_NEXT to look at the next message in the queue. MQ_PEEK_NEXT looks at the next message, and then moves the cursor.
HRESULT hr;
QUEUEHANDLE hQueue;
//////////////////////////////////
// Open queue with receive access.
/////////////////////////////////
hr = MQOpenQueue(
wszFormatNameBuffer,
MQ_RECEIVE_ACCESS,
0,
&hQueue
);
if (FAILED(hr))
{
//
// Handle failure
//
}
//////////////////////////////////
// Create the cursor.
/////////////////////////////////
HANDLE hCursor;
hr = MQCreateCursor(
hQueue, //Queue handle
&hCursor
);
if (FAILED(hr))
{
//
// Handle failure
//
}
////////////////////////////////////////
// Specify the message properties you
// want to retrieve.
///////////////////////////////////////
MQMSGPROPS MsgProps;
MQPROPVARIANT aVariant[10];
MSGPROPID aPropId[10];
DWORD PropIdCount = 0;
#define MSG_BODY_LEN 500
unsigned char ucMsgBody[MSG_BODY_LEN];
DWORD dwAppspecificIndex;
// Set the PROPID_M_BODY property.
aPropId[PropIdCount] = PROPID_M_BODY; //PropId
aVariant[PropIdCount].vt = VT_VECTOR|VT_UI1; //Type
aVariant[PropIdCount].caub.cElems = MSG_BODY_LEN; //Value
aVariant[PropIdCount].caub.pElems = ucMsgBody;
PropIdCount++;
//Set the PROPID_M_APPSPECIFIC property.
aPropId[PropIdCount] = PROPID_M_APPSPECIFIC; //PropId
aVariant[PropIdCount].vt = VT_UI4; //Type
dwAppspecificIndex = PropIdCount; //Value
PropIdCount++;
//Set the MQMSGPROPS structure.
MsgProps.cProp = PropIdCount; //Number of properties.
MsgProps.aPropID = aPropId; //Ids of properties.
MsgProps.aPropVar = aVariant; //Values of properties.
MsgProps.aStatus = NULL; //No Error report.
///////////////////////////////////
// Peek until you find the message
// where APPSPECIFIC = 1.
///////////////////////////////////
DWORD dwAction = MQ_ACTION_PEEK_CURRENT; //Peek at first msg.
do
{
hr = MQReceiveMessage(
hQueue, // handle to the Queue.
5 * 60 * 1000, // Max time (msec) to wait for msg.
dwAction, // Action.
&MsgProps, // properties to retrieve.
NULL, // No overlapped structure.
NULL, // No callback function.
hCursor, // Cursor handle.
NULL // No transaction.
);
if (FAILED(hr))
{
// Handle failure
break;
}
dwAction = MQ_ACTION_PEEK_NEXT; //Peek at next message.
} while (MsgProps.aPropVar[dwAppspecificIndex].ulVal != 1);
hr = MQCloseCursor(
hCursor
);