3

When my application is running on x86 the program works fine. When I run it on x64, the Access Violation exception occurs. Exception details mentioned below.

"System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'"

I thought that the problem lies in Marshalling. Do I have to manually Marshal the structure? Need help on this. I would prefer to have the same struct for both x64 and x86. My native method is defined like below.

[StructLayout(LayoutKind.Sequential)]
   internal struct CWPSTRUCT
  {
   internal IntPtr lParam;
   internal IntPtr wParam;
   internal int message;
   internal IntPtr hwnd;
  }

And the CallNextHookEx is,

[DllImport("user32", CharSet=CharSet.Auto, ExactSpelling=true)]
        extern public static IntPtr CallNextHookEx(IntPtr hhook, int code, int wparam, int lparam)  ;

And the method in which exception occurs,

private IntPtr MessageHookProc(int nCode, int wParam, int lParam, ref bool processMessage)  
        {
            GC.KeepAlive(this);
            if (nCode >= 0 && !this.DisableMessageHook)
            {
                IMessageFilter imf = client as IMessageFilter;
                if (imf != null)
                {
                    **CWPSTRUCT cwp = 
                        (CWPSTRUCT)(Marshal.PtrToStructure((IntPtr)lParam, typeof(CWPSTRUCT)));**

                    Message msg = Message.Create(cwp.hwnd, cwp.message, cwp.wParam, cwp.lParam);

                    if(imf.PreFilterMessage(ref msg))
                    {
                        processMessage = false;
                        return (IntPtr)1;
                    }
                }
            }

            return NativeHookMethods.CallNextHookEx(this.MessageHookHandle,nCode,wParam,lParam);
        }

And the code in which the particular method-MessageHookProc used,

WndProcHooker messageHooker = (WndProcHooker)this.reference.Target;
retval = messageHooker.MessageHookProc(nCode,wParam,lParam, ref processMessage);
  • You have an alignment issue. Try the pack option for 64. See : https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.structlayoutattribute?view=netcore-3.1 Also specifically make the integer 32 bits. – jdweng May 18 '20 at 08:21
  • I have tried this also need more explanation about this solution . Is there any other way to solve the issue? – Visithra Venkatesan May 28 '20 at 03:50
  • The Microprocessor has a Pipeline register to allow instructions to run in parallel. The compiler has optimization that takes advantage to the pipeline of the processor. On a 64 bit processor the alignment of data needs to be on an 8 byte boundary to work with the pipeline. Your structure is 16 bytes. The compile assigns memory to your application in x64 on 8 byte boundary. If the structure exceeds the boundary limits you will get a memory exception. Alignment makes sure the structure doesn't exceed the memory boundary. Error also can occur if the return value from c++ doesn't match c#. – jdweng May 28 '20 at 06:54
  • I think your casting may be cause of issue : return (IntPtr)1;. Try instead IntPtr.Zero. Also try From : extern public static IntPtr CallNextHookEx To : extern public static Uint CallNextHookEx. Check if user32.dll is in the c:\Window\System32 folder or c:\Window\Wow64 folder. Are you running on same machine that code is compiled? You may need to publish application and run setup.exe for application to run on another machine. If you compile on a 64 bit machine and then run on a 32 bit machine you will have issues. – jdweng May 28 '20 at 07:04

0 Answers0