[Pkg-mozext-commits] [firetray] 13/84: failed attempt to use a hook (WH_CALLWNDPROC) instead of a window procedure.

David Prévot taffit at moszumanska.debian.org
Sun Jul 20 01:42:42 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository firetray.

commit 258ddbfbe0d0049bfd08cf16cb5d003bd96a34e9
Author: foudfou <foudil.newbie+git at gmail.com>
Date:   Mon Dec 2 00:31:45 2013 +0100

    failed attempt to use a hook (WH_CALLWNDPROC) instead of a window procedure.
    
    This works well until we try to SendMessage from our proxy window to Firefox
    windows. SendMessage crashes when sending to a Firefox window with our hook
    registered, or to *any* window (tested on our proxy window and arbitrary
    launched programs).
---
 src/modules/ctypes/winnt/kernel32.jsm    |   2 +
 src/modules/ctypes/winnt/user32.jsm      |  49 +++++++++++++++
 src/modules/ctypes/winnt/win32.jsm       |   1 +
 src/modules/winnt/FiretrayStatusIcon.jsm |  29 +++++----
 src/modules/winnt/FiretrayWin32.jsm      |  17 ++++--
 src/modules/winnt/FiretrayWindow.jsm     | 100 +++++++++++++++++--------------
 6 files changed, 138 insertions(+), 60 deletions(-)

diff --git a/src/modules/ctypes/winnt/kernel32.jsm b/src/modules/ctypes/winnt/kernel32.jsm
index 613523e..a9d975a 100644
--- a/src/modules/ctypes/winnt/kernel32.jsm
+++ b/src/modules/ctypes/winnt/kernel32.jsm
@@ -33,6 +33,8 @@ function kernel32_defines(lib) {
 
   lib.lazy_bind("LoadLibraryW", win32.HMODULE, win32.LPCTSTR);
   lib.lazy_bind("GetProcAddress", win32.FARPROC, win32.HMODULE, win32.LPCSTR);
+  lib.lazy_bind("GetCurrentThreadId", win32.DWORD);
+
 
 }
 
diff --git a/src/modules/ctypes/winnt/user32.jsm b/src/modules/ctypes/winnt/user32.jsm
index 1f90dc8..154999f 100644
--- a/src/modules/ctypes/winnt/user32.jsm
+++ b/src/modules/ctypes/winnt/user32.jsm
@@ -134,6 +134,55 @@ function user32_defines(lib) {
   this.WS_OVERLAPPEDWINDOW = (this.WS_OVERLAPPED | this.WS_CAPTION | this.WS_SYSMENU | this.WS_THICKFRAME | this.WS_MINIMIZEBOX | this.WS_MAXIMIZEBOX);
   this.WS_TILEDWINDOW      = (this.WS_OVERLAPPED | this.WS_CAPTION | this.WS_SYSMENU | this.WS_THICKFRAME | this.WS_MINIMIZEBOX | this.WS_MAXIMIZEBOX);
 
+  this.CWPSTRUCT = ctypes.StructType("CWPSTRUCT", [
+    { "lParam": win32.LPARAM },
+    { "wParam": win32.WPARAM },
+    { "message": win32.UINT },
+    { "hwnd": win32.HWND }
+  ]);
+
+  this.CWPRETSTRUCT = ctypes.StructType("CWPRETSTRUCT", [
+    { "lResult": win32.LRESULT },
+    { "lParam": win32.LPARAM },
+    { "wParam": win32.WPARAM },
+    { "message": win32.UINT },
+    { "hwnd": win32.HWND }
+  ]);
+
+  this.HOOKPROC = ctypes.FunctionType(
+    WinCbABI, win32.LRESULT,
+    [ctypes.int, win32.WPARAM, win32.LPARAM]).ptr;
+
+  lib.lazy_bind("SetWindowsHookExW", win32.HHOOK, ctypes.int, this.HOOKPROC, win32.HINSTANCE, win32.DWORD);
+  lib.lazy_bind("CallNextHookEx", win32.LRESULT, win32.HHOOK, ctypes.int, win32.WPARAM, win32.LPARAM);
+  lib.lazy_bind("UnhookWindowsHookEx", win32.BOOL, win32.HHOOK);
+
+  this.WH_MIN             = (-1);
+  this.WH_MSGFILTER       = (-1);
+  this.WH_JOURNALRECORD   = 0;
+  this.WH_JOURNALPLAYBACK = 1;
+  this.WH_KEYBOARD        = 2;
+  this.WH_GETMESSAGE      = 3;
+  this.WH_CALLWNDPROC     = 4;
+  this.WH_CBT             = 5;
+  this.WH_SYSMSGFILTER    = 6;
+  this.WH_MOUSE           = 7;
+  this.WH_HARDWARE        = 8;
+  this.WH_DEBUG           = 9;
+  this.WH_SHELL           = 10;
+  this.WH_FOREGROUNDIDLE  = 11;
+  this.WH_CALLWNDPROCRET  = 12;
+  this.WH_KEYBOARD_LL     = 13;
+  this.WH_MOUSE_LL        = 14;
+
+  this.HC_ACTION      = 0;
+  this.HC_GETNEXT     = 1;
+  this.HC_SKIP        = 2;
+  this.HC_NOREMOVE    = 3;
+  this.HC_NOREM       = this.HC_NOREMOVE;
+  this.HC_SYSMODALON  = 4;
+  this.HC_SYSMODALOFF = 5;
+
 }
 
 new ctypes_library(USER32_LIBNAME, USER32_ABIS, user32_defines, this);
