854 lines
20 KiB
C
854 lines
20 KiB
C
/******************************************************************************\
|
|
* This is a part of the Microsoft Source Code Samples.
|
|
* Copyright (C) 1999 Microsoft Corporation.
|
|
* All rights reserved.
|
|
* This source code is only intended as a supplement to
|
|
* Microsoft Development Tools and/or WinHelp documentation.
|
|
* See these sources for detailed information regarding the
|
|
* Microsoft samples programs.
|
|
\******************************************************************************/
|
|
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
|
|
|
|
//
|
|
// Unique include file for MSMQ apps
|
|
//
|
|
#include <mq.h>
|
|
|
|
|
|
//
|
|
// Various defines
|
|
//
|
|
#define MAX_VAR 20
|
|
#define MAX_FORMAT 100
|
|
#define MAX_BUFFER 500
|
|
|
|
#define DIRECT 1
|
|
#define STANDARD 0
|
|
|
|
#define DS_ENABLED 1
|
|
#define DS_DISABLED 0
|
|
|
|
|
|
//
|
|
// GUID created with the tool "GUIDGEN"
|
|
//
|
|
static CLSID guidMQTestType =
|
|
{ 0xc30e0960, 0xa2c0, 0x11cf, { 0x97, 0x85, 0x0, 0x60, 0x8c, 0xb3, 0xe8, 0xc } };
|
|
|
|
|
|
//
|
|
// Prototypes
|
|
//
|
|
void Error(char *s, HRESULT hr);
|
|
void Syntax();
|
|
|
|
|
|
char mbsMachineName[MAX_COMPUTERNAME_LENGTH + 1];
|
|
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// Check if local computer is DS enabled or DS disabled
|
|
//
|
|
//-----------------------------------------------------
|
|
int DetectDsConnection(void)
|
|
{
|
|
|
|
MQPRIVATEPROPS PrivateProps;
|
|
QMPROPID aPropId[MAX_VAR];
|
|
MQPROPVARIANT aPropVar[MAX_VAR];
|
|
HRESULT aStatus[MAX_VAR];
|
|
|
|
DWORD cProp;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
//
|
|
// Prepare ds-enabled property
|
|
//
|
|
cProp = 0;
|
|
|
|
aPropId[cProp] = PROPID_PC_DS_ENABLED;
|
|
aPropVar[cProp].vt = VT_NULL;
|
|
++cProp;
|
|
|
|
// Create a PRIVATEPROPS structure
|
|
PrivateProps.cProp = cProp;
|
|
PrivateProps.aPropID = aPropId;
|
|
PrivateProps.aPropVar = aPropVar;
|
|
PrivateProps.aStatus = aStatus;
|
|
//
|
|
// Retrieve the information
|
|
//
|
|
hr = MQGetPrivateComputerInformation(
|
|
NULL,
|
|
&PrivateProps);
|
|
if(FAILED(hr))
|
|
{
|
|
Error("Unable to detect DS connection", hr);
|
|
}
|
|
|
|
|
|
if(PrivateProps.aPropVar[0].boolVal == 0)
|
|
return DS_DISABLED;
|
|
|
|
|
|
return DS_ENABLED;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// Allow a DS enabled client connect with a
|
|
// DS disabled one.
|
|
//
|
|
//-----------------------------------------------------
|
|
int SetConnectionMode(void)
|
|
{
|
|
|
|
char cDirectMode;
|
|
|
|
|
|
//
|
|
// In case the local computer is in a domain and not in workgroup mode,
|
|
// we have two cases:
|
|
// 1. Other side is a computer in a domain.
|
|
// 2. Other side is a computer working in workgroup mode.
|
|
//
|
|
|
|
if(DetectDsConnection() == DS_ENABLED)
|
|
{
|
|
printf("Do you wish to connect with a DS disabled client (y or n) ? ");
|
|
scanf("%c", &cDirectMode);
|
|
|
|
switch(tolower(cDirectMode))
|
|
{
|
|
case 'y':
|
|
return DIRECT;
|
|
|
|
case 'n':
|
|
return STANDARD;
|
|
|
|
default:
|
|
printf("Bye.\n");
|
|
exit(1);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return DIRECT; // Local computer is DS disabled
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------
|
|
//
|
|
// Receiver Mode
|
|
// -------------
|
|
// The receiver side does the following:
|
|
// 1. Creates a queue on its own computer'
|
|
// of type "guidMQTestType".
|
|
// The queue is either public or private, depending
|
|
// on the connection we wish to establish
|
|
// 2. Opens the queue
|
|
// 3. In a Loop
|
|
// Receives messages
|
|
// Prints message body and message label
|
|
// 4. Cleanup handles
|
|
// 5. Deletes the queue from the directory service
|
|
//
|
|
//--------------------------------------------------------
|
|
void Receiver(int dDirectMode)
|
|
{
|
|
|
|
MQQUEUEPROPS qprops;
|
|
MQMSGPROPS msgprops;
|
|
MQPROPVARIANT aPropVar[MAX_VAR];
|
|
QUEUEPROPID aqPropId[MAX_VAR];
|
|
MSGPROPID amPropId[MAX_VAR];
|
|
DWORD cProps;
|
|
|
|
WCHAR wcsFormat[MAX_FORMAT];
|
|
|
|
UCHAR Buffer[MAX_BUFFER];
|
|
WCHAR wcsMsgLabel[MQ_MAX_MSG_LABEL_LEN];
|
|
WCHAR wcsPathName[1000];
|
|
|
|
|
|
DWORD dwNumChars;
|
|
QUEUEHANDLE qh;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
printf("\nReceiver Mode on Machine: %s\n\n", mbsMachineName);
|
|
|
|
|
|
//
|
|
// Prepare properties to create a queue on local machine
|
|
//
|
|
cProps = 0;
|
|
|
|
// Set the PathName
|
|
if(dDirectMode == DIRECT) // Private queue pathname
|
|
{
|
|
swprintf(wcsPathName, L"%S\\private$\\MSMQTest", mbsMachineName);
|
|
}
|
|
else // Public queue pathname
|
|
{
|
|
swprintf(wcsPathName, L"%S\\MSMQTest", mbsMachineName);
|
|
}
|
|
|
|
aqPropId[cProps] = PROPID_Q_PATHNAME;
|
|
aPropVar[cProps].vt = VT_LPWSTR;
|
|
aPropVar[cProps].pwszVal = wcsPathName;
|
|
cProps++;
|
|
|
|
// Set the type of the queue
|
|
// (Will be used to locate all the queues of this type)
|
|
aqPropId[cProps] = PROPID_Q_TYPE;
|
|
aPropVar[cProps].vt = VT_CLSID;
|
|
aPropVar[cProps].puuid = &guidMQTestType;
|
|
cProps++;
|
|
|
|
// Put a description to the queue
|
|
// (Useful for administration through the MSMQ admin tools)
|
|
aqPropId[cProps] = PROPID_Q_LABEL;
|
|
aPropVar[cProps].vt = VT_LPWSTR;
|
|
aPropVar[cProps].pwszVal = L"Sample application of MSMQ SDK";
|
|
cProps++;
|
|
|
|
// Create a QUEUEPROPS structure
|
|
qprops.cProp = cProps;
|
|
qprops.aPropID = aqPropId;
|
|
qprops.aPropVar = aPropVar;
|
|
qprops.aStatus = 0;
|
|
|
|
|
|
//
|
|
// Create the queue
|
|
//
|
|
dwNumChars = MAX_FORMAT;
|
|
hr = MQCreateQueue(
|
|
NULL, // IN: Default security
|
|
&qprops, // IN/OUT: Queue properties
|
|
wcsFormat, // OUT: Format name (OUT)
|
|
&dwNumChars); // IN/OUT: Size of format name
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
//
|
|
// API Fails, not because the queue exists
|
|
//
|
|
if (hr != MQ_ERROR_QUEUE_EXISTS)
|
|
Error("Cannot create queue", hr);
|
|
|
|
//
|
|
// Queue exist, so get its format name
|
|
//
|
|
printf("Queue already exists. Open it anyway.\n");
|
|
|
|
if(dDirectMode == DIRECT)
|
|
// It's a private queue, so we know its format name
|
|
{
|
|
swprintf(wcsFormat, L"DIRECT=OS:%s", wcsPathName);
|
|
}
|
|
else
|
|
// It's a public queue, so we must get it from the DS
|
|
{
|
|
dwNumChars = MAX_FORMAT;
|
|
hr = MQPathNameToFormatName(
|
|
wcsPathName, // IN: Queue pathname
|
|
wcsFormat, // OUT: Format name
|
|
&dwNumChars); // IN/OUT: Size of format name
|
|
|
|
if (FAILED(hr))
|
|
Error("Cannot retrieve format name", hr);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Open the queue for receive access
|
|
//
|
|
hr = MQOpenQueue(
|
|
wcsFormat, // IN: Queue format name
|
|
MQ_RECEIVE_ACCESS, // IN: Want to receive from queue
|
|
0, // IN: Allow sharing
|
|
&qh); // OUT: Handle of open queue
|
|
|
|
//
|
|
// Little bit tricky. MQCreateQueue succeeded but, in case
|
|
// it's a public queue, it does not mean that MQOpenQueue
|
|
// will, because of replication delay. The queue is registered
|
|
// in MQIS, but it might take a replication interval
|
|
// until the replica reaches the server I am connected to.
|
|
// To overcome this, open the queue in a loop.
|
|
//
|
|
// (in this specific case, this can happen only if this
|
|
// program is run on a Backup Server Controller - BSC, or on
|
|
// a client connected to a BSC)
|
|
// To be totally on the safe side, we should have put some code
|
|
// to exit the loop after a few retries, but hey, this is just a sample.
|
|
//
|
|
while (hr == MQ_ERROR_QUEUE_NOT_FOUND)
|
|
{
|
|
printf(".");
|
|
|
|
// Wait a bit
|
|
Sleep(500);
|
|
|
|
// And retry
|
|
hr = MQOpenQueue(wcsFormat, MQ_RECEIVE_ACCESS, 0, &qh);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
Error("Cannot open queue", hr);
|
|
|
|
|
|
//
|
|
// Main receiver loop
|
|
//
|
|
if(dDirectMode == DIRECT)
|
|
{
|
|
printf("\n* Working in direct mode.");
|
|
}
|
|
printf("\n* Waiting for messages...\n");
|
|
|
|
for(;;)
|
|
{
|
|
//
|
|
// Prepare message properties to read
|
|
//
|
|
cProps = 0;
|
|
|
|
// Ask for the body of the message
|
|
amPropId[cProps] = PROPID_M_BODY;
|
|
aPropVar[cProps].vt = VT_UI1 | VT_VECTOR;
|
|
aPropVar[cProps].caub.cElems = sizeof(Buffer);
|
|
aPropVar[cProps].caub.pElems = Buffer;
|
|
cProps++;
|
|
|
|
// Ask for the label of the message
|
|
amPropId[cProps] = PROPID_M_LABEL;
|
|
aPropVar[cProps].vt = VT_LPWSTR;
|
|
aPropVar[cProps].pwszVal = wcsMsgLabel;
|
|
cProps++;
|
|
|
|
// Ask for the length of the label of the message
|
|
amPropId[cProps] = PROPID_M_LABEL_LEN;
|
|
aPropVar[cProps].vt = VT_UI4;
|
|
aPropVar[cProps].ulVal = MQ_MAX_MSG_LABEL_LEN;
|
|
cProps++;
|
|
|
|
// Create a MSGPROPS structure
|
|
msgprops.cProp = cProps;
|
|
msgprops.aPropID = amPropId;
|
|
msgprops.aPropVar = aPropVar;
|
|
msgprops.aStatus = 0;
|
|
|
|
|
|
//
|
|
// Receive the message
|
|
//
|
|
hr = MQReceiveMessage(
|
|
qh, // IN: Queue handle
|
|
INFINITE, // IN: Timeout
|
|
MQ_ACTION_RECEIVE, // IN: Read operation
|
|
&msgprops, // IN/OUT: Message properties to receive
|
|
NULL, // IN/OUT: No overlap
|
|
NULL, // IN: No callback
|
|
NULL, // IN: No cursor
|
|
NULL); // IN: Not part of a transaction
|
|
|
|
if (FAILED(hr))
|
|
Error("Receive message", hr);
|
|
|
|
//
|
|
// Display the received message
|
|
//
|
|
printf("%S : %s\n", wcsMsgLabel, Buffer);
|
|
|
|
//
|
|
// Check for end of app
|
|
//
|
|
if (stricmp(Buffer, "quit") == 0)
|
|
break;
|
|
|
|
} /* while (1) */
|
|
|
|
//
|
|
// Cleanup - Close handle to the queue
|
|
//
|
|
MQCloseQueue(qh);
|
|
|
|
|
|
//
|
|
// Finish - Let's delete the queue from the directory service
|
|
// (We don't need to do it. In case of a public queue, leaving
|
|
// it in the DS enables sender applications to send messages
|
|
// even if the receiver is not available.)
|
|
//
|
|
hr = MQDeleteQueue(wcsFormat);
|
|
if (FAILED(hr))
|
|
Error("Cannot delete queue", hr);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// Sender Mode
|
|
// -----------
|
|
// The sender side does the following:
|
|
//
|
|
// If we work in STANDARD mode:
|
|
// 1. Locates all queues of type "guidMQTestType"
|
|
// 2. Opens handles to all the queues
|
|
// 3. In a loop
|
|
// Sends messages to all those queues
|
|
// 4. Cleans up handles
|
|
//
|
|
// If we work in DIRECT mode:
|
|
// 1. Opens a handle to a private queue labeled
|
|
// "MSMQTest" on the computer specified
|
|
// 2. Sends messages to that queue
|
|
// 3. Cleans up handles
|
|
//-----------------------------------------------------
|
|
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// Sender in STANDARD mode
|
|
//
|
|
//-----------------------------------------------------
|
|
void StandardSender(void)
|
|
{
|
|
DWORD cProps;
|
|
|
|
MQMSGPROPS msgprops;
|
|
MQPROPVARIANT aPropVar[MAX_VAR];
|
|
QUEUEPROPID aqPropId[MAX_VAR];
|
|
MSGPROPID amPropId[MAX_VAR];
|
|
|
|
MQPROPERTYRESTRICTION aPropRestriction[MAX_VAR];
|
|
MQRESTRICTION Restriction;
|
|
|
|
MQCOLUMNSET Column;
|
|
HANDLE hEnum;
|
|
|
|
WCHAR wcsFormat[MAX_FORMAT];
|
|
|
|
UCHAR Buffer[MAX_BUFFER];
|
|
WCHAR wcsMsgLabel[MQ_MAX_MSG_LABEL_LEN];
|
|
|
|
DWORD i;
|
|
|
|
DWORD cQueue;
|
|
DWORD dwNumChars;
|
|
QUEUEHANDLE aqh[MAX_VAR];
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
printf("\nSender Mode on Machine: %s\n\n", mbsMachineName);
|
|
|
|
|
|
//
|
|
// Prepare parameters to locate a queue
|
|
//
|
|
|
|
//
|
|
// 1. Restriction = Queues with PROPID_TYPE = MSMQTest queue type
|
|
//
|
|
cProps = 0;
|
|
aPropRestriction[cProps].rel = PREQ;
|
|
aPropRestriction[cProps].prop = PROPID_Q_TYPE;
|
|
aPropRestriction[cProps].prval.vt = VT_CLSID;
|
|
aPropRestriction[cProps].prval.puuid = &guidMQTestType;
|
|
cProps++;
|
|
|
|
Restriction.cRes = cProps;
|
|
Restriction.paPropRes = aPropRestriction;
|
|
|
|
|
|
//
|
|
// 2. Columnset (i.e. queue properties to retrieve) = queue instance
|
|
//
|
|
cProps = 0;
|
|
aqPropId[cProps] = PROPID_Q_INSTANCE;
|
|
cProps++;
|
|
|
|
Column.cCol = cProps;
|
|
Column.aCol = aqPropId;
|
|
|
|
|
|
//
|
|
// Locate the queues. Issue the query
|
|
//
|
|
hr = MQLocateBegin(
|
|
NULL, // IN: Context must be NULL
|
|
&Restriction, // IN: Restriction
|
|
&Column, // IN: Columns (properties) to return
|
|
NULL, // IN: No need to sort
|
|
&hEnum); // OUT: Enumeration handle
|
|
|
|
if (FAILED(hr))
|
|
Error("LocateBegin", hr);
|
|
|
|
//
|
|
// Get the results (up to MAX_VAR)
|
|
// (For more results, call MQLocateNext in a loop)
|
|
//
|
|
cQueue = MAX_VAR;
|
|
hr = MQLocateNext(
|
|
hEnum, // IN: Enumeration handle
|
|
&cQueue, // IN/OUT: Count of properties
|
|
aPropVar); // OUT: Properties of located queues
|
|
|
|
if (FAILED(hr))
|
|
Error("LocateNext", hr);
|
|
|
|
//
|
|
// And that's it for locate
|
|
//
|
|
hr = MQLocateEnd(hEnum);
|
|
|
|
if (cQueue == 0)
|
|
{
|
|
//
|
|
// Could Not find any queue, so exit
|
|
//
|
|
printf("No queue registered");
|
|
exit(0);
|
|
}
|
|
|
|
|
|
printf("\t%d queue(s) found.\n", cQueue);
|
|
|
|
|
|
//
|
|
// Open a handle for each of the queues found
|
|
//
|
|
for (i = 0; i < cQueue; i++)
|
|
{
|
|
// Convert the queue instance to a format name
|
|
dwNumChars = MAX_FORMAT;
|
|
hr = MQInstanceToFormatName(
|
|
aPropVar[i].puuid, // IN: Queue instance
|
|
wcsFormat, // OUT: Format name
|
|
&dwNumChars); // IN/OUT: Size of format name
|
|
|
|
if (FAILED(hr))
|
|
Error("GuidToFormatName", hr);
|
|
|
|
//
|
|
// Open the queue for send access
|
|
//
|
|
hr = MQOpenQueue(
|
|
wcsFormat, // IN: Queue format name
|
|
MQ_SEND_ACCESS, // IN: Want to send to queue
|
|
0, // IN: Must be 0 for send access
|
|
&aqh[i]); // OUT: Handle of open queue
|
|
|
|
if (FAILED(hr))
|
|
Error("OpenQueue", hr);
|
|
|
|
//
|
|
// Free the GUID memory that was allocated during the locate.
|
|
//
|
|
MQFreeMemory(aPropVar[i].puuid);
|
|
}
|
|
|
|
|
|
printf("\nEnter \"quit\" to exit\n");
|
|
|
|
|
|
//
|
|
// Build the message label property
|
|
//
|
|
swprintf(wcsMsgLabel, L"Message from %S", mbsMachineName);
|
|
|
|
|
|
//
|
|
// Main sender loop
|
|
//
|
|
for(;;)
|
|
{
|
|
//
|
|
// Get a string from the console
|
|
//
|
|
printf("Enter a string: ");
|
|
if (gets(Buffer) == NULL)
|
|
break;
|
|
|
|
|
|
//
|
|
// Prepare properties of message to send
|
|
//
|
|
cProps = 0;
|
|
|
|
// Set the body of the message
|
|
amPropId[cProps] = PROPID_M_BODY;
|
|
aPropVar[cProps].vt = VT_UI1 | VT_VECTOR;
|
|
aPropVar[cProps].caub.cElems = sizeof(Buffer);
|
|
aPropVar[cProps].caub.pElems = Buffer;
|
|
cProps++;
|
|
|
|
// Set the label of the message
|
|
amPropId[cProps] = PROPID_M_LABEL;
|
|
aPropVar[cProps].vt = VT_LPWSTR;
|
|
aPropVar[cProps].pwszVal = wcsMsgLabel;
|
|
cProps++;
|
|
|
|
// Create a MSGPROPS structure
|
|
msgprops.cProp = cProps;
|
|
msgprops.aPropID = amPropId;
|
|
msgprops.aPropVar = aPropVar;
|
|
msgprops.aStatus = 0;
|
|
|
|
|
|
//
|
|
// Send the message to all the queue
|
|
//
|
|
for (i = 0; i < cQueue; i++)
|
|
{
|
|
hr = MQSendMessage(
|
|
aqh[i], // IN: Queue handle
|
|
&msgprops, // IN: Message properties to send
|
|
NULL); // IN: Not part of a transaction
|
|
|
|
if (FAILED(hr))
|
|
Error("Send message", hr);
|
|
}
|
|
|
|
//
|
|
// Check for end of app
|
|
//
|
|
if (stricmp(Buffer, "quit") == 0)
|
|
break;
|
|
|
|
} /* for */
|
|
|
|
|
|
//
|
|
// Close all the queue handles
|
|
//
|
|
for (i = 0; i < cQueue; i++)
|
|
MQCloseQueue(aqh[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// Sender in DIRECT mode
|
|
//
|
|
//-----------------------------------------------------
|
|
void DirectSender(void)
|
|
{
|
|
|
|
MQMSGPROPS msgprops;
|
|
MQPROPVARIANT aPropVar[MAX_VAR];
|
|
MSGPROPID amPropId[MAX_VAR];
|
|
DWORD cProps;
|
|
|
|
WCHAR wcsFormat[MAX_FORMAT];
|
|
WCHAR wcsReceiverComputer[MAX_BUFFER];
|
|
|
|
UCHAR Buffer[MAX_BUFFER];
|
|
WCHAR wcsMsgLabel[MQ_MAX_MSG_LABEL_LEN];
|
|
|
|
QUEUEHANDLE qhSend;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
//
|
|
// Get the receiver computer name
|
|
//
|
|
printf("Enter receiver computer name: ");
|
|
wscanf(L"%s", wcsReceiverComputer);
|
|
if(wcsReceiverComputer[0] == 0)
|
|
{
|
|
printf("You have entered an incorrect parameter. Exiting...\n");
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the queue for send access
|
|
//
|
|
swprintf(wcsFormat, L"DIRECT=OS:%s\\private$\\MSMQTest", wcsReceiverComputer);
|
|
|
|
hr = MQOpenQueue(
|
|
wcsFormat, // IN: Queue format name
|
|
MQ_SEND_ACCESS, // IN: Want to send to queue
|
|
0, // IN: Must be 0 for send access
|
|
&qhSend); // OUT: Handle of open queue
|
|
|
|
if (FAILED(hr))
|
|
Error("OpenQueue", hr);
|
|
|
|
|
|
printf("\nEnter \"quit\" to exit\n");
|
|
|
|
|
|
//
|
|
// Build the message label property
|
|
//
|
|
swprintf(wcsMsgLabel, L"Message from %S", mbsMachineName);
|
|
|
|
|
|
fflush(stdin);
|
|
|
|
//
|
|
// Main sender loop
|
|
//
|
|
for(;;)
|
|
{
|
|
//
|
|
// Get a string from the console
|
|
//
|
|
printf("Enter a string: ");
|
|
if (gets(Buffer) == NULL)
|
|
break;
|
|
|
|
|
|
//
|
|
// Prepare properties of message to send
|
|
//
|
|
cProps = 0;
|
|
|
|
// Set the body of the message
|
|
amPropId[cProps] = PROPID_M_BODY;
|
|
aPropVar[cProps].vt = VT_UI1 | VT_VECTOR;
|
|
aPropVar[cProps].caub.cElems = sizeof(Buffer);
|
|
aPropVar[cProps].caub.pElems = Buffer;
|
|
cProps++;
|
|
|
|
// Set the label of the message
|
|
amPropId[cProps] = PROPID_M_LABEL;
|
|
aPropVar[cProps].vt = VT_LPWSTR;
|
|
aPropVar[cProps].pwszVal = wcsMsgLabel;
|
|
cProps++;
|
|
|
|
// Create a MSGPROPS structure
|
|
msgprops.cProp = cProps;
|
|
msgprops.aPropID = amPropId;
|
|
msgprops.aPropVar = aPropVar;
|
|
msgprops.aStatus = 0;
|
|
|
|
|
|
//
|
|
// Send the message
|
|
//
|
|
hr = MQSendMessage(
|
|
qhSend, // IN: Queue handle
|
|
&msgprops, // IN: Message properties to send
|
|
NULL); // IN: Not part of a transaction
|
|
|
|
if (FAILED(hr))
|
|
Error("Send message", hr);
|
|
|
|
//
|
|
// Check for end of app
|
|
//
|
|
if (stricmp(Buffer, "quit") == 0)
|
|
break;
|
|
|
|
} /* for */
|
|
|
|
|
|
//
|
|
// Close queue handle
|
|
//
|
|
MQCloseQueue(qhSend);
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------
|
|
//
|
|
// Sender function
|
|
//
|
|
//------------------------------------------------------
|
|
void Sender(int dDirectMode)
|
|
{
|
|
|
|
if(dDirectMode == DIRECT)
|
|
DirectSender();
|
|
|
|
else
|
|
StandardSender();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// MAIN
|
|
//
|
|
//-----------------------------------------------------
|
|
main(int argc, char * * argv)
|
|
{
|
|
DWORD dwNumChars;
|
|
int dDirectMode;
|
|
|
|
|
|
if (argc != 2)
|
|
{
|
|
Syntax();
|
|
}
|
|
|
|
//
|
|
// Retrieve machine name
|
|
//
|
|
dwNumChars = MAX_COMPUTERNAME_LENGTH + 1;
|
|
GetComputerName(mbsMachineName, &dwNumChars);
|
|
|
|
//
|
|
// Detect DS connection and working mode
|
|
//
|
|
|
|
dDirectMode = SetConnectionMode();
|
|
|
|
if(strcmp(argv[1], "-s") == 0)
|
|
Sender(dDirectMode);
|
|
|
|
else if (strcmp(argv[1], "-r") == 0)
|
|
Receiver(dDirectMode);
|
|
|
|
else
|
|
Syntax();
|
|
|
|
|
|
printf("\nOK\n");
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
void Error(char *s, HRESULT hr)
|
|
{
|
|
printf("Error: %s (0x%X)\n", s, hr);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
void Syntax()
|
|
{
|
|
printf("\n");
|
|
printf("Syntax: msmqtest -s | -r\n");
|
|
printf("\t-s: Sender\n");
|
|
printf("\t-r: Receiver\n");
|
|
exit(1);
|
|
}
|