C-C++ Code Example: Validating Authentication
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_AUTHENTICATED_EX property of all the messages in a known queue, displaying the type of signature that was used to sign any messages that requested authentication.
For information on how Message Queuing authenticates messages, see Message Authentication.
This example uses the PROPID_M_AUTHENTICATED_EX property (introduced in MSMQ 2.0) to validate authentication and to determine what type of signature was used to sign the message. Receiving applications using earlier versions of Message Queuing must use the PROPID_M_AUTHENTICATED property that can only validate that authentication was requested.
To validate authentication
Define the constants, variables, and structures needed by the function.
Specify PROPID_M_AUTHENTICATED_EX.
Initialize the MQMSGPROPS structure.
Generate a format name for opening the queue.
Note
wcslen properly handles only null-terminated strings. This code example does not verify that the strings passed to it are null-terminated. It is the responsibility of the caller to ensure that the strings passed are null-terminated.
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 each message in the queue.
Call MQCloseQueue and MQCloseCursor to free the resources.
Code Example
The following code example requires MSMQ 2.0 or later.
HRESULT ValidatingAuthentication(
WCHAR * wszQueueName,
WCHAR * wszComputerName
)
{
// Validate the input strings.
if (wszQueueName == NULL || wszComputerName == NULL)
{
return MQ_ERROR_INVALID_PARAMETER;
}
// Define constants, variables, and structures.
const int NUMBEROFPROPERTIES = 5; // Number of properties
DWORD cPropId = 0; // Property counter
MQMSGPROPS msgProps;
MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];
MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];
HRESULT aMsgStatus[NUMBEROFPROPERTIES];
// Specify the message properties to be retrieved.
aMsgPropId[cPropId] = PROPID_M_AUTHENTICATED_EX; // Property ID
aMsgPropVar[cPropId].vt = VT_NULL; // 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
// Generate a format name from the queue name and the computer name.
WCHAR * wszFormatName = NULL;
DWORD dwFormatNameLength = 0;
dwFormatNameLength = wcslen(wszQueueName) + wcslen(wszComputerName) + 12;
wszFormatName = new WCHAR[dwFormatNameLength];
if (wszFormatName == NULL)
{
return MQ_ERROR_INSUFFICIENT_RESOURCES;
}
memset(wszFormatName, 0, dwFormatNameLength*sizeof(WCHAR));
// ************************************
// You must concatenate "DIRECT=OS:", wszComputerName, "\", and
// wszQueueName into the wszFormatName buffer.
// wszFormatName = "DIRECT=OS:" + wszComputerName + "\" +
// wszQueueName
// If the format name is too long for the buffer, return FALSE.
// ************************************
// Open the queue to read messages.
HRESULT hr = MQ_OK; // Return code
HANDLE hQueue = NULL; // Queue handle
hr = MQOpenQueue(
wszFormatName, // Format name of the queue
MQ_RECEIVE_ACCESS, // Access mode
MQ_DENY_RECEIVE_SHARE, // Share mode
&hQueue // [out] Queue handle
);
// Free the memory that was allocated for the format name string.
delete [] wszFormatName;
// Handle any error returned by MQOpenQueue.
if (FAILED(hr))
{
return hr;
}
// Create the cursor used to navigate through the queue.
HANDLE hCursor = NULL; // Cursor handle
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) to read the message
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;
}
// Peek at all messages in the queue and check whether
// authentication was requested.
while (SUCCEEDED(hr))
{
switch(msgProps.aPropVar[0].bVal)
{
case MQMSG_AUTHENTICATION_NOT_REQUESTED:
wprintf(L"Not an authenticated message.\n");
break;
case MQMSG_AUTHENTICATED_SIG10:
wprintf(L"Authenticated message. Signed with an MSMQ 1.0 signature.\n");
break;
case MQMSG_AUTHENTICATED_SIG20:
wprintf(L"Authenticated message. Signed with an MSMQ 2.0 signature.\n");
break;
case MQMSG_AUTHENTICATED_SIG30:
wprintf(L"Authenticated message. Signed with an MSMQ 3.0 multiple-destination digital signature.\n");
break;
case MQMSG_AUTHENTICATED_SIGXML:
wprintf(L"Authenticated message. Signed with an XML digital signature.\n");
break;
}
hr = MQReceiveMessage(
hQueue, // Queue handle
0, // Maximum time (msec) to read message
MQ_ACTION_PEEK_NEXT, // Receive action
&msgProps, // Message property structure
NULL, // No OVERLAPPED structure
NULL, // No callback function
hCursor, // Cursor handle
MQ_NO_TRANSACTION // Not in a transaction
);
}
// Close the cursor and the queue.
hr = MQCloseCursor(hCursor);
if (FAILED(hr))
{
MQCloseQueue(hQueue);
return hr;
}
hr = MQCloseQueue(hQueue);
return hr;
}