Bug 1014673 - Allow WM_GETOBJECT calls to succeed when mozilla window procedures are neutered by ipc WaitForNotify calls. r=bent

This commit is contained in:
Jim Mathies
2014-05-30 14:30:54 -05:00
parent 76076cf517
commit 102ccc0fef
2 changed files with 57 additions and 25 deletions

View File

@@ -86,6 +86,7 @@ extern UINT sDefaultBrowserMsgId;
namespace {
const wchar_t kOldWndProcProp[] = L"MozillaIPCOldWndProc";
const wchar_t k3rdPartyWindowProp[] = L"Mozilla3rdPartyWindow";
// This isn't defined before Windows XP.
enum { WM_XP_THEMECHANGED = 0x031A };
@@ -103,6 +104,9 @@ HHOOK gDeferredCallWndProcHook = nullptr;
DWORD gUIThreadId = 0;
// WM_GETOBJECT id pulled from uia headers
#define MOZOBJID_UIAROOT -25
LRESULT CALLBACK
DeferredMessageHook(int nCode,
WPARAM wParam,
@@ -161,6 +165,28 @@ ScheduleDeferredMessageRun()
}
}
static void
DumpNeuteredMessage(HWND hwnd, UINT uMsg)
{
#ifdef DEBUG
nsAutoCString log("Received \"nonqueued\" message ");
log.AppendInt(uMsg);
log.AppendLiteral(" during a synchronous IPC message for window ");
log.AppendInt((int64_t)hwnd);
wchar_t className[256] = { 0 };
if (GetClassNameW(hwnd, className, sizeof(className) - 1) > 0) {
log.AppendLiteral(" (\"");
log.Append(NS_ConvertUTF16toUTF8((char16_t*)className));
log.AppendLiteral("\")");
}
log.AppendLiteral(", sending it to DefWindowProc instead of the normal "
"window procedure.");
NS_ERROR(log.get());
#endif
}
LRESULT
ProcessOrDeferMessage(HWND hwnd,
UINT uMsg,
@@ -285,7 +311,24 @@ ProcessOrDeferMessage(HWND hwnd,
case WM_APP-1:
return 0;
// We only support a query for our IAccessible or UIA pointers.
// This should be safe, and needs to be sync.
#if defined(ACCESSIBILITY)
case WM_GETOBJECT: {
if (!::GetPropW(hwnd, k3rdPartyWindowProp)) {
DWORD objId = static_cast<DWORD>(lParam);
WNDPROC oldWndProc = (WNDPROC)GetProp(hwnd, kOldWndProcProp);
if ((objId == OBJID_CLIENT || objId == MOZOBJID_UIAROOT) && oldWndProc) {
return CallWindowProcW(oldWndProc, hwnd, uMsg, wParam, lParam);
}
}
break;
}
#endif // ACCESSIBILITY
default: {
// Unknown messages only are logged in debug builds and sent to
// DefWindowProc.
if (uMsg && uMsg == mozilla::widget::sAppShellGeckoMsgId) {
// Widget's registered native event callback
deferred = new DeferredSendMessage(hwnd, uMsg, wParam, lParam);
@@ -294,31 +337,16 @@ ProcessOrDeferMessage(HWND hwnd,
// Metro widget's system shutdown message
deferred = new DeferredSendMessage(hwnd, uMsg, wParam, lParam);
#endif
} else {
// Unknown messages only
#ifdef DEBUG
nsAutoCString log("Received \"nonqueued\" message ");
log.AppendInt(uMsg);
log.AppendLiteral(" during a synchronous IPC message for window ");
log.AppendInt((int64_t)hwnd);
wchar_t className[256] = { 0 };
if (GetClassNameW(hwnd, className, sizeof(className) - 1) > 0) {
log.AppendLiteral(" (\"");
log.Append(NS_ConvertUTF16toUTF8((char16_t*)className));
log.AppendLiteral("\")");
}
}
}
log.AppendLiteral(", sending it to DefWindowProc instead of the normal "
"window procedure.");
NS_ERROR(log.get());
#endif
// No deferred message was created and we land here, this is an
// unhandled message.
if (!deferred) {
DumpNeuteredMessage(hwnd, uMsg);
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
}
NS_ASSERTION(deferred, "Must have a message here!");
// Create the deferred message array if it doesn't exist already.
if (!gDeferredMessages) {
@@ -400,6 +428,7 @@ WindowIsDeferredWindow(HWND hWnd)
if (className.EqualsLiteral("ShockwaveFlashFullScreen") ||
className.EqualsLiteral("QTNSHIDDEN") ||
className.EqualsLiteral("AGFullScreenWinClass")) {
SetPropW(hWnd, k3rdPartyWindowProp, (HANDLE)1);
return true;
}
@@ -407,6 +436,7 @@ WindowIsDeferredWindow(HWND hWnd)
// earth process. The earth process can trigger a plugin incall on the browser
// at any time, which is badness if the instance is already making an incall.
if (className.EqualsLiteral("__geplugin_bridge_window__")) {
SetPropW(hWnd, k3rdPartyWindowProp, (HANDLE)1);
return true;
}
@@ -473,7 +503,8 @@ NeuterWindowProcedure(HWND hWnd)
// Cleanup
NS_WARNING("SetProp failed!");
SetWindowLongPtr(hWnd, GWLP_WNDPROC, currentWndProc);
RemoveProp(hWnd, kOldWndProcProp);
RemovePropW(hWnd, kOldWndProcProp);
RemovePropW(hWnd, k3rdPartyWindowProp);
return false;
}
@@ -495,7 +526,8 @@ RestoreWindowProcedure(HWND hWnd)
NS_ASSERTION(currentWndProc == (LONG_PTR)NeuteredWindowProc,
"This should never be switched out from under us!");
}
RemoveProp(hWnd, kOldWndProcProp);
RemovePropW(hWnd, kOldWndProcProp);
RemovePropW(hWnd, k3rdPartyWindowProp);
}
LRESULT CALLBACK

View File

@@ -77,7 +77,7 @@ UINT sDefaultBrowserMsgId = RegisterWindowMessageW(L"DefaultBrowserClosing");
} }
// WM_GETOBJECT id pulled from uia headers
#define UiaRootObjectId -25
#define MOZOBJID_UIAROOT -25
namespace mozilla {
namespace widget {
@@ -892,7 +892,7 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
// UiaReturnRawElementProvider passing the return result from FrameworkView
// OnAutomationProviderRequested as the hwnd (me scratches head) which results in
// GetLastError always being set to invalid handle (6) after CallWindowProc returns.
if (dwObjId == UiaRootObjectId && gProviderRoot) {
if (dwObjId == MOZOBJID_UIAROOT && gProviderRoot) {
ComPtr<IRawElementProviderSimple> simple;
gProviderRoot.As(&simple);
if (simple) {