Janardhan Reddy
Janardhan Reddy

Reputation: 1

MQSendMessage() failed with MQ_ERROR_INVALID_PARAMETER (0xC00E0006)

Problem with MSMQ configuration or code i've implemented??

I've written windows service code (win32 C++ ) in which i am sending a log to the local private queue.This code is working fine if I execute that in 32-bit environment (either windows7/8/vista). But that same code if I build for x64 OS and if I execute MQSendMessage() failed with MQ_ERROR_INVALID_PARAMETER (0xC00E0006). What could be the problem.??? Please help me out in this regard.Thanks in advance..

I've tried by changing the NUMBEROFPROPERTIES from 3-7 in x-64 windows 7 system. But still the problem remains same. what to do to avoid this..

Here is my sample code

#define ClientQueue L".\\Private$\\TestQueue"
#define LogMsgLable L"TestLOG"
#define MIN_PRIVATE_QUEUE_NAME_LENGTH 55

DWORD MSMQSendMessage()
{
    //Define the required constants and variables.
    const int NUMBEROFPROPERTIES = 7;                   // Number of properties
    DWORD cPropId = 0;                                  // Property counter
    HRESULT hr = MQ_OK;                                 // Return code
    HANDLE hQueue = NULL;                               // Queue handle

    //Define an MQMSGPROPS structure.
    MQMSGPROPS msgProps;
    MSGPROPID aMsgPropId[NUMBEROFPROPERTIES] = {0};
    MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES] = {0};
    HRESULT aMsgStatus[NUMBEROFPROPERTIES] = {0};

    // Specify the message properties to be sent.
    aMsgPropId[cPropId] = PROPID_M_LABEL;               // Property ID
    aMsgPropVar[cPropId].vt = VT_LPWSTR;                // Type indicator
    aMsgPropVar[cPropId].pwszVal = L"ADCLOG";     // The message label
    cPropId++;


    // Specifying the storage of messages in the harddisk
    // setting the message properties as recoverable

    aMsgPropId[cPropId] = PROPID_M_DELIVERY;
    aMsgPropVar[cPropId].vt = VT_UI1;
    aMsgPropVar[cPropId].bVal = MQMSG_DELIVERY_RECOVERABLE;
    cPropId++;

    aMsgPropId[cPropId] = PROPID_M_ACKNOWLEDGE;   // Property ID
    aMsgPropVar[cPropId].vt = VT_UI1;             // Type indicator
    aMsgPropVar[cPropId].bVal = MQMSG_ACKNOWLEDGMENT_FULL_RECEIVE;
    cPropId++;

    // we need to set the size of the message
    // if we dont set it, takes 4MB as default message size
    // to set the size of it we have ---> PROPID_M_BODY
    ULONG ulBufferSize = 15;
    char *lLog_msg = NULL;

    lLog_msg = ( char*)GlobalAlloc( GPTR,  15);

    ZeroMemory( lLog_msg, 15) ;

    strcpy(lLog_msg, "HelloWorld");

    aMsgPropId[cPropId] = PROPID_M_BODY;                // Property ID
    aMsgPropVar[cPropId].vt = VT_VECTOR | VT_UI1;       // Type indicator
    aMsgPropVar[cPropId].caub.pElems = (UCHAR *)lLog_msg;  // Body buffer
    aMsgPropVar[cPropId].caub.cElems = ulBufferSize;    // Buffer size
    cPropId++;

    //here we should not put VT_NULL in type as defined with VT_UI4.........
    aMsgPropId[cPropId] = PROPID_M_BODY_TYPE;           // Property ID
    aMsgPropVar[cPropId].vt = VT_UI4;                  // Type indicator
    cPropId++;

    // Initialize the MQMSGPROPS structure.
    msgProps.cProp = cPropId;
    msgProps.aPropID = aMsgPropId;
    msgProps.aPropVar = aMsgPropVar;
    msgProps.aStatus = aMsgStatus;

    // Create a direct format name for the queue.
    WCHAR *gFormatName    = NULL;
    DWORD dwBufferLength    = 0;

    dwBufferLength = MIN_PRIVATE_QUEUE_NAME_LENGTH; //Private queue format name buffer size atleast 54

    gFormatName = (WCHAR *)malloc( dwBufferLength*sizeof( WCHAR ));
    if (gFormatName == NULL)
    {
        printf( "malloc", 0, NULL );
        return MQ_ERROR_INSUFFICIENT_RESOURCES;
    }

    SecureZeroMemory( gFormatName, dwBufferLength*sizeof(WCHAR) );

    hr = MQPathNameToFormatName( ClientQueue,
                                 gFormatName,
                                 &dwBufferLength );
    if (FAILED( hr ))
    {
        if( hr == MQ_ERROR_FORMATNAME_BUFFER_TOO_SMALL )
        {
            if (gFormatName != NULL)
            {
                gFormatName = (WCHAR *)realloc( gFormatName, dwBufferLength*sizeof( WCHAR ));
                if (gFormatName == NULL)
                {
                    printf( "realloc failed\n");
                    return MQ_ERROR_INSUFFICIENT_RESOURCES;
                }                
            }

            SecureZeroMemory( gFormatName, dwBufferLength*sizeof( WCHAR ));

            hr = MQPathNameToFormatName( ClientQueue,
                                 gFormatName,
                                 &dwBufferLength );
            if(FAILED( hr ))
            {
                printf(  L"MQPathNameToFormatName2 failed:%x\n", hr);

                return hr;
            }
        }
        else
        {

               printf("MQPathNameToFormatName failed:%x\n", hr);            

               return hr;
        }
    }

    // Call MQOpenQueue to open the queue with send access.
    hr = MQOpenQueue(
                   gFormatName,                     // Format name of the queue
                   MQ_SEND_ACCESS,                    // Access mode
                   MQ_DENY_NONE,                      // Share mode
                   &hQueue                            // OUT: Queue handle
                   );    

    if ( FAILED( hr ))
    {
        printf("MQOpenQueue failed:%x\n", hr);
        goto ret;
        //goto cleanup;
    }

    if( gFormatName )
        free( gFormatName );

    // Call MQSendMessage to send the message to the queue.
    hr = MQSendMessage(
                     hQueue,                          // Queue handle
                     &msgProps,                       // Message property structure
                     NULL               // Not in a transaction
                     );
    if (FAILED(hr))
    {
        printf( "MQSendMessage failed:%x\n", hr );
        MQCloseQueue( hQueue );
        goto ret;
    }

     //Call MQCloseQueue to close the queue.
    hr = MQCloseQueue(hQueue);
    if(hr != 0)
    {
        printf("MQCloseQueue failed:%x",hr);
        //goto cleanup;
        goto ret;
    }ret:
    if( lLog_msg )
    {
        GlobalFree( lLog_msg );
        lLog_msg = NULL;
    }

    return hr;
}

