C-C++ Code Example: Verifying Acknowledgment Requests

 

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 peeks at the PROPID_M_ACKNOWLEDGE property of all the messages in a known queue, displaying the label of any message that requested acknowledgment messages.

For information on how acknowledgment messages are requested, see Acknowledgment Messages.

To verify acknowledgments

  1. Define the maximum number of queue properties to be specified and the queue property counter.

  2. Define the MQMSGPROPS structure.

  3. Specify PROPID_M_ACKNOWLEDGE.

  4. Initialize the MQMSGPROPS structure.

  5. Call MQOpenQueue to open the queue with receive access. Receive access allows the application to peek at or remove the messages in the queue.

  6. Call MQCreateCursor to create the cursor for navigating the queue. The returned cursor handle is used in the calls to read messages.

  7. 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.

  8. In a loop structure, continue to call MQReceiveMessage to peek at and remove the messages in the queue.

Note

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 an acknowledgment level that is not equal to MQ_ACKNOWLEDGMENT_NONE, 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 call will remove the current message and Message Queuing moves the cursor to the next message.

If the acknowledgment level of the current message is equal to MQ_ACKNOWLEDGMENT_NONE, 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.

  1. Call MQCloseQueue and MQCloseCursor to free the resources.

Code Example

The following code example can be run on all versions of Message Queuing.

HRESULT VerifyingAcknowledgment(  
                                LPCWSTR wszQueueFormatName  
                                )  
{  
  
  // Validate the input string.  
  if (wszQueueFormatName == NULL)  
  {  
    return MQ_ERROR_INVALID_PARAMETER;  
  }  
  
  //  Define the maximum total number of message properties and a property counter.  
  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;                            // Return code  
  DWORD dwRecAction = 0;                         // Receive action mode  
  
  // Specify the message properties to be retrieved.  
  aMsgPropId[cPropId] = PROPID_M_ACKNOWLEDGE;    // Property ID  
  aMsgPropVar[cPropId].vt = VT_UI1;              // Type indicator  
  cPropId++;  
  
  // Initialize the MQMSGPROPS structure.  
  msgprops.cProp = cPropId;                      // Number of message properties  
  msgprops.aPropID = aMsgPropId;                 // IDs of the message properties  
  msgprops.aPropVar = aMsgPropVar;               // Values of the message properties  
  msgprops.aStatus  = aMsgStatus;                // Error reports  
  
  // Open the queue to read 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  
                        MQ_NO_TRANSACTION        // Not in a transaction  
                        );  
  if (FAILED(hr))  
  {  
    MQCloseCursor(hCursor);  
    MQCloseQueue(hQueue);  
    return hr;  
  }  
  
  // Verify messages.  
  do  
  {  
    if (msgprops.aPropVar[0].bVal != MQMSG_ACKNOWLEDGMENT_NONE)  
    {  
      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  
                            MQ_NO_TRANSACTION    // Not in a transaction  
                            );  
      if (FAILED(hr))  
      {  
         break;  
      }  
  
      //  
      // Process the 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  
                          MQ_NO_TRANSACTION      // Not in a transaction  
                          );  
    if (FAILED(hr))  
    {  
      break;  
    }  
  
  } while (SUCCEEDED(hr));  
  
  // Close the cursor and queue.  
  hr = MQCloseCursor(hCursor);  
  if (FAILED(hr))  
  {  
    MQCloseQueue(hQueue);  
    return hr;  
  }  
  hr = MQCloseQueue(hQueue);  
  return hr;  
}