MQSendMessage() 失败,出现 MQ_ERROR_INVALID_PARAMETER (0xC00E0006)

问题描述 投票:0回答:2

我已实现的 MSMQ 配置或代码有问题吗??

我已经编写了Windows服务代码(win32 C++),其中我将日志发送到本地专用队列。如果我在32位环境(windows7/8/vista)中执行该代码,则该代码工作正常。但是,如果我为 x64 操作系统构建并且执行 MQSendMessage(),则相同的代码会失败并出现 MQ_ERROR_INVALID_PARAMETER (0xC00E0006)。可能是什么问题呢。???请在这方面帮助我。提前致谢..

我尝试过在 x-64 windows 7 系统中将 NUMBEROFPROPERTIES 从 3-7 更改。但问题仍然是一样的。该怎么做才能避免这种情况..

这是我的示例代码

#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;
}
winapi msmq win32-process
2个回答
0
投票

您的代码在 32 位 Windows 上运行纯属偶然。看看这个:

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

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

ZeroMemory( lLog_msg, sizeof( 15)) ;

strcpy(lLog_msg, "HelloWorld");

您似乎误解了

sizeof
运算符的作用。它是一个编译时运算符,用该参数的大小替换其参数。在这种情况下,编译器将
sizeof(15)
替换为数字
4
。为什么?因为像
15
这样的文字常量在64位机器上占用4个字节。因此,在上面的代码中,您分配了 4 个字节的内存,然后将 11 个字节复制到其中,从而损坏了内存。

要解决此问题,只需删除

sizeof
。上面的代码应该如下所示:

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");

0
投票

也许您需要指定管理队列,如果您请求确认,确认也会发送到该管理队列。 (MQMSG_ACKNOWLEDGMENT_FULL_RECEIV) 我将从更简单的示例开始,然后在您完成简单的示例工作后添加确认。

© www.soinside.com 2019 - 2024. All rights reserved.