Esempio n. 1
0
HRESULT MsmqQueue::read(     char    *szMessageBody,
                             int     *iMessageBodySize,
							 int     *iMessageBodyType,
                             char    *szLabel,
                             char    *szCorrelationID,
							 bool    isTransactional,
                             int     iTimeout, 
                             bool    isPeekOnly
                             )
{
    const int NUMBEROFPROPERTIES = 8;
    DWORD i = 0;
    HRESULT hr = MQ_OK;
	
    DWORD dwAction= isPeekOnly ? MQ_ACTION_PEEK_CURRENT : MQ_ACTION_RECEIVE;
	ITransaction* pTransaction = isTransactional ? MQ_SINGLE_MESSAGE : MQ_NO_TRANSACTION;

    MQMSGPROPS msgprops;
    MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];
    PROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];

	// Message Body Buffer
	if (szMessageBody!=NULL)
	{
		memset(szMessageBody, 0, *iMessageBodySize);
		aMsgPropId[i] = PROPID_M_BODY;
		aMsgPropVar[i].vt = VT_VECTOR | VT_UI1;
		aMsgPropVar[i].caub.pElems = (LPBYTE)szMessageBody;
		aMsgPropVar[i].caub.cElems = *iMessageBodySize;
		i++;
	}

	// Message Body Size
	aMsgPropId[i] = PROPID_M_BODY_SIZE;
	aMsgPropVar[i].vt = VT_NULL;
	i++;
	
	// Message Body Type
	aMsgPropId[i] = PROPID_M_BODY_TYPE;
	aMsgPropVar[i].vt = VT_NULL;
	i++;

	// Correlation ID
	aMsgPropId[i] = PROPID_M_CORRELATIONID;
    aMsgPropVar[i].vt = VT_VECTOR | VT_UI1;
    aMsgPropVar[i].caub.pElems = (LPBYTE)szCorrelationID;
    aMsgPropVar[i].caub.cElems = PROPID_M_CORRELATIONID_SIZE;
	memset(szCorrelationID, 0, PROPID_M_CORRELATIONID_SIZE);
    i++;

	// Label Size
    aMsgPropId[i] = PROPID_M_LABEL_LEN;            // Property ID
    aMsgPropVar[i].vt =VT_UI4;                     // Type indicator
    aMsgPropVar[i].ulVal = MQ_MAX_MSG_LABEL_LEN;   // Label buffer size
    i++;

	// Label Buffer
    WCHAR wszLabelBuffer[MQ_MAX_MSG_LABEL_LEN] = {0};
    aMsgPropId[i] = PROPID_M_LABEL;
    aMsgPropVar[i].vt = VT_LPWSTR;
    aMsgPropVar[i].pwszVal = wszLabelBuffer;
    i++;

    // NB: if you want to get PROPID_M_RESP_QUEUE, you must also request PROPID_M_RESP_QUEUE_LEN. 
    // that implies 2 additional properties to request. 
    // see http://msdn.microsoft.com/library/en-us/msmq/html/ea8cfb28-43e0-4041-9add-11080375690c.asp

    msgprops.cProp = i;                         // Number of message properties
    msgprops.aPropID = aMsgPropId;                    // IDs of the message properties
    msgprops.aPropVar = aMsgPropVar;                  // Values of the message properties
    msgprops.aStatus  = 0;			  // Error reports

    hr = MQReceiveMessage(
			  hQueue,             // Handle to the destination queue
			  iTimeout,	      // Time out interval
			  dwAction,           // Peek?  or Dequeue.  Receive action
			  &msgprops,          // Pointer to the MQMSGPROPS structure
			  NULL, NULL, NULL,   // No OVERLAPPED structure etc.
			  pTransaction  // MQ_SINGLE_MESSAGE | MQ_MTS_TRANSACTION |
			                     // MQ_XA_TRANSACTION   
			  );
			  
	// http://msdn.microsoft.com/library/en-us/intl/unicode_2bj9.asp
	memset(szLabel, 0, MQ_MAX_MSG_LABEL_LEN);
	if (0 != WideCharToMultiByte(
					 CP_ACP,                // code page
					 0,                    // conversion flags
					 wszLabelBuffer,     // wide-character string to convert
					 (int) wcslen(wszLabelBuffer), // number of chars in string.
					 szLabel,                // buffer for new string
					 MQ_MAX_MSG_LABEL_LEN,         // size of buffer
					 NULL,                // (LPCSTR) default for unmappable chars
					 NULL                 // (LPBOOL) set when default char used
					 )) {
		// actually converted, so... we are happy...
	}

	for(ULONG prop = 0 ; prop < msgprops.cProp; ++prop)
	{
		if (msgprops.aPropID[prop]==PROPID_M_BODY_SIZE)
			*iMessageBodySize = msgprops.aPropVar[prop].ulVal;
		if (msgprops.aPropID[prop]==PROPID_M_BODY_TYPE)
			*iMessageBodyType = msgprops.aPropVar[prop].ulVal;
	}


    return hr;
};
//--------------------------------------------------------
//
// Receiver Mode
// -------------
// The receiver side does the following:
//    1. Creates a queue on the local computer
//       of type "guidMQTestType".
//       The queue is either public or private, depending
//       on the connection we want to establish.
//    2. Opens the queue.
//    3. In a loop,
//          receives messages
//          and prints the message body and message label.
//    4. Cleans up 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+1];
    WCHAR         wcsPathName[MAX_FORMAT];


    DWORD         dwNumChars;
    QUEUEHANDLE   qh;

    HRESULT       hr;
	int			  nPos;

    printf("\nReceiver Mode on Machine: %s\n\n", mbsMachineName);


    //
    // Set properties to create a queue on the local computer.
    //
    cProps = 0;

    // Set the path name.
    if(dDirectMode == DIRECT)  // Private queue path name
    {
		nPos = _snwprintf_s(
                           wcsPathName, 
                           sizeof(wcsPathName)/sizeof(wcsPathName[0]), 
                           sizeof(wcsPathName)/sizeof(wcsPathName[0]) - 1, 
                           L"%S\\private$\\MSMQTest", 
                           mbsMachineName
                           );
		if(nPos < 0)
		{
			printf("The path name is too long for the buffer. Exiting...\n");
			exit(1);
		}	

    }
    else                       // Public queue path name
    {    
		nPos = _snwprintf_s(
                           wcsPathName, 
                           sizeof(wcsPathName)/sizeof(wcsPathName[0]), 
                           sizeof(wcsPathName)/sizeof(wcsPathName[0]) - 1, 
                           L"%S\\MSMQTest", 
                           mbsMachineName
                           );
		if(nPos < 0)
		{
			printf("The path name is too long for the buffer. Exiting...\n");
			exit(1);
		}	

    }

    aqPropId[cProps]         = PROPID_Q_PATHNAME;
    aPropVar[cProps].vt      = VT_LPWSTR;
    aPropVar[cProps].pwszVal = wcsPathName;
    cProps++;

    // Specify the service type GUID of the queue.
    // (This property 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++;

    // Add a descriptive label to the queue.
    // (A label is 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
            &dwNumChars);   // IN/OUT: Size of the format name

    if (FAILED(hr))
    {
        //
        // API failed, but not because the queue exists.
        //
        if (hr != MQ_ERROR_QUEUE_EXISTS)
            Error("MQCreateQueue failed", hr);

        //
        // The queue exist, so get its format name.
        //
        printf("The queue already exists. Open it anyway.\n");

        if(dDirectMode == DIRECT)
        // It's a private queue, so we know its direct format name.
        {
			int n = _snwprintf_s(
                                    wcsFormat, 
                                    sizeof(wcsFormat)/sizeof(wcsFormat[0]), 
                                    sizeof(wcsFormat)/sizeof(wcsFormat[0]) - 1, 
                                    L"DIRECT=OS:%s", 
                                    wcsPathName);
			if(n < 0)
			{
				printf("The format name is too long for the buffer. Exiting...\n");
				exit(1);
			}	

        }
        else
        // It's a public queue, so we must get its format name from the DS.
        {
            dwNumChars = sizeof(wcsFormat)/sizeof(wcsFormat[0]);
            hr = MQPathNameToFormatName(
                       wcsPathName,     // IN:     Queue path name
                       wcsFormat,       // OUT:    Format name
                       &dwNumChars);    // IN/OUT: Size of the format name

            if (FAILED(hr))
                Error("The format name cannot be retrieved", hr);
        }
    }


    //
    // Open the queue with 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

    //
    // Things are a little bit tricky. MQCreateQueue succeeded, but in the 
    // case of a public queue, this does not mean that MQOpenQueue
    // will succeed, because replication delays are possible. The queue is
    // registered in the DS, but it might take a replication interval
    // until the replica reaches the server that 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 an MSMQ 1.0 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 this is just a sample.
    //
    while (hr == MQ_ERROR_QUEUE_NOT_FOUND)
    {
       printf(".");

       // Wait a bit.
       Sleep(500);

       // Retry.
       hr = MQOpenQueue(wcsFormat, MQ_RECEIVE_ACCESS, 0, &qh);
    }

    if (FAILED(hr))
         Error("The queue cannot be opened", hr);


    //
    // Main receiver loop
    //
    if(dDirectMode == DIRECT)
    {
        printf("\n* Working in workgroup (direct) mode.\n");
    }
    printf("\n* Waiting for messages...\n");
    
    for(;;)
    {
        //
        // Set the message properties for reading messages.
        //
        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   = sizeof(wcsMsgLabel);
        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:     Time-out
               MQ_ACTION_RECEIVE, // IN:     Read operation
               &msgprops,         // IN/OUT: Message properties to retrieve
               NULL,              // IN/OUT: No OVERLAPPED structure
               NULL,              // IN:     No callback
               NULL,              // IN:     No cursor
               NULL);             // IN:     Not part of a transaction

        if (FAILED(hr))
            Error("MQReceiveMessage failed", hr);

        //
        // Display the received message.
        //
        printf("%S : %s\n", wcsMsgLabel, Buffer);

        //
        // Check for a request to end the application.
        //
        if (_stricmp(Buffer, "quit") == 0)
            break;

    } /* while (1) */

    //
    // Cleanup: Close the handle to the queue.
    //
    MQCloseQueue(qh);


    //
    // In the concluding stage, we delete the queue from the directory
    // service. (We don't need to do this. 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("The queue cannot be deleted", hr);
}
Esempio n. 3
0
DWORD ReceiveUpdates(CDisdrawDlg *pDrawDlg)
{
   	//
	// Prepare the message properties to receive.
	//
	DWORD cProps = 0;
	MQMSGPROPS    propsMessage;
	MQPROPVARIANT aPropVar[2];
	MSGPROPID     aPropId[2];

	WCHAR wcsBody[MAX_MSG_BODY_LEN+1];
	aPropId[cProps]				= PROPID_M_BODY;
	aPropVar[cProps].vt			= VT_UI1 | VT_VECTOR;
	aPropVar[cProps].caub.cElems = sizeof(wcsBody);
	aPropVar[cProps].caub.pElems = (UCHAR *)wcsBody;
	cProps++;

    aPropId[cProps]				= PROPID_M_BODY_SIZE;
	aPropVar[cProps].vt			= VT_UI4;
	cProps++;

	propsMessage.cProp    = cProps;
	propsMessage.aPropID  = aPropId;
	propsMessage.aPropVar = aPropVar;
	propsMessage.aStatus  = NULL;


    //
    // Keep receiving updates sent to the incoming queue.
    //
    HRESULT hr;
    LINE line;
	char mbsBody[MAX_MSG_BODY_LEN + 1];

    while (TRUE)
    {
        //
        // Synchronously receive a message from the incoming queue.
        //
        hr = MQReceiveMessage(pDrawDlg->m_hqIncoming, INFINITE, 
                              MQ_ACTION_RECEIVE, &propsMessage, 
							  NULL, NULL, NULL, NULL);

		//
		// Determine if the message contains a keystroke or a line.
		//
        if (!FAILED(hr))
        {
			//
			// Convert the body to a multibyte null-terminated string. 
			//
            UINT uNumChars = aPropVar[1].ulVal/sizeof(WCHAR);
            size_t nResultedStringLength=0;
            wcstombs_s(
                &nResultedStringLength,
                mbsBody, 
                sizeof(mbsBody),
                wcsBody, 
                uNumChars
                );

			//
			// Add the keystroke to the drawing.
			//
			if (uNumChars == 1)
            {
				pDrawDlg->m_drawScribble.AddKeystroke(mbsBody);
            }
			
			//
			// Add the line received to the drawing.
			//
			else
			{
                		sscanf_s(mbsBody, "%07ld%07ld%07ld%07ld", 
					   &line.ptStart.x, &line.ptStart.y, 
					   &line.ptEnd.x, &line.ptEnd.y);
				pDrawDlg->m_drawScribble.AddLine(line);
			}
        }
    }


    return 0;
}