home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************\
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1996 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 ActiveX MSMQ apps
- //
- #include "mqoai.h"
-
- //
- // Various defines
- //
- #define MAX_VAR 20
- #define MAX_BUFFER 500
-
-
- //
- // GUID created with the tool "GUIDGEN"
- //
- static WCHAR strGuidMQTestType[] =
- L"{c30e0960-a2c0-11cf-9785-00608cb3e80c}";
- //
- // Prototypes
- //
- void PrintError(char *s, HRESULT hr);
- HRESULT Syntax();
-
- char mbsMachineName[MAX_COMPUTERNAME_LENGTH + 1];
-
- // Some useful macros
- #define RELEASE(punk) if (punk) { (punk)->Release(); (punk) = NULL; }
- #define ADDREF(punk) ((punk) ? (punk)->AddRef() : 0)
- #define PRINTERROR(s, hr) { PrintError(s, hr); goto Cleanup; }
-
-
- //-----------------------------------------------------
- //
- // Receiver Mode
- // -------------
- // The receiver side does the following:
- // 1. Creates a public queue on its own machine
- // of type "strGuidMQTestType"
- // 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
- //
- //-----------------------------------------------------
- HRESULT Receiver()
- {
- 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 Mode on Machine: %s\n\n", mbsMachineName);
-
- //
- // Create MSMQQueueInfo object
- //
- hresult = CoCreateInstance(
- CLSID_MSMQQueueInfo,
- NULL, // punkOuter
- CLSCTX_SERVER,
- IID_IMSMQQueueInfo,
- (LPVOID *)&pqinfo);
- if (FAILED(hresult)) {
- PRINTERROR("Cannot create queue", hresult);
- }
-
- //
- // Prepare properties to create a queue on local machine
- //
-
- // Set the PathName
- swprintf(wcsPathName, L"%S\\MSMQTest", mbsMachineName);
- 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"Sample ActiveX application of MSMQ SDK");
- 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
- //
- 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 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 reach 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) {
- printf(".");
-
- // 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);
- }
-
- //
- // Main receiver loop
- //
- printf("\nWaiting for messages...\n");
- while (!fQuit) {
- //
- // 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
- hresult = pqReceive->Receive(
- NULL,
- &varWantDestQueue,
- &varWantBody,
- &varReceiveTimeout,
- &pmessageReceive);
- if (FAILED(hresult)) {
- PRINTERROR("Receive message", hresult);
- }
-
- //
- // 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);
- }
- hresult = VariantChangeType(&varBody2,
- &varBody,
- 0,
- VT_BSTR);
- if (FAILED(hresult)) {
- PRINTERROR("can't convert message to string.", hresult);
- }
- printf("%S : %s\n", bstrMsgLabel, V_BSTR(&varBody2));
- //
- // Check for end of app
- //
- if (stricmp((char *)V_BSTR(&varBody2), "quit") == 0) {
- fQuit = TRUE;
- }
-
- VariantClear(&varBody);
- VariantClear(&varBody2);
-
- //
- // release the current message
- //
- RELEASE(pmessageReceive);
- } /* while (1) */
-
- //
- // Cleanup - Close handle to the queue
- //
- pqReceive->Close();
- if (FAILED(hresult)) {
- PRINTERROR("Cannot close queue", hresult);
- }
-
- //
- // Finish - Let's delete the queue from the directory service
- // (We don't need to do it. Leaving the queue 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;
- }
-
-
- //-----------------------------------------------------
- //
- // Sender Mode
- // -----------
- // The sender side does the following:
- // 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. Cleanup handles
- //
- //-----------------------------------------------------
- HRESULT Sender()
- {
- IMSMQQuery *pquery = NULL;
- IMSMQQueueInfo *rgpqinfo[MAX_VAR];
- IMSMQQueue *rgpqSend[MAX_VAR];
- IMSMQQueueInfo *pqinfo = NULL;
- IMSMQQueueInfos *pqinfos = NULL;
- IMSMQMessage *pmessage = NULL;
- char *szBuffer = new char[MAX_BUFFER];
- WCHAR wcsMsgLabel[MQ_MAX_MSG_LABEL_LEN];
- BSTR bstrServiceType = NULL;
- BSTR bstrLabel = NULL;
- BSTR bstrBody = NULL;
- VARIANT varBody;
- DWORD i;
- DWORD cQueue = 0;
- HRESULT hresult = NOERROR;
-
- printf("\nSender Mode on Machine: %s\n\n", mbsMachineName);
-
- //
- // create query object for lookup
- //
- hresult = CoCreateInstance(
- CLSID_MSMQQuery,
- NULL, // punkOuter
- CLSCTX_SERVER,
- IID_IMSMQQuery,
- (LPVOID *)&pquery);
- if (FAILED(hresult)) {
- PRINTERROR("Cannot create query", hresult);
- }
-
- //
- // Prepare parameters to locate a queue: all queues that
- // match test guid type
- //
- VARIANT varGuidQueue;
- VARIANT varStrLabel;
- VARIANT varGuidServiceType;
- VARIANT varRelServiceType;
- VARIANT varRelLabel;
- VARIANT varCreateTime;
- VARIANT varModifyTime;
- VARIANT varRelCreateTime;
- VARIANT varRelModifyTime;
-
- VariantInit(&varGuidQueue);
- VariantInit(&varStrLabel);
- VariantInit(&varGuidServiceType);
- VariantInit(&varRelServiceType);
- VariantInit(&varRelLabel);
- VariantInit(&varCreateTime);
- VariantInit(&varModifyTime);
- VariantInit(&varRelCreateTime);
- VariantInit(&varRelModifyTime);
-
- //
- // We only want to specify service type so we set
- // the other variant params to VT_ERROR to simulate
- // "missing", i.e. optional, params.
- //
- V_VT(&varGuidQueue) = VT_ERROR;
- V_VT(&varStrLabel) = VT_ERROR;
- V_VT(&varRelServiceType) = VT_ERROR;
- V_VT(&varRelLabel) = VT_ERROR;
- V_VT(&varCreateTime) = VT_ERROR;
- V_VT(&varModifyTime) = VT_ERROR;
- V_VT(&varRelCreateTime) = VT_ERROR;
- V_VT(&varRelModifyTime) = VT_ERROR;
- bstrServiceType = SysAllocString(strGuidMQTestType);
- if (bstrServiceType == NULL) {
- PRINTERROR("OOM: Service Type", E_OUTOFMEMORY);
- }
- V_VT(&varGuidServiceType) = VT_BSTR;
- V_BSTR(&varGuidServiceType) = bstrServiceType;
-
- hresult = pquery->LookupQueue(&varGuidQueue,
- &varGuidServiceType,
- &varStrLabel,
- &varCreateTime,
- &varModifyTime,
- &varRelServiceType,
- &varRelLabel,
- &varRelCreateTime,
- &varRelModifyTime,
- &pqinfos);
- if (FAILED(hresult)) {
- PRINTERROR("LookupQueue failed", hresult);
- }
-
- //
- // reset the queue collection
- //
- hresult = pqinfos->Reset();
- if (FAILED(hresult)) {
- PRINTERROR("Reset failed", hresult);
- }
-
- //
- // Open each of the queues found
- //
- i = 0;
- hresult = pqinfos->Next(&rgpqinfo[i]);
- if (FAILED(hresult)) {
- PRINTERROR("Next failed", hresult);
- }
- pqinfo = rgpqinfo[i];
- while (pqinfo) {
- //
- // Open the queue for send access
- //
- hresult = pqinfo->Open(
- MQ_SEND_ACCESS,
- MQ_DENY_NONE,
- &rgpqSend[i]);
- if (FAILED(hresult)) {
- PRINTERROR("Open failed", hresult);
- }
- i++;
- hresult = pqinfos->Next(&rgpqinfo[i]);
- if (FAILED(hresult)) {
- PRINTERROR("Next failed", hresult);
- }
- pqinfo = rgpqinfo[i];
- }
- cQueue = i;
- if (cQueue == 0) {
- //
- // Could Not find any queue, so exit
- //
- PRINTERROR("No queue registered", hresult = E_INVALIDARG);
- }
- printf("\t%d queue(s) found.\n", cQueue);
- printf("\nEnter \"quit\" to exit\n");
-
-
- //
- // Build the message label property
- //
- swprintf(wcsMsgLabel, L"Message from %S", mbsMachineName);
-
-
- //
- // Main sender loop
- //
- while (1) {
- //
- // Get a string from the console
- //
- printf("Enter a string: ");
- if (gets(szBuffer) == NULL)
- break;
-
-
- //
- // create a message object
- //
- hresult = CoCreateInstance(
- CLSID_MSMQMessage,
- NULL, // punkOuter
- CLSCTX_SERVER,
- IID_IMSMQMessage,
- (LPVOID *)&pmessage);
- //
- // Send the message to all the queues
- //
- for (i = 0; i < cQueue; i++) {
- bstrLabel = SysAllocString(wcsMsgLabel);
- if (bstrLabel == NULL) {
- PRINTERROR("OOM: label", E_OUTOFMEMORY);
- }
- hresult = pmessage->put_Label(bstrLabel);
-
- //
- // This isn't a "true" unicode string of course...
- //
- bstrBody = SysAllocStringByteLen(szBuffer, strlen(szBuffer)+1);
- if (bstrBody == NULL) {
- PRINTERROR("OOM: body", E_OUTOFMEMORY);
- }
- VariantInit(&varBody);
- V_VT(&varBody) = VT_BSTR;
- V_BSTR(&varBody) = bstrBody;
- hresult = pmessage->put_Body(varBody);
- if (FAILED(hresult)) {
- PRINTERROR("put_body failed", hresult);
- }
- hresult = pmessage->Send(rgpqSend[i], NULL);
- if (FAILED(hresult)) {
- PRINTERROR("Send failed", hresult);
- }
- VariantClear(&varBody);
- bstrBody = NULL;
- }
- RELEASE(pmessage);
-
- //
- // Check for end of app
- //
- if (stricmp(szBuffer, "quit") == 0)
- break;
- } /* while (1) */
-
-
-
- Cleanup:
- //
- // Close and release all the queues
- //
- for (i = 0; i < cQueue; i++) {
- rgpqSend[i]->Close();
- rgpqSend[i]->Release();
- rgpqinfo[i]->Release();
- }
- RELEASE(pqinfos);
- RELEASE(pquery);
- RELEASE(pmessage);
- SysFreeString(bstrLabel);
- SysFreeString(bstrBody);
- SysFreeString(bstrServiceType);
- delete [] szBuffer;
- return hresult;
- }
-
-
- //-----------------------------------------------------
- //
- // MAIN
- //
- //-----------------------------------------------------
- int main(int argc, char * * argv)
- {
- DWORD dwNumChars;
- HRESULT hresult = NOERROR;
-
- if (argc != 2)
- return Syntax();
-
- hresult = OleInitialize(NULL);
- if (FAILED(hresult)) {
- PRINTERROR("Cannot init OLE", hresult);
- }
-
-
- //
- // Retrieve machine name
- //
- dwNumChars = MAX_COMPUTERNAME_LENGTH + 1;
- GetComputerNameA(mbsMachineName, &dwNumChars);
-
-
- if (strcmp(argv[1], "-s") == 0)
- hresult = Sender();
-
- else if (strcmp(argv[1], "-r") == 0)
- hresult = Receiver();
-
- else
- hresult = Syntax();
-
- printf("\nOK\n");
-
- // fall through...
-
-
- Cleanup:
- return (int)hresult;
- }
-
-
- void PrintError(char *s, HRESULT hr)
- {
- printf("Cleanup: %s (0x%X)\n", s, hr);
- }
-
-
- HRESULT Syntax()
- {
- printf("\n");
- printf("Syntax: mqtestoa -s | -r\n");
- printf("\t-s: Sender\n");
- printf("\t-r: Receiver\n");
- return E_INVALIDARG;
- }
-