P/Invoking SetWindowLong and CallWindowProc in managed code (compact framework)

♀尐吖头ヾ 提交于 2019-12-11 08:53:42

问题


I am trying to override the window procedure for the winmobile taskbar (in order to catch and block pressed buttons) by using SetWindowLong. I have created a class with one method for overriding and one for restoring the window procedure. The MessageReceived method is the one I use to replace the taskbar window procedure with. My class looks the following way:

class ButtonBlocker
{
  public delegate IntPtr WindowProc(IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam);

  public static WindowProc newWindowDeleg;
  private static IntPtr oldWindowProc;

  [DllImport("coredll.dll")]
  static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

  [DllImport("coredll.dll")]
  static extern int GetWindowLong(IntPtr hWnd, int nIndex);

  [DllImport("coredll.dll")]
  static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

  [DllImport("coredll.dll", EntryPoint = "FindWindow")]
  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

  private static IntPtr MessageReceived(IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam)
  {
      Debug.WriteLine("Message received");
      return CallWindowProc(oldWindowProc, hwnd, uMsg, wParam, lParam);
  }

  public static void OverrideWindowProc()
  {
      newWindowDeleg = MessageReceived;

      IntPtr taskBarHandle = FindWindow("HHTaskBar", null);

      int newWndProc = Marshal.GetFunctionPointerForDelegate(newWindowDeleg).ToInt32();
      int result = SetWindowLong(taskBarHandle, -4, newWndProc);
      oldWindowProc = (IntPtr)result;
      if (result == 0)
      {
          MessageBox.Show("Failed to SetWindowLong");
      }
  }

  public static void RestoreWindowProc()
  {
      IntPtr taskBarHandle = FindWindow("HHTaskBar", null);
      int result = SetWindowLong(taskBarHandle, -4, oldWindowProc.ToInt32());
  }
}

The behavior in the mobile emulator is the following - after I press a button, "Message received" is displayed in the Debug output, but the program crashes and offers to send a crash report to Microsoft. The visual studio debugger hangs and doesn't react to the stop command. It unfreezes only after an emulator reset. The problem seems to be with the CallWindowProc at the end of the MessageReceived method. Most probably, there is some issue with the old windowproc address. If I try to execute the RestoreWindowProc code immediately after the OverrideWindowProc code (with no messages being intercepted by my function), the application exits okay and the debugger does not freeze. Any ideas on how to get this to work would be appreciated.

I am using Visual Studio 2008 SP1. The project targets .NET framework v3.5, Windows Mobile 6 Professional.


回答1:


You cannot replace the window procedure of a window that is owned by another process. The address of the replacement function is only valid in your process. It causes an immediate bomb in the other process. You would have to inject a DLL into the target process to work around this problem. You can't inject DLLs written in a managed language, the CLR isn't initialized.



来源:https://stackoverflow.com/questions/2104667/p-invoking-setwindowlong-and-callwindowproc-in-managed-code-compact-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!