2

I am trying to send an HWND with the WM_COPYDATA IPC method. So far when sending a string LPCTSTR it works.

LPCTSTR str = L"Test";
COPYDATASTRUCT cds;
cds.dwData = 20;
cds.cbData = sizeof(TCHAR) * wcslen(str);
cds.lpData = (PVOID)str;
LRESULT l = SendMessage(myhWnd, WM_COPYDATA, (WPARAM)nullptr, (LPARAM)&cds);

But when using the HWND the message doesn't even arrive...

COPYDATASTRUCT cds;
cds.dwData = 20;
cds.cbData = sizeof(HWND);
cds.lpData = (PVOID)targetWnd;
LRESULT l = SendMessage(myhWnd, WM_COPYDATA, (WPARAM)nullptr, (LPARAM)&cds);

A PVOID should be able to point at anything afaik.

My HWNDs are both set and both of the methods above return 0 as LRESULT. How do I debug this? Or is there something fundamentally wrong?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Nur1
  • 418
  • 4
  • 11
  • 4
    Unless you're sending other data as well `WM_COPYDATA` is overkill to send a HWND; you can just send this as the `wParam` or `lParam` parameter of any custom message. – Jonathan Potter Jun 02 '21 at 20:19
  • I don't know any other type of IPC except WM_COPYDATA for small things like syncing statuses and some vars. If there is a better method I would love to learn it.@JonathanPotter – Nur1 Jun 02 '21 at 20:28
  • Oh the WM_USER+x thing. Alright. But why is this overkill? Isn't that the same? – Nur1 Jun 02 '21 at 20:33
  • 4
    No. Sending a custom message doesn't have the system marshal memory across processes (like `WM_COPYDATA`). `SendMessage(target, MY_MESSAGE, 0, (LPARAM)hwnd)` will simply copy the `wParam` and `lParam` values over. Though you don't want `WM_USER` messages. Use `WM_APP` messages instead, or registered messages if you want to make the message part of the public API. – IInspectable Jun 02 '21 at 20:36
  • 1
    "*So far when sending a string LPCTSTR it works*" - actually, it doesn't, because you are setting `cds.cbData` to the wrong value. You would need to set it to `lstrlen(str) * sizeof(*str)` instead of `sizeof(LPCTSTR)`. – Remy Lebeau Jun 02 '21 at 20:46
  • The last variant I was working on was the HWND one. So recreating an example snippet quickly with the LPCTSTR got me wrong. I updated the question. Well paid attention @RemyLebeau – Nur1 Jun 02 '21 at 21:00
  • 1
    @Nur1 you can get the custom `MY_MESSAGE` safely using `RegisterWindowMessage` API. – Sidhin S Thomas Jun 03 '21 at 06:32
  • @sid Defining a custom message in the `WM_APP + x` range is safe. `RegisterWindowMessage` doesn't add safety. It allows to establish a protocol that clients that aren't under your control can follow. It's rare that you need that. – IInspectable Jun 04 '21 at 07:59
  • @IInspectable what happens in case of collision? Like another app uses the same number to share their messages? App A using WM_APP + 1 and App B also using WMP_APP + 1? – Sidhin S Thomas Aug 06 '21 at 04:24
  • @sid If App A and App B both handle `WM_APP + 1`, and they aren't communicating with each other, nothing will happen. If they are communicating with each other, and they agree on the semantics of the message parameters, everything still works just fine. However, if they do not agree on how to interpret the parameters, things start to fall apart. If, for example, App A sends an integer value through `lParam`, but App B interprets that as a pointer, then App B will eventually read from or write to random memory. That's hardly desirable. – IInspectable Aug 06 '21 at 04:41

1 Answers1

4

An HWND is not a pointer. You most likely want:

COPYDATASTRUCT cds;
cds.dwData = 20;
cds.cbData = sizeof(HWND);
cds.lpData = &targetWnd;
//           ^
LRESULT l = SendMessage(myhWnd, WM_COPYDATA, (WPARAM)nullptr, (LPARAM)&cds);

Also, there seems to be some confusion between the source and destination HWNDs, but perhaps that's just the way you named them.

As Jonathan Potter (and some of the other commenters) point out, there are more efficient ways of sending an HWND, if that's all you want to do.

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48