Is it safe to use WM_COPYDATA between 64-and 32-bit (WOW64) apps?

0

There is a good SO Q/A session on the general use of WM_COPYDATA messages here, and a 'discussion' about whether or not this will work between apps of different 32/64-bitness here. However, the latter seems to be focussed on possible misuse of the 'data pointer' being passed. So, I'm raising a new question here.

I am working on getting two Windows apps to communicate/synchronize with each other and, as a first-round approach, I'm using Windows Messaging to implement this. Everything seems OK for now … but I'm using the WM_COPYDATA message to pass info between the apps.

My question: Is this approach guaranteed to be safe when the two apps have different (32/64) bitness? I've done some tests using the code below with all four possible combinations of 32 vs 64 builds between 'client' and 'server', and all work as expected; but is this just because I'm getting 'lucky' results (from possible undefined behaviour), or does the WOW64 system (especially when server is 64-bit and client is 32) take care of all the necessary marshalling?

If anyone can confirm that it is guaranteed to work, I would very much appreciate an 'official' link/reference confirming that.

Shared header file:

static const WPARAM nmIdFilePath = 0x00001100;

struct nmLockInfoType {
    char filePathID[1024];
    // More elements will be added later!
};
static const nmLockInfoType nmLockInfoDefault = {
    "<<<Uninitialised Image Data Path>>>",
    //...
};
extern nmLockInfoType nmLockInfo; // MUST be provided by each app!
///nmLockInfoType nmLockInfo = nmLockInfoDefault; // Use this code to instatiate it (once, somewhere)!

Server program code (inside the handler for a RegisterWindowMessage(L"HANDSHAKE"); message):

//...
COPYDATASTRUCT cds;
cds.dwData = nmIdFilePath;           // Pre-defined ID
cds.cbData = sizeof(nmLockInfoType);
cds.lpData = &nmLockInfo;            // Pre-defined structure (see above)
//...
// Send a copy of the "Welcome Pack" data structure to the client app ...
::SendMessage(clientLock, WM_COPYDATA, WPARAM(m_hWnd), LPARAM(&cds)); // "clientLock is the HWND of the client app's MainWnd

Client Program code:

BOOL MyFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
    switch (pCopyDataStruct->dwData)
    {
    case nmIdFilePath:
        memcpy(&nmLockInfo, pCopyDataStruct->lpData, pCopyDataStruct->cbData);
        return nmsSucceeded; // This is NON_ZERO so evaluates to TRUE
    // Other cases here ...
    } 
    return CMDIFrameWnd::OnCopyData(pWnd, pCopyDataStruct);
}

I'm particularly concerned about the case when the client is 32-bit but the server is 64-bit; in such a case, it would be sending a 64-bit data address to a 32-bit app (albeit, a WOW64 app). Does the in-built 'marshalling' handle this in WOW64 situations?

winapi
wow64
wm-copydata
asked on Stack Overflow Nov 7, 2019 by Adrian Mole • edited Nov 7, 2019 by Adrian Mole

1 Answer

1

It's safe only when we follow the rule how to use it. Please refer the remarks of WM_COPYDATA message from below:

The data being passed must not contain pointers or other references to objects not accessible to the application receiving the data.

While this message is being sent, the referenced data must not be changed by another thread of the sending process.

The receiving application should consider the data read-only. The lParam parameter is valid only during the processing of the message. The receiving application should not free the memory referenced by lParam. If the receiving application must access the data after SendMessage returns, it must copy the data into a local buffer.

For example, if we are trying to passing the data type: ULONG_PTR, then the data copy maybe not function well when pass it from 64-bit application to 32-bit application. Because it is 32-bit on 32-bit application and 64-bit on 64-bit application.

You can test it via modify the code below:

struct nmLockInfoType {
char filePathID[1024];
ULONG_PTR point64_32;
// More elements will be added later!
};

The scenario mentioned above, which should be safe as the result you tested. Feel free to let me know if you still have concern about.

In-addition, below is an helpful document about developing 64-bit application for your reference:

Common Visual C++ 64-bit Migration Issues

answered on Stack Overflow Nov 27, 2019 by Fei Xue - MSFT

User contributions licensed under CC BY-SA 3.0