在带有 WM_COPYDATA 消息的结构中使用 LPCTSTR 是不是安全?

Posted

技术标签:

【中文标题】在带有 WM_COPYDATA 消息的结构中使用 LPCTSTR 是不是安全?【英文标题】:Is it safe to use LPCTSTR in a structure with the WM_COPYDATA message?在带有 WM_COPYDATA 消息的结构中使用 LPCTSTR 是否安全? 【发布时间】:2020-05-11 08:18:22 【问题描述】:

我有这个结构:

typedef struct tagCOPY_PACKET

    TCHAR szFile[_MAX_PATH];
    GUID guidSignature;

 S_COPY_PACKET;

我准备像这样用WM_COPYDATA 发送数据:

CString strFile = GetFileToOpenFromFileExplorerPath();

S_COPY_PACKET sCopyDataPacket;
_tcscpy_s(sCopyDataPacket.szFile, _MAX_PATH, strFile);
sCopyDataPacket.guidSignature = CopyData_Signature;
COPYDATASTRUCT cds;
cds.dwData = COPYDATA_TYPE_MSA;
cds.cbData = sizeof(sCopyDataPacket);
cds.lpData = &sCopyDataPacket;

DWORD_PTR dwResult;
if (SendMessageTimeout(hOtherInstance, WM_COPYDATA,
                NULL, (LPARAM)(LPVOID)&cds, SMTO_BLOCK, 2000, &dwResult) != 0)


在另一端:

BOOL CMeetingScheduleAssistantDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)

    if (pCopyDataStruct->dwData == COPYDATA_TYPE_MSA)
    
        S_COPY_PACKET* pCopyPacket = (S_COPY_PACKET*)(pCopyDataStruct->lpData);
        if (pCopyPacket->guidSignature != CopyData_Signature)
        
            // Bad GUID
            return FALSE;
        

        if (GetLastActivePopup() != this) // Popup windows!
        
            // TODO: Tell user?
            return FALSE;
        

        theApp.SetFileToOpenFromFileExplorer(pCopyPacket->szFile);

        OpenFileFromFileExplorer();

        return TRUE;
    

    return FALSE;

它工作正常。我只是想知道这样改变我的结构是否可以接受:

typedef struct tagCOPY_PACKET

    LPCTSTR lpszFile;
    GUID guidSignature;

 S_COPY_PACKET;

然后使用:

S_COPY_PACKET sCopyDataPacket;
sCopyDataPacket.lpszFile = strFile.GetBufferSetLength(_MAX_PATH);
sCopyDataPacket.guidSignature = CopyData_Signature;
COPYDATASTRUCT cds;
cds.dwData = COPYDATA_TYPE_MSA;
cds.cbData = sizeof(sCopyDataPacket);
cds.lpData = &sCopyDataPacket;
...

并且,一旦消息被发布和处理:

strFile.ReleaseBuffer();

LPCTSTR 方法与WM_COPYDATA 一起使用是否安全?如果是,为什么?

【问题讨论】:

从接收应用的角度来看,这两者之间绝对没有区别:cds.lpData = &sCopyDataPacket;cds.lpData = strFile.GetString();。它们都指向 local 数据副本。所以是的,这是绝对可以接受的,除非您不尝试在接收应用程序中使用cds.lpData 指针之后 SendMessage 返回。 @Jovibor 我明白你在说什么。但我需要发送这个包含GUIDCString 内容的结构。 您的S_COPY_PACKET sCopyDataPacket;CString strFile 都是本地 数据对象,对吧?那么,您在cds.lpData = 中提供的指针有什么区别?好吧,这里的建议 - 尝试这两种情况并自己查看结果。 @Jovibor 接收应用程序无法从发送应用程序的内存中读取数据。其余的都无所谓。 @MartinPrikryl 但它可以读取S_COPY_PACKET sCopyDataPacket; ? 【参考方案1】:

documentation of WM_COPYDATA 说:

传递的数据不得包含指针或其他对接收数据的应用程序无法访问的对象的引用。

因此,当CMeetingScheduleAssistantDlg 存在于不同的可执行文件中时,您不能传递LPCTSTR 值。如果它在同一个可执行文件中,则很有可能它可以工作。

【讨论】:

谢谢。所以我做的方式更好(_tcscpy_s)。【参考方案2】:

没有。 LPCTSTR 是一个指针。因此接收方应用程序将收到一个指向发送方应用程序内存位置的指针。如果它试图访问数据,它将导致接收应用程序由于内存冲突而崩溃。

【讨论】:

谢谢。所以我做的方式更好(_tcscpy_s)。

以上是关于在带有 WM_COPYDATA 消息的结构中使用 LPCTSTR 是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

MFC中WM_COPYDATA消息

VC++ 在两个程序中 传送字符串等常量值的方法:使用了 WM_COPYDATA 消息(转载)

在 WPF 或控制台 C# 应用程序中接收 WM_COPYDATA 结构

进程间通信之WM_COPYDATA

在 Qt 应用程序中接收 WM_COPYDATA 消息

IPC进程间通信之四数据复制消息WM_COPYDATA