So, I'm experiencing a very weird issue with my little test application. And by issue, I mean it crashes... hard. No exception (at least, nothing that I could catch) is thrown, just the "Blah Blah has stopped responding..." message. It crashes ONLY when I run the app in x64, release mode and outside of the IDE. If I run it in x86 mode, or if I run it in the IDE in x64 or I run it standalone as DEBUG in x64 it works fine.
I've narrowed it down to my p/invoke PeekMessage call. So, I need the brilliant minds here to look at the crap I've written and tell me if I'm doing it right. Because, seriously, I'm about to lose my f**king mind. I've tried this on 2 computers and they both exhibit the same behaviour. I'm a little concerned that this could be a .NET 4.0 bug.
Anyway, here's my p/invoke code. Please let me know if you see anything odd or just plain stupid:
Here's the call to PeekMessage:
private static bool PeekMessage()
{
MSG message = new MSG(); // Message to retrieve.
return Win32API.PeekMessage(ref message, IntPtr.Zero, 0, 0, PeekMessageFlags.NoRemove);
}
Here's PeekMessage (NOTE: The suppress security attribute is on the class definition, so it is being applied):
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern bool PeekMessage(ref MSG msg, IntPtr hwnd, uint wFilterMin, uint wFilterMax, PeekMessageFlags flags);
Here's the MSG:
[StructLayout(LayoutKind.Sequential)]
internal struct MSG
{
/// <summary>Window handle.</summary>
public IntPtr hwnd;
/// <summary>Message to process.</summary>
public uint Message;
/// <summary>Window message parameter 1.</summary>
public uint wParam;
/// <summary>Window message parameter 2.</summary>
public uint lParam;
/// <summary>Time message was sent?</summary>
public uint time;
/// <summary>Mouse pointer position.</summary>
public Point pt;
}
And finally, the PeekMessageFlags:
internal enum PeekMessageFlags
{
/// <summary>Keep message on the message queue.</summary>
NoRemove = 0,
/// <summary>Remove message from the queue.</summary>
Remove = 1,
/// <summary>Do not yield execution to waiting threads.</summary>
NoYield = 2
}
I checked the event log and I got this:
Faulting application name: Tester_Graphics.exe, version: 1.0.0.0, time stamp: 0x4ec0ba85
Faulting module name: unknown, version: 0.0.0.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x00000000000001cb
Faulting process id: 0x1260
Faulting application start time: 0x01cca299e2c21a77
Faulting application path: D:\Code\Current\Gorgon\Branches\2.x\Dorian\Examples\Tester_Graphics\bin\Release\Tester_Graphics.exe
Faulting module path: unknown
Report Id: 20ac891f-0e8d-11e1-a5d7-bcaec5753ddd
So, if you see anything not quite right, please let me know. I'd hate for this to not be my fault.
Sorry if it's not detailed enough, if you need more info, just leave a note.
The size of lParam
and wParam
fields of MSG
are wrong. You should use IntPtr
instead of uint
/ int
.
If you take a look at Windows Data Types you can see that:
LPARAM
is a LONG_PTR
i.e. its 32 bits in size of 32 bit platforms and 64 bits in size on 64 bit platforms.PARAM
is a UINT_PTR
which again is 32 bits in size of 32 bit platforms and 64 bits in size on 64 bit platforms.Conversely the int
and uint
types are both 32 bits in size regardless of the platform, meaning that on 64 bit platforms your MSG
struct is 64 bits too small which will result in some sort of memory corruption.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With