473,505 Members | 16,800 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

(apparent) Marshalling related problem in x64 but works in x86

Hi,

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:

[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
[MarshalAs(UnmanagedType.U4)]
public int dwData; // not used
[MarshalAs(UnmanagedType.U4)]
public int cbData; // holds length of string
[MarshalAs(UnmanagedType.LPStr)]
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.
COPYDATASTRUCT dataStruct = new COPYDATASTRUCT();

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)
{
MessageBox.Show(stringdata);
}
}
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)
{
COPYDATASTRUCT datastruct =
(COPYDATASTRUCT)Marshal.PtrToStructure(
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
data.

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,
Dave
Jun 27 '08 #1
2 2130
The dwData member of COPYDATASTRUCT is not an int. It is a pointer sized
type so you must use IntPtr in your struct definition.
"d-42" <db********@gmail.comwrote in message
news:e3**********************************@v26g2000 prm.googlegroups.com...
Hi,

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:

[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
[MarshalAs(UnmanagedType.U4)]
public int dwData; // not used
[MarshalAs(UnmanagedType.U4)]
public int cbData; // holds length of string
[MarshalAs(UnmanagedType.LPStr)]
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.
COPYDATASTRUCT dataStruct = new COPYDATASTRUCT();

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)
{
MessageBox.Show(stringdata);
}
}
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)
{
COPYDATASTRUCT datastruct =
(COPYDATASTRUCT)Marshal.PtrToStructure(
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
data.

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,
Dave

Jun 27 '08 #2
Thank you very much, that resolved the problem.

-regards,
Dave
On May 5, 7:21 am, "Stephen Martin"
<smar...@removethis.emsoft.andthis.cawrote:
The dwData member of COPYDATASTRUCT is not an int. It is a pointer sized
type so you must use IntPtr in your struct definition.
Jun 27 '08 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2845
by: Animesh | last post by:
Hi All, I don't know whethher this is possible or not. This is the result of a bad design problem. Here I go; I have a structure like this: typedef struct _s_index_entry { char *doc_id;...
7
606
by: GianPiero Andreis | last post by:
Hello All, let me pose a simple question about combobox and the CB_INSERTSTRING message. Suppose for instance that I already have a combobox handle, how can I declare and use the SendMessage...
2
5537
by: Howard Kaikow | last post by:
I've got the following in a VB 6 project: Private Type PROCESSENTRY32 dwSize As Long cntUsage As Long th32ProcessID As Long th32DefaultHeapID As Long th32ModuleID As Long cntThreads As Long...
0
1132
by: swartzbill2000 | last post by:
I am familiar with the VB6/VC6/ATL way of marshalling an incoming interface via New (VB), and then marshalling an outgoing interface with some form of Advise. To me it looks like .Net has...
2
1396
by: bonk | last post by:
I am currently trying to write a longer article about Marshalling when using . Does anyone know books, articles, or websites that cover Marshalling in Platform Invocation Services ()?
10
2518
by: Bryce Calhoun | last post by:
Hello, First of all, this is a .NET 1.1 component I'm creating. SUMMARY ----------------------- This component that I'm creating is, for all intents and purposes, a document parser (I'm...
2
2467
by: RJ Lohan | last post by:
Howdy, I have a legacy DLL for which I have a problem marshalling a parameter type of char**. The function header (C++) is as so; extern "C" __declspec(dllexport) int __stdcall...
2
3321
by: calenlas | last post by:
Hi all, I'm taking my first steps into C# <--C++ DLL Interop and unfortunately I've run into (what seems to be) a very complicated case as my first task. Perhaps someone here can help me. I...
1
2520
by: d-42 | last post by:
Hi, 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...
0
7103
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
1
7021
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7478
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
5035
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4701
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3177
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1532
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
755
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
409
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.