Problem marshalling CopyData structure for WM_COPYDATA message in x64(code works in x86)




I'm pretty sure I've just got a Marshalling problem, but I'm
completely stumped. If there is a better newsgroup to post this in,
please point me towards it.

First I'm trying to use SendMessage() with WM_COPYDATA to send a
string data between two instances of a program. As part of the
debugging I've written two methods one where a given instance will
obtain its own hWnd and send itself the message, one where it accepts
obtains the hWnd of the other instance and sends it to the other one.
Both methods work fine when compiled as x86. And the send-to-itself
works on x64, but the send-to-another-instance breaks... the
WM_COPYDATA message is sent, and received, but I'm unable to read back
the string data.

I *think* its a marshalling problem related to changes with x64. But
I'm not sure.

Here are the relevant bits:

// The COPYDATA structure used for the WM_COPYDATA message:

public struct COPYDATASTRUCT
public int dwData; // not used
public int cbData; // holds length of string
public string lpData; //holds string

//DLL Import of SendMessage
[DllImport("user32.dll", CharSet=CharSet.Ansi)]
private static extern IntPtr SendMessage(IntPtr hWnd,
[MarshalAs(UnmanagedType.U4)] int Msg,
IntPtr wParam, ref COPYDATASTRUCT lParam);

//The function that sends the message:

public static IntPtr SendCopyDataMessage(IntPtr toHandle)
int messageid = 1234; // random message id

stringdata = "Testing\0"; // send the string "Testing"

// Create/populate the copydata structure.

dataStruct.dwData = 0; //not used
dataStruct.cbData = stringdata.Length;
dataStruct.lpData = stringdata;

// Make the call
IntPtr result = SendMessage(toHandle, WM_COPYDATA,
messageid, ref dataStruct);

return result;

The WndProc that receives the messages is an override of Form.WndProc:

// Process Custom Messages!
protected override void WndProc(ref Message m)
if (m.Msg == WM_COPYDATA)
// unpack the data
string stringdata = ProcessWM_COPYDATA(m);
// show what it was
if (stringdata != null)
base.WndProc(ref m);

The function it calls to unpack the COPYDATA structure is as follows:

public static string
ProcessWM_COPYDATA(System.Windows.Forms.Message m)
if (m.WParam.ToInt32() == 1234)
m.LParam, typeof(COPYDATASTRUCT));
return datastruct.lpData;
return null;

As I said: It works when targeted at x86. In x64 it also works when I
fire the send message at the same instance. (e.g. I have a button on
the form that calls the SendCopyData(...) with its own window handle.

The only time it doesn't work is when I have 2nd instance running and
it calls SendCopyData(...) with the hWnd of the OTHER instance. In
that case the message is received, and the MessageBox is displayed,
but instead of saying testing its either blank or contains garbage

I'd be grateful if someone can point out where I've screwed it up. As
I said, I think its in marshalling/unmarshalling the lpData string,
but I'm at a loss to fix it. I've tried doing it a number of ways,
including setting lpData in COPYDATASTRUCTURE to an IntPtr, and then
manually calling Marshal.StringToHGlobal(stringdata); and then when
unpacking it, calling Marshal.PtrToString(lpData), but I end up with
the same behaviour... breaking in x64.

-best regards,


I'm pretty sure I've just got a Marshalling problem, but I'm
completely stumped. If there is a better newsgroup to post this in,
please point me towards it.

Aw crap. I didn't even post to the newsgroup I intended. Sorry about


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question