summaryrefslogtreecommitdiffstats
path: root/toolkit/xre/dllservices/mozglue/WindowsMsctfInitialization.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/xre/dllservices/mozglue/WindowsMsctfInitialization.cpp')
-rw-r--r--toolkit/xre/dllservices/mozglue/WindowsMsctfInitialization.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/toolkit/xre/dllservices/mozglue/WindowsMsctfInitialization.cpp b/toolkit/xre/dllservices/mozglue/WindowsMsctfInitialization.cpp
new file mode 100644
index 0000000000..03a6a30deb
--- /dev/null
+++ b/toolkit/xre/dllservices/mozglue/WindowsMsctfInitialization.cpp
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/WindowsMsctfInitialization.h"
+
+#include <windows.h>
+
+#include "mozilla/NativeNt.h"
+#include "mozilla/WindowsVersion.h"
+#include "nsWindowsDllInterceptor.h"
+
+namespace mozilla {
+
+#if defined(_M_IX86) || defined(_M_X64)
+
+// Starting with Windows 11 22H2 (10.0.22621.*), msctf.dll uses a new
+// convention for the lParam argument of TF_Notify when uMsg is 0x20000. It now
+// expects a pointer to a structure similar to LPARAM20000 described below,
+// where a scalar value was used before. We convert the value forwarded by
+// ZoneAlarm Anti-Keylogger to the new convention, if we detect that it is
+// still using the old convention (bug 1777960).
+
+struct LPARAM20000 {
+ uintptr_t Reserved1; // Not used
+ LPARAM LegacyValue; // This value used to be sent as lParam directly
+ uintptr_t Reserved2; // Used as a boolean (though never saw it set to true)
+};
+
+static WindowsDllInterceptor MsctfIntercept;
+
+typedef uintptr_t(WINAPI* TF_Notify_func)(UINT uMsg, WPARAM wParam,
+ LPARAM lParam);
+static WindowsDllInterceptor::FuncHookType<TF_Notify_func> stub_TF_Notify;
+
+uintptr_t WINAPI patched_TF_Notify(UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ // Only convert to the new convention if we detect a problem with the lParam
+ if (uMsg == 0x20000 &&
+ IsBadReadPtr(reinterpret_cast<void*>(lParam), sizeof(LPARAM20000))) {
+ // Using a pointer to stack as lParam is fine here: when observing calls
+ // that originate from Microsoft code, pointers to stack are used as well
+ LPARAM20000 lParamWithNewConvention{
+ .Reserved1 = 0,
+ .LegacyValue = lParam,
+ .Reserved2 = 0,
+ };
+ return stub_TF_Notify(uMsg, wParam,
+ reinterpret_cast<LPARAM>(&lParamWithNewConvention));
+ }
+ return stub_TF_Notify(uMsg, wParam, lParam);
+}
+
+bool WindowsMsctfInitialization() {
+ // Only proceed if we detect ZoneAlarm Anti-Keylogger (bug 1777960)
+ HMODULE icsak = ::GetModuleHandleW(L"icsak.dll");
+ if (!icsak) {
+ return true;
+ }
+
+ // Only proceed if msctf.dll uses the new lParam convention
+ if (!IsWin1122H2OrLater()) {
+ return true;
+ }
+
+ // Only proceed if icsak.dll is in version 1.5.393.2181 or older
+ nt::PEHeaders icsakHeaders{icsak};
+ uint64_t icsakVersion{};
+ if (!icsakHeaders || !icsakHeaders.GetVersionInfo(icsakVersion) ||
+ icsakVersion > 0x0001000501890885) {
+ return true;
+ }
+
+ // Apply our hook to fix messages using the old lParam convention
+ MsctfIntercept.Init(L"msctf.dll");
+ return stub_TF_Notify.Set(MsctfIntercept, "TF_Notify", &patched_TF_Notify);
+}
+
+#endif // _M_IX86 || _M_X64
+
+} // namespace mozilla