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 MSMQ apps
- //
- #include "mq.h"
-
-
- //
- // Various defines
- //
- #define MAX_VAR 20
- #define MAX_FORMAT 100
- #define MAX_BUFFER 500
-
-
- //
- // 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];
-
-
- //-----------------------------------------------------
- //
- // Receiver Mode
- // -------------
- // The receiver side does the following:
- // 1. Creates a public queue on its own machine
- // of type "guidMQTestType"
- // 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()
- {
-
- 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
- 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");
-
- 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 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 (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
- //
- printf("\nWaiting for messages...\n");
- while (1)
- {
- //
- // 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. Leaving the queue 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:
- // 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
- //
- //-----------------------------------------------------
- void Sender()
- {
- 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
- //
- while (1)
- {
- //
- // 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;
-
- } /* while (1) */
-
-
- //
- // Close all the queue handles
- //
- for (i = 0; i < cQueue; i++)
- MQCloseQueue(aqh[i]);
-
- }
-
-
- //-----------------------------------------------------
- //
- // MAIN
- //
- //-----------------------------------------------------
- main(int argc, char * * argv)
- {
- DWORD dwNumChars;
-
-
- if (argc != 2)
- Syntax();
-
-
- //
- // Retrieve machine name
- //
- dwNumChars = MAX_COMPUTERNAME_LENGTH + 1;
- GetComputerName(mbsMachineName, &dwNumChars);
-
-
- if (strcmp(argv[1], "-s") == 0)
- Sender();
-
- else if (strcmp(argv[1], "-r") == 0)
- Receiver();
-
- 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);
- }
-