Upvotes: 0

Views: 876

Answers (2)

r4v3n6
r4v3n6

Reputation: 46

Perhaps you need to specify the admin queue where acks will be sent to as well if you request acknowledgement. (MQMSG_ACKNOWLEDGMENT_FULL_RECEIVE) I would start with more simple sample and then add acknowledgement later once you have simple sample working.

Here is sample for acknowledgement where it adds both PROPID_M_ADMIN_QUEUE and PROPID_M_ACKNOWLEDGE: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/msmq/ms711369(v=vs.85)

Upvotes: 0

Carey Gregory
Carey Gregory

Reputation: 6846

Your code works on 32-bit Windows purely by chance. Take a look at this:

ULONG ulBufferSize = sizeof( 15);
char *lLog_msg = NULL;

lLog_msg = ( char*)GlobalAlloc( GPTR, sizeof( 15));

ZeroMemory( lLog_msg, sizeof( 15)) ;

strcpy(lLog_msg, "HelloWorld");

You seem to misunderstand what the sizeof operator does. It is a compile time operator that replaces its argument with the size of that argument. In this case, the compiler replaces sizeof(15) with the number 4. Why? Because a literal constant like 15 occupies 4 bytes on a 64-bit machine. So in the code above you are allocating 4 bytes of memory and then copying 11 bytes into it, thereby corrupting memory.

To fix this, simply remove sizeof. The code above should look like this:

ULONG ulBufferSize = 15;
char *lLog_msg = NULL;     // this is pointless since you set it in the next line

lLog_msg = ( char*)GlobalAlloc( GPTR, ulBufferSize);

ZeroMemory( lLog_msg, ulBufferSize) ;

strcpy(lLog_msg, "HelloWorld");

Upvotes: 0

Related Questions