You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
9.6 KiB
315 lines
9.6 KiB
|
|
#include <Windows.h>
|
|
#include <objBase.h>
|
|
#include <stdio.h>
|
|
#include <mqoai.h> // MSMQ include file
|
|
// Existing code
|
|
|
|
//-----------------------------------------------------
|
|
//
|
|
// Check if local computer is DS enabled or DS disabled
|
|
//
|
|
//-----------------------------------------------------
|
|
short DetectDsConnection(void)
|
|
{
|
|
IMSMQApplication2 *pqapp = NULL;
|
|
short fDsConnection;
|
|
HRESULT hresult;
|
|
|
|
hresult = CoCreateInstance(
|
|
CLSID_MSMQApplication,
|
|
NULL, // punkOuter
|
|
CLSCTX_SERVER,
|
|
IID_IMSMQApplication2,
|
|
(LPVOID *)&pqapp);
|
|
|
|
if (FAILED(hresult))
|
|
PRINTERROR("Cannot create application", hresult);
|
|
|
|
pqapp->get_IsDsEnabled(&fDsConnection);
|
|
|
|
Cleanup:
|
|
RELEASE(pqapp);
|
|
return fDsConnection;
|
|
}
|
|
|
|
|
|
// Split this routine into initialize and get next file path
|
|
//--------------------------------------------------------
|
|
//
|
|
// Receiver Mode
|
|
// -------------
|
|
// The receiver side does the following:
|
|
// 1. Creates a queue on its given computer'
|
|
// of type "guidMQTestType".
|
|
// 2. Opens the queue
|
|
// 3. In a Loop
|
|
// Receives messages
|
|
// Prints message body and message label
|
|
// Launches debugger
|
|
// 4. Cleanup handles
|
|
// 5. Deletes the queue from the directory service
|
|
//
|
|
//--------------------------------------------------------
|
|
// rename this function to reciever
|
|
HRESULT CMessageQueue::Initialize(/* send connect params*/)
|
|
{
|
|
IMSMQMessage *pmessageReceive = NULL;
|
|
IMSMQQueue *pqReceive = NULL;
|
|
IMSMQQueueInfo *pqinfo = NULL;
|
|
BSTR bstrPathName = NULL;
|
|
BSTR bstrServiceType = NULL;
|
|
BSTR bstrLabel = NULL;
|
|
BSTR bstrMsgLabel = NULL;
|
|
VARIANT varIsTransactional, varIsWorldReadable, varBody, varBody2, varWantDestQueue, varWantBody, varReceiveTimeout;
|
|
WCHAR wcsPathName[1000];
|
|
BOOL fQuit = FALSE;
|
|
HRESULT hresult = NOERROR;
|
|
|
|
/* printf("\nReceiver for queue %s on machine %s\nLimit memusage to %ld%%\n",
|
|
g_QueueName,
|
|
g_ServerMachine,
|
|
g_MaxMemUsage);
|
|
*/
|
|
//
|
|
// Create MSMQQueueInfo object
|
|
//
|
|
hresult = CoCreateInstance(
|
|
CLSID_MSMQQueueInfo,
|
|
NULL, // punkOuter
|
|
CLSCTX_SERVER,
|
|
IID_IMSMQQueueInfo,
|
|
(LPVOID *)&pqinfo);
|
|
if (FAILED(hresult))
|
|
{
|
|
//PRINTERROR("Cannot create queue instance", hresult);
|
|
}
|
|
|
|
//
|
|
// Prepare properties to create a queue on local machine
|
|
//
|
|
|
|
if (g_FormatName[0])
|
|
{
|
|
// access by formatname
|
|
// Set the FormatName
|
|
swprintf(wcsPathName, L"DIRECT=%S\\%S", g_FormatName,g_QueueName);
|
|
|
|
//printf("Openeing q byt formatname: %ws\n", wcsPathName);
|
|
bstrPathName = SysAllocString(wcsPathName);
|
|
if (bstrPathName == NULL)
|
|
{
|
|
// PRINTERROR("OOM: formatname", E_OUTOFMEMORY);
|
|
}
|
|
pqinfo->put_FormatName(bstrPathName);
|
|
} else
|
|
{
|
|
// access by pathname
|
|
// Set the PathName
|
|
swprintf(wcsPathName, L"%S\\%S", g_ServerMachine,g_QueueName);
|
|
|
|
//printf("Openeing q %ws\n", wcsPathName);
|
|
bstrPathName = SysAllocString(wcsPathName);
|
|
if (bstrPathName == NULL)
|
|
{
|
|
// PRINTERROR("OOM: pathname", E_OUTOFMEMORY);
|
|
}
|
|
pqinfo->put_PathName(bstrPathName);
|
|
}
|
|
|
|
//
|
|
// Set the type of the queue
|
|
// (Will be used to locate all the queues of this type)
|
|
//
|
|
bstrServiceType = SysAllocString(strGuidMQTestType);
|
|
if (bstrServiceType == NULL)
|
|
{
|
|
PRINTERROR("OOM: ServiceType", E_OUTOFMEMORY);
|
|
}
|
|
pqinfo->put_ServiceTypeGuid(bstrServiceType);
|
|
|
|
//
|
|
// Put a description to the queue
|
|
// (Useful for administration through the MSMQ admin tools)
|
|
//
|
|
bstrLabel =
|
|
SysAllocString(L"MSMQ for dumpfiles");
|
|
if (bstrLabel == NULL)
|
|
{
|
|
//PRINTERROR("OOM: label ", E_OUTOFMEMORY);
|
|
}
|
|
pqinfo->put_Label(bstrLabel);
|
|
|
|
//
|
|
// specify if transactional
|
|
//
|
|
VariantInit(&varIsTransactional);
|
|
varIsTransactional.vt = VT_BOOL;
|
|
varIsTransactional.boolVal = MQ_TRANSACTIONAL_NONE;
|
|
VariantInit(&varIsWorldReadable);
|
|
varIsWorldReadable.vt = VT_BOOL;
|
|
varIsWorldReadable.boolVal = FALSE;
|
|
//
|
|
// create the queue
|
|
//
|
|
if (g_CreateQ)
|
|
{
|
|
hresult = pqinfo->Create(&varIsTransactional, &varIsWorldReadable);
|
|
if (FAILED(hresult))
|
|
{
|
|
//
|
|
// API Fails, not because the queue exists
|
|
//
|
|
if (hresult != MQ_ERROR_QUEUE_EXISTS)
|
|
// PRINTERROR("Cannot create queue", hresult);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Open the queue for receive access
|
|
//
|
|
hresult = pqinfo->Open(MQ_RECEIVE_ACCESS,
|
|
MQ_DENY_NONE,
|
|
&pqReceive);
|
|
|
|
//
|
|
// 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 (hresult == MQ_ERROR_QUEUE_NOT_FOUND && iCurrentRetry < g_MaxRetry)
|
|
{
|
|
// printf(".");
|
|
fflush(stdout);
|
|
|
|
// Wait a bit
|
|
Sleep(500);
|
|
|
|
// And retry
|
|
hresult = pqinfo->Open(MQ_RECEIVE_ACCESS,
|
|
MQ_DENY_NONE,
|
|
&pqReceive);
|
|
}
|
|
if (FAILED(hresult))
|
|
{
|
|
// PRINTERROR("Cannot open queue", hresult);
|
|
//We sould stop here
|
|
}
|
|
|
|
g_DumpPath[0] = 0;
|
|
|
|
//
|
|
// Main receiver loop
|
|
//
|
|
// printf("\nWaiting for messages ...\n");
|
|
// while (!fQuit)
|
|
// {
|
|
// MEMORYSTATUS stat;
|
|
|
|
//--------------------------------------------------------------------------------------//
|
|
// this goes into GetNextFilePath()
|
|
//--------------------------------------------------------------------------------------//
|
|
ULONG nWaitCount;
|
|
|
|
//
|
|
// Receive the message
|
|
//
|
|
VariantInit(&varWantDestQueue);
|
|
VariantInit(&varWantBody);
|
|
VariantInit(&varReceiveTimeout);
|
|
varWantDestQueue.vt = VT_BOOL;
|
|
varWantDestQueue.boolVal = TRUE; // yes we want the dest queue
|
|
varWantBody.vt = VT_BOOL;
|
|
varWantBody.boolVal = TRUE; // yes we want the msg body
|
|
varReceiveTimeout.vt = VT_I4;
|
|
varReceiveTimeout.lVal = INFINITE; // infinite timeout <--- This needs to be set to a reasonable value so that we
|
|
// can bounce between queues.
|
|
hresult = pqReceive->Receive(
|
|
NULL,
|
|
&varWantDestQueue,
|
|
&varWantBody,
|
|
&varReceiveTimeout,
|
|
&pmessageReceive);
|
|
if (FAILED(hresult))
|
|
{
|
|
// PRINTERROR("Receive message", hresult);
|
|
// we should stop here
|
|
}
|
|
|
|
//
|
|
// Display the received message
|
|
//
|
|
pmessageReceive->get_Label(&bstrMsgLabel);
|
|
VariantInit(&varBody);
|
|
VariantInit(&varBody2);
|
|
hresult = pmessageReceive->get_Body(&varBody);
|
|
if (FAILED(hresult))
|
|
{
|
|
// PRINTERROR("can't get body", hresult);
|
|
//log event nd exit
|
|
}
|
|
hresult = VariantChangeType(&varBody2,
|
|
&varBody,
|
|
0,
|
|
VT_BSTR);
|
|
if (FAILED(hresult))
|
|
{
|
|
// PRINTERROR("can't convert message to string.", hresult);
|
|
// log event and exit
|
|
}
|
|
|
|
VariantClear(&varBody);
|
|
VariantClear(&varBody2);
|
|
|
|
//
|
|
// release the current message
|
|
//
|
|
RELEASE(pmessageReceive);
|
|
|
|
|
|
//
|
|
// Cleanup - Close handle to the queue
|
|
//
|
|
pqReceive->Close();
|
|
if (FAILED(hresult))
|
|
{
|
|
// PRINTERROR("Cannot close queue", hresult);
|
|
// Log Error and Exit
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------------//
|
|
// This code goes in the constructor.
|
|
//-----------------------------------------------------------------------------------//
|
|
// Move this to class destructor
|
|
// 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.)
|
|
//
|
|
hresult = pqinfo->Delete();
|
|
if (FAILED(hresult))
|
|
{
|
|
PRINTERROR("Cannot delete queue", hresult);
|
|
}
|
|
// fall through...
|
|
|
|
Cleanup:
|
|
SysFreeString(bstrPathName);
|
|
SysFreeString(bstrMsgLabel);
|
|
SysFreeString(bstrServiceType);
|
|
SysFreeString(bstrLabel);
|
|
RELEASE(pmessageReceive);
|
|
RELEASE(pqReceive);
|
|
RELEASE(pqinfo);
|
|
return hresult;
|
|
*/
|
|
}
|