summaryrefslogtreecommitdiffstats
path: root/ipc/mscom/mozglue
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/mscom/mozglue')
-rw-r--r--ipc/mscom/mozglue/ActCtxResource.cpp239
-rw-r--r--ipc/mscom/mozglue/ActCtxResource.h40
-rw-r--r--ipc/mscom/mozglue/ProcessRuntimeShared.cpp31
-rw-r--r--ipc/mscom/mozglue/ProcessRuntimeShared.h55
-rw-r--r--ipc/mscom/mozglue/moz.build19
5 files changed, 384 insertions, 0 deletions
diff --git a/ipc/mscom/mozglue/ActCtxResource.cpp b/ipc/mscom/mozglue/ActCtxResource.cpp
new file mode 100644
index 0000000000..778e36c4bc
--- /dev/null
+++ b/ipc/mscom/mozglue/ActCtxResource.cpp
@@ -0,0 +1,239 @@
+/* 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 "ActCtxResource.h"
+
+#include <string>
+
+#include "mozilla/GetKnownFolderPath.h"
+#include "mozilla/WindowsVersion.h"
+#include "nsWindowsHelpers.h"
+
+namespace mozilla {
+namespace mscom {
+
+#if !defined(HAVE_64BIT_BUILD)
+
+static bool ReadCOMRegDefaultString(const std::wstring& aRegPath,
+ std::wstring& aOutBuf) {
+ aOutBuf.clear();
+
+ std::wstring fullyQualifiedRegPath;
+ fullyQualifiedRegPath.append(L"SOFTWARE\\Classes\\");
+ fullyQualifiedRegPath.append(aRegPath);
+
+ // Get the required size and type of the registry value.
+ // We expect either REG_SZ or REG_EXPAND_SZ.
+ DWORD type;
+ DWORD bufLen = 0;
+ LONG result =
+ ::RegGetValueW(HKEY_LOCAL_MACHINE, fullyQualifiedRegPath.c_str(), nullptr,
+ RRF_RT_ANY, &type, nullptr, &bufLen);
+ if (result != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) {
+ return false;
+ }
+
+ // Now obtain the value
+ DWORD flags = type == REG_SZ ? RRF_RT_REG_SZ : RRF_RT_REG_EXPAND_SZ;
+
+ aOutBuf.resize((bufLen + 1) / sizeof(char16_t));
+
+ result = ::RegGetValueW(HKEY_LOCAL_MACHINE, fullyQualifiedRegPath.c_str(),
+ nullptr, flags, nullptr, &aOutBuf[0], &bufLen);
+ if (result != ERROR_SUCCESS) {
+ aOutBuf.clear();
+ return false;
+ }
+
+ // Truncate terminator
+ aOutBuf.resize((bufLen + 1) / sizeof(char16_t) - 1);
+ return true;
+}
+
+static bool IsSystemOleAcc(HANDLE aFile) {
+ if (aFile == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ BY_HANDLE_FILE_INFORMATION info = {};
+ if (!::GetFileInformationByHandle(aFile, &info)) {
+ return false;
+ }
+
+ // Use FOLDERID_SystemX86 so that Windows doesn't give us a redirected
+ // system32 if we're a 32-bit process running on a 64-bit OS. This is
+ // necessary because the values that we are reading from the registry
+ // are not redirected; they reference SysWOW64 directly.
+ auto systemPath = GetKnownFolderPath(FOLDERID_SystemX86);
+ if (!systemPath) {
+ return false;
+ }
+
+ std::wstring oleAccPath(systemPath.get());
+ oleAccPath.append(L"\\oleacc.dll");
+
+ nsAutoHandle oleAcc(
+ ::CreateFileW(oleAccPath.c_str(), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
+
+ if (oleAcc.get() == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ BY_HANDLE_FILE_INFORMATION oleAccInfo = {};
+ if (!::GetFileInformationByHandle(oleAcc, &oleAccInfo)) {
+ return false;
+ }
+
+ return info.dwVolumeSerialNumber == oleAccInfo.dwVolumeSerialNumber &&
+ info.nFileIndexLow == oleAccInfo.nFileIndexLow &&
+ info.nFileIndexHigh == oleAccInfo.nFileIndexHigh;
+}
+
+static bool IsTypelibPreferred() {
+ // If IAccessible's Proxy/Stub CLSID is kUniversalMarshalerClsid, then any
+ // external a11y clients are expecting to use a typelib.
+ const wchar_t kUniversalMarshalerClsid[] =
+ L"{00020424-0000-0000-C000-000000000046}";
+
+ const wchar_t kIAccessiblePSClsidPath[] =
+ L"Interface\\{618736E0-3C3D-11CF-810C-00AA00389B71}"
+ L"\\ProxyStubClsid32";
+
+ std::wstring psClsid;
+ if (!ReadCOMRegDefaultString(kIAccessiblePSClsidPath, psClsid)) {
+ return false;
+ }
+
+ if (psClsid.size() !=
+ sizeof(kUniversalMarshalerClsid) / sizeof(kUniversalMarshalerClsid)[0] -
+ 1) {
+ return false;
+ }
+
+ int index = 0;
+ while (kUniversalMarshalerClsid[index]) {
+ if (toupper(psClsid[index]) != kUniversalMarshalerClsid[index]) {
+ return false;
+ }
+ index++;
+ }
+ return true;
+}
+
+static bool IsIAccessibleTypelibRegistered() {
+ // The system default IAccessible typelib is always registered with version
+ // 1.1, under the neutral locale (LCID 0).
+ const wchar_t kIAccessibleTypelibRegPath[] =
+ L"TypeLib\\{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}\\1.1\\0\\win32";
+
+ std::wstring typelibPath;
+ if (!ReadCOMRegDefaultString(kIAccessibleTypelibRegPath, typelibPath)) {
+ return false;
+ }
+
+ nsAutoHandle libTestFile(
+ ::CreateFileW(typelibPath.c_str(), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
+
+ return IsSystemOleAcc(libTestFile);
+}
+
+static bool IsIAccessiblePSRegistered() {
+ const wchar_t kIAccessiblePSRegPath[] =
+ L"CLSID\\{03022430-ABC4-11D0-BDE2-00AA001A1953}\\InProcServer32";
+
+ std::wstring proxyStubPath;
+ if (!ReadCOMRegDefaultString(kIAccessiblePSRegPath, proxyStubPath)) {
+ return false;
+ }
+
+ nsAutoHandle libTestFile(
+ ::CreateFileW(proxyStubPath.c_str(), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
+
+ return IsSystemOleAcc(libTestFile);
+}
+
+static bool UseIAccessibleProxyStub() {
+ // If a typelib is preferred then external clients are expecting to use
+ // typelib marshaling, so we should use that whenever available.
+ if (IsTypelibPreferred() && IsIAccessibleTypelibRegistered()) {
+ return false;
+ }
+
+ // Otherwise we try the proxy/stub
+ if (IsIAccessiblePSRegistered()) {
+ return true;
+ }
+
+ return false;
+}
+
+#endif // !defined(HAVE_64BIT_BUILD)
+
+#if defined(_MSC_VER)
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+#endif
+
+static HMODULE GetContainingModuleHandle() {
+ HMODULE thisModule = nullptr;
+#if defined(_MSC_VER)
+ thisModule = reinterpret_cast<HMODULE>(&__ImageBase);
+#else
+ if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ reinterpret_cast<LPCWSTR>(&GetContainingModuleHandle),
+ &thisModule)) {
+ return 0;
+ }
+#endif
+ return thisModule;
+}
+
+static uint16_t sActCtxResourceId = 0;
+
+/* static */
+void ActCtxResource::SetAccessibilityResourceId(uint16_t aResourceId) {
+ sActCtxResourceId = aResourceId;
+}
+
+/* static */
+uint16_t ActCtxResource::GetAccessibilityResourceId() {
+ return sActCtxResourceId;
+}
+
+static void EnsureAccessibilityResourceId() {
+ if (!sActCtxResourceId) {
+#if defined(HAVE_64BIT_BUILD)
+ // The manifest for 64-bit Windows is embedded with resource ID 64.
+ sActCtxResourceId = 64;
+#else
+ // The manifest for 32-bit Windows is embedded with resource ID 32.
+ // Beginning with Windows 10 Creators Update, 32-bit builds always use the
+ // 64-bit manifest. Older builds of Windows may or may not require the
+ // 64-bit manifest: UseIAccessibleProxyStub() determines the course of
+ // action.
+ if (mozilla::IsWin10CreatorsUpdateOrLater() || UseIAccessibleProxyStub()) {
+ sActCtxResourceId = 64;
+ } else {
+ sActCtxResourceId = 32;
+ }
+#endif // defined(HAVE_64BIT_BUILD)
+ }
+}
+
+ActCtxResource ActCtxResource::GetAccessibilityResource() {
+ ActCtxResource result = {};
+ result.mModule = GetContainingModuleHandle();
+ EnsureAccessibilityResourceId();
+ result.mId = GetAccessibilityResourceId();
+ return result;
+}
+
+} // namespace mscom
+} // namespace mozilla
diff --git a/ipc/mscom/mozglue/ActCtxResource.h b/ipc/mscom/mozglue/ActCtxResource.h
new file mode 100644
index 0000000000..4e9c16c8e0
--- /dev/null
+++ b/ipc/mscom/mozglue/ActCtxResource.h
@@ -0,0 +1,40 @@
+/* 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/. */
+
+#ifndef ACT_CTX_RESOURCE_H
+#define ACT_CTX_RESOURCE_H
+
+#include <stdint.h>
+#include <windows.h>
+#include "mozilla/Types.h"
+
+namespace mozilla {
+namespace mscom {
+
+struct ActCtxResource {
+ uint16_t mId;
+ HMODULE mModule;
+
+ /**
+ * Set the resource ID used by GetAccessibilityResource. This is so that
+ * sandboxed child processes can use a value passed down from the parent.
+ */
+ static MFBT_API void SetAccessibilityResourceId(uint16_t aResourceId);
+
+ /**
+ * Get the resource ID used by GetAccessibilityResource.
+ */
+ static MFBT_API uint16_t GetAccessibilityResourceId();
+
+ /**
+ * @return ActCtxResource of a11y manifest resource to be passed to
+ * mscom::ActivationContext
+ */
+ static MFBT_API ActCtxResource GetAccessibilityResource();
+};
+
+} // namespace mscom
+} // namespace mozilla
+
+#endif
diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.cpp b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp
new file mode 100644
index 0000000000..ee4f6b221f
--- /dev/null
+++ b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp
@@ -0,0 +1,31 @@
+/* -*- 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/mscom/ProcessRuntimeShared.h"
+
+#include "mozilla/glue/WinUtils.h"
+
+// We allow multiple ProcessRuntime instances to exist simultaneously (even
+// on separate threads), but only one should be doing the process-wide
+// initialization. These variables provide that mutual exclusion.
+static mozilla::glue::Win32SRWLock gLock;
+static mozilla::mscom::detail::ProcessInitState gProcessInitState =
+ mozilla::mscom::detail::ProcessInitState::Uninitialized;
+
+namespace mozilla {
+namespace mscom {
+namespace detail {
+
+MFBT_API ProcessInitState& BeginProcessRuntimeInit() {
+ gLock.LockExclusive();
+ return gProcessInitState;
+}
+
+MFBT_API void EndProcessRuntimeInit() { gLock.UnlockExclusive(); }
+
+} // namespace detail
+} // namespace mscom
+} // namespace mozilla
diff --git a/ipc/mscom/mozglue/ProcessRuntimeShared.h b/ipc/mscom/mozglue/ProcessRuntimeShared.h
new file mode 100644
index 0000000000..d5a58a7b92
--- /dev/null
+++ b/ipc/mscom/mozglue/ProcessRuntimeShared.h
@@ -0,0 +1,55 @@
+/* -*- 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/. */
+
+#ifndef mozilla_mscom_ProcessRuntimeShared_h
+#define mozilla_mscom_ProcessRuntimeShared_h
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Types.h"
+
+namespace mozilla {
+namespace mscom {
+namespace detail {
+
+enum class ProcessInitState : uint32_t {
+ Uninitialized = 0,
+ PartialSecurityInitialized,
+ PartialGlobalOptions,
+ FullyInitialized,
+};
+
+MFBT_API ProcessInitState& BeginProcessRuntimeInit();
+MFBT_API void EndProcessRuntimeInit();
+
+} // namespace detail
+
+class MOZ_RAII ProcessInitLock final {
+ public:
+ ProcessInitLock() : mInitState(detail::BeginProcessRuntimeInit()) {}
+
+ ~ProcessInitLock() { detail::EndProcessRuntimeInit(); }
+
+ detail::ProcessInitState GetInitState() const { return mInitState; }
+
+ void SetInitState(const detail::ProcessInitState aNewState) {
+ MOZ_DIAGNOSTIC_ASSERT(aNewState > mInitState);
+ mInitState = aNewState;
+ }
+
+ ProcessInitLock(const ProcessInitLock&) = delete;
+ ProcessInitLock(ProcessInitLock&&) = delete;
+ ProcessInitLock operator=(const ProcessInitLock&) = delete;
+ ProcessInitLock operator=(ProcessInitLock&&) = delete;
+
+ private:
+ detail::ProcessInitState& mInitState;
+};
+
+} // namespace mscom
+} // namespace mozilla
+
+#endif // mozilla_mscom_ProcessRuntimeShared_h
diff --git a/ipc/mscom/mozglue/moz.build b/ipc/mscom/mozglue/moz.build
new file mode 100644
index 0000000000..635b5264cf
--- /dev/null
+++ b/ipc/mscom/mozglue/moz.build
@@ -0,0 +1,19 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+FINAL_LIBRARY = "mozglue"
+
+EXPORTS.mozilla.mscom += [
+ "ActCtxResource.h",
+ "ProcessRuntimeShared.h",
+]
+
+UNIFIED_SOURCES += [
+ "ActCtxResource.cpp",
+ "ProcessRuntimeShared.cpp",
+]
+
+REQUIRES_UNIFIED_BUILD = True