#include #include #include #include // 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; */ }