diff --git a/src/modules/ctypes/winnt/win32.jsm b/src/modules/ctypes/winnt/win32.jsm
index af33350..15e554c 100644
--- a/src/modules/ctypes/winnt/win32.jsm
+++ b/src/modules/ctypes/winnt/win32.jsm
@@ -39,6 +39,7 @@ var win32 = new function() {
   this.HMENU     = this.HANDLE;
   this.HBRUSH    = this.HICON;
   this.HCURSOR   = this.HANDLE;
+  this.HHOOK     = this.HANDLE;
   this.TCHAR     = ctypes.jschar, // Mozilla compiled with UNICODE/_UNICODE macros and wchar_t = jschar
   this.LPSTR     = ctypes.char.ptr;
   this.LPCSTR    = ctypes.char.ptr;
diff --git a/src/modules/winnt/FiretrayStatusIcon.jsm b/src/modules/winnt/FiretrayStatusIcon.jsm
index 8c64283..49ff851 100644
--- a/src/modules/winnt/FiretrayStatusIcon.jsm
+++ b/src/modules/winnt/FiretrayStatusIcon.jsm
@@ -124,11 +124,15 @@ firetray.StatusIcon = {
     if (uMsg === firetray.Win32.WM_TASKBARCREATED) {
       log.info("____________TASKBARCREATED");
 
+    } else if (uMsg === firetray.Win32.WM_TRAYMESSAGEFWD) {
+      log.debug("ProxyWindowProc WM_TRAYMESSAGEFWD reached!");
+
     } else if (uMsg === firetray.Win32.WM_TRAYMESSAGE) {
 
       switch (+lParam) {
       case win32.WM_LBUTTONUP:
         log.debug("WM_LBUTTONUP");
+        let rv = user32.SendMessageW(hWnd, firetray.Win32.WM_TRAYMESSAGEFWD, 0, 1);
         break;
       case win32.WM_RBUTTONUP:
         log.debug("WM_RBUTTONUP");
@@ -142,27 +146,30 @@ firetray.StatusIcon = {
       default:
       }
 
-    }
+try {
 
-/*
-    // CallWindowProcW() on a non-moz window works fine
-    let procPrev = firetray.StatusIcon.callbacks.procPrev;
-    log.debug("  procPrev="+procPrev);
-    let rv = user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam);
-    log.debug("  CallWindowProc="+rv);
-    return rv;
-*/
+      for (let wid in firetray.Handler.windows) {
+        let hwnd = firetray.Win32.hexStrToHwnd(wid);
+        let rv = user32.SendMessageW(hwnd, firetray.Win32.WM_TRAYMESSAGEFWD, 0, 1);
+        log.debug("SendMessageW WM_TRAYMESSAGEFWD rv="+rv+" winLastError="+ctypes.winLastError);
+      }
+
+  } catch(error) {
+log.error(error);
+  }
+
+    }
 
     return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam);
   },
 
   getIconFromWindow: function(hwnd) {
-    rv = user32.SendMessageW(hwnd, user32.WM_GETICON, user32.ICON_SMALL, 0);
+    let rv = user32.SendMessageW(hwnd, user32.WM_GETICON, user32.ICON_SMALL, 0);
+    log.debug("SendMessageW winLastError="+ctypes.winLastError);
     // result is a ctypes.Int64. So we need to create a CData from it before
     // casting it to a HICON.
     let icon = ctypes.cast(win32.LRESULT(rv), win32.HICON);
     let NULL = win32.HICON(null); // for comparison only
-    log.debug("SendMessageW winLastError="+ctypes.winLastError);
     if (firetray.js.strEquals(icon, NULL)) { // from the window class
       rv = user32.GetClassLong(hwnd, user32.GCLP_HICONSM);
       icon = ctypes.cast(win32.ULONG_PTR(rv), win32.HICON);
diff --git a/src/modules/winnt/FiretrayWin32.jsm b/src/modules/winnt/FiretrayWin32.jsm
index 74d8c72..0d7c279 100644
--- a/src/modules/winnt/FiretrayWin32.jsm
+++ b/src/modules/winnt/FiretrayWin32.jsm
@@ -15,8 +15,8 @@ firetray.Handler.subscribeLibsForClosing([kernel32, user32]);
 
 let log = firetray.Logging.getLogger("firetray.Win32");
 
-const kMessageTray     = "_FIRETRAY_TrayMessage";
-const kMessageCallback = "_FIRETRAY_TrayCallback";
+const kMessageTray     = "_FIRETRAY_Tray";
+const kMessageTrayFwd  = "_FIRETRAY_TrayFwd";
 
 if ("undefined" == typeof(firetray.Handler))
   log.error("This module MUST be imported from/after FiretrayHandler !");
@@ -26,9 +26,10 @@ function Win32Env() {
   this.hInstance = kernel32.GetModuleHandleW("xul"); // ordinary windows are created from xul.dll
   log.debug("hInstance="+this.hInstance);
 
+  // we use our own messages because we create a different window class than Moz
   this.WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated");
-  this.WM_TRAYMESSAGE  = user32.RegisterWindowMessageW(kMessageTray);
-  this.WM_TRAYCALLBACK = user32.RegisterWindowMessageW(kMessageCallback);
+  this.WM_TRAYMESSAGE    = user32.RegisterWindowMessageW(kMessageTray);
+  this.WM_TRAYMESSAGEFWD = user32.RegisterWindowMessageW(kMessageTrayFwd);
   log.debug("WM_*="+this.WM_TASKBARCREATED+" "+this.WM_TRAYMESSAGE+" "+this.WM_TRAYCALLBACK);
 
   /* if Administrator, accept messages from applications running in a lower
@@ -48,6 +49,14 @@ function Win32Env() {
     return rv;
   };
 
+  // wid will be used as a string most of the time (through f.Handler.windows mainly)
+  this.hwndToHexStr = function(hWnd) {
+    return "0x" + ctypes.cast(hWnd, ctypes.uintptr_t).value.toString(16);
+  };
+  this.hexStrToHwnd = function(wid) {
+    return win32.HWND(ctypes.UInt64(wid));
+  };
+
 }
 
 firetray.Win32 = new Win32Env();
diff --git a/src/modules/winnt/FiretrayWindow.jsm b/src/modules/winnt/FiretrayWindow.jsm
index aeee4ba..1eb505e 100644
--- a/src/modules/winnt/FiretrayWindow.jsm
+++ b/src/modules/winnt/FiretrayWindow.jsm
@@ -9,11 +9,12 @@ const Cu = Components.utils;
 Cu.import("resource://gre/modules/ctypes.jsm");
 Cu.import("resource://firetray/ctypes/ctypesMap.jsm");
 Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
+Cu.import("resource://firetray/ctypes/winnt/kernel32.jsm");
 Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
 Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
 Cu.import("resource://firetray/FiretrayWindow.jsm");
 Cu.import("resource://firetray/commons.js");
-firetray.Handler.subscribeLibsForClosing([user32]);
+firetray.Handler.subscribeLibsForClosing([kernel32, user32]);
 
 let log = firetray.Logging.getLogger("firetray.Window");
 
@@ -28,8 +29,7 @@ const kPropProcPrev = "_FIRETRAY_OLD_PROC";
 // NOTE: storing ctypes pointers into a JS object doesn't work: pointers are
 // "evolving" after a while (maybe due to back and forth conversion). So we
 // need to store them into a real ctypes array !
-firetray.Handler.wndProcs     = new ctypesMap(user32.WNDPROC);
-firetray.Handler.wndProcsOrig = new ctypesMap(user32.WNDPROC);
+firetray.Handler.callProcHooks     = new ctypesMap(win32.HHOOK);
 
 
 firetray.Window = new FiretrayWindow();
@@ -57,11 +57,6 @@ firetray.Window.startupHide = function(xid) {
 firetray.Window.setVisibility = function(xid, visibility) {
 };
 
-// wid will be used as a string most of the time (through f.Handler.windows mainly)
-firetray.Window.hwndToHexStr = function(hWnd) {
-  return "0x" + ctypes.cast(hWnd, ctypes.uintptr_t).value.toString(16);
-};
-
 firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow
   log.debug("wndProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
 
@@ -70,16 +65,12 @@ firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow
 
 try {
 
-  let wid = firetray.Window.hwndToHexStr(hWnd);
+  let wid = firetray.Win32.hwndToHexStr(hWnd);
   // let procPrev = firetray.Handler.wndProcsOrig.get(wid);
   // let procPrev = ctypes.cast(user32.GetPropW(hWnd, win32._T(kPropProcPrev)), user32.WNDPROC);
   // let procPrev = user32.GetPropW(hWnd, win32._T(kPropProcPrev));
   log.debug("  wid="+wid+" prev="+procPrev);
 
-  /*
-   * https://bugzilla.mozilla.org/show_bug.cgi?id=598679
-   * https://bugzilla.mozilla.org/show_bug.cgi?id=671266
-   */
   // let rv = user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam);
   let rv = procPrev(hWnd, uMsg, wParam, lParam);
   log.debug("  CallWindowProc="+rv);
@@ -100,6 +91,34 @@ log.error(error);
   // return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam);
 };
 
+firetray.Window.callProcHook = function(nCode, wParam, lParam) { // WH_CALLWNDPROC, WH_GETMESSAGE
+  // log.debug("callProcHook CALLED: nCode="+nCode+", wParam="+wParam+", lParam="+lParam);
+  let cwpstruct = ctypes.cast(win32.LPARAM(lParam), user32.CWPSTRUCT.ptr).contents;
+  let uMsg = cwpstruct.message;
+
+  if (uMsg === firetray.Win32.WM_TRAYMESSAGEFWD) {
+    log.debug("WM_TRAYMESSAGEFWD received!");
+
+    if (wParam != 0) {
+      log.debug("message was sent by the current thread");
+    }
+
+    let hWnd = cwpstruct.hwnd;
+    log.debug("hWnd="+hWnd);
+    let wid = firetray.Win32.hwndToHexStr(hWnd);
+    log.debug("wid="+wid);
+
+    if (nCode === user32.HC_ACTION) {
+      log.warn("*** must process the message ***");
+    } else if (nCode < 0) {
+      log.warn("*** must pass the message to the CallNextHookEx function without further processing ***");
+    }
+
+  }
+
+  return user32.CallNextHookEx(null, nCode, wParam, lParam);
+};
+
 
 
 ///////////////////////// firetray.Handler overriding /////////////////////////
@@ -121,7 +140,7 @@ firetray.Handler.registerWindow = function(win) {
   let hwnd = nativeHandle ?
         new ctypes.voidptr_t(ctypes.UInt64(nativeHandle)) :
         user32.FindWindowW("MozillaWindowClass", win.document.title);
-  let wid = firetray.Window.hwndToHexStr(hwnd);
+  let wid = firetray.Win32.hwndToHexStr(hwnd);
   log.debug("=== hwnd="+hwnd+" wid="+wid+" win.document.title: "+win.document.title);
 
   if (this.windows.hasOwnProperty(wid)) {
@@ -144,39 +163,28 @@ firetray.Handler.registerWindow = function(win) {
   // windows *are* shown at startup
   firetray.Window.updateVisibility(wid, true);
   log.debug("window "+wid+" registered");
-  // NOTE: shouldn't be necessary to gtk_widget_add_events(gtkWin, gdk.GDK_ALL_EVENTS_MASK);
 
 /*
-  // try {
-try {
-    let wndProc = user32.WNDPROC(firetray.Window.wndProc);
-    log.debug("proc="+wndProc);
-    this.wndProcs.insert(wid, wndProc);
-    let procPrev = user32.WNDPROC(
-      user32.SetWindowLongW(hwnd, user32.GWLP_WNDPROC, ctypes.cast(wndProc, win32.LONG_PTR))
-    );
-    log.debug("procPrev="+procPrev+" winLastError="+ctypes.winLastError);
-    this.wndProcsOrig.insert(wid, procPrev); // could be set as a window prop (SetPropW)
-
-    procPrev = ctypes.cast(procPrev, win32.HANDLE);
-    user32.SetPropW(hwnd, win32._T(kPropProcPrev), procPrev);
-    log.debug("SetPropW: "+procPrev+" winLastError="+ctypes.winLastError);
-  } catch(error) {
-log.error(error);
+  try {
+    let callProcHook = user32.HOOKPROC(firetray.Window.callProcHook);
+    log.debug("callhk="+callProcHook);
+    // Global hooks must reside in a dll (hence hInst). This is important for
+    // the scope of variables.
+    let hhook = user32.SetWindowsHookExW(
+      user32.WH_CALLWNDPROC, callProcHook, null, kernel32.GetCurrentThreadId());
+    log.debug("  hhook="+hhook+" winLastError="+ctypes.winLastError);
+    this.callProcHooks.insert(wid, hhook);
+
+    firetray.Win32.acceptAllMessages(hwnd);
+
+  } catch (x) {
+    if (x.name === "RangeError") // instanceof not working :-(
+      win.alert(x+"\n\nYou seem to have more than "+FIRETRAY_WINDOW_COUNT_MAX
+                +" windows open. This breaks FireTray and most probably "
+                +firetray.Handler.appName+".");
+    else win.alert(x);
   }
 */
-    // firetray.Win32.acceptAllMessages(hwnd);
-
-  // } catch (x) {
-  //   if (x.name === "RangeError") // instanceof not working :-(
-  //     win.alert(x+"\n\nYou seem to have more than "+FIRETRAY_WINDOW_COUNT_MAX
-  //               +" windows open. This breaks FireTray and most probably "
-  //               +firetray.Handler.appName+".");
-  //   else win.alert(x);
-  // }
-
-  // TODO: check wndproc chaining http://stackoverflow.com/a/8835843/421846 if
-  // needed for startupFilter
 
   log.debug("AFTER"); firetray.Handler.dumpWindows();
   return wid;
@@ -194,8 +202,10 @@ firetray.Handler.unregisterWindow = function(win) {
 
   if (!delete firetray.Handler.windows[wid])
     throw new DeleteError();
-  // firetray.Handler.wndProcs.remove(wid);
-  // firetray.Handler.wndProcsOrig.remove(wid);
+/*
+  user32.UnhookWindowsHookEx(firetray.Handler.callProcHooks.get(wid));
+  firetray.Handler.callProcHooks.remove(wid);
+*/
   firetray.Handler.windowsCount -= 1;
   firetray.Handler.visibleWindowsCount -= 1;
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firetray.git



More information about the Pkg-mozext-commits mailing list