Bug 1400344: Rename mscom::MainThreadRuntime to mscom::ProcessRuntime and make it aware of Win32k lockdown and of multiple instantiations; r=Jamie
☠☠ backed out by dbd7b92caef0 ☠ ☠
authorAaron Klotz <aklotz@mozilla.com>
Thu, 14 Feb 2019 16:40:58 +0000
changeset 459163 2d4b8d90cbd789525ae9a8829b21c3cecac5d594
parent 459162 e98c01bfb3fc84b35198f6abca75ad86a2b16b56
child 459164 c14813709eeb86deecd4725679e022e4478860d8
push id35556
push userdvarga@mozilla.com
push dateFri, 15 Feb 2019 01:38:24 +0000
treeherdermozilla-central@b29c87add05f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersJamie
bugs1400344
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1400344: Rename mscom::MainThreadRuntime to mscom::ProcessRuntime and make it aware of Win32k lockdown and of multiple instantiations; r=Jamie This patch takes care of a bunch of issues and does some cleanup: * We rename mscom::MainThreadRuntime to mscom::ProcessRuntime, as the latter is a more accurate name going forward. * We make ProcessRuntime aware of the Win32k Lockdown process mitigation policy. When Win32k is disabled, we perform process-wide COM initialization in the multi-threaded apartment (since we cannot create an STA window). * We refactor the mscom apartment region stuff to enable the Win32k lockdown pieces in ProcessRuntime. * We move some Gecko-specific stuff into MOZILLA_INTERNAL_API guards so that ProcessRuntime is usable outside of xul.dll (I will be needing it for the launcher process). * Another thing that might happen with the launcher process is that, under error conditions in the launcher, we create a ProcessRuntime object on a background thread for the purposes of telemetry logging, but we also allow the main thread to proceed to start as the browser. This could result in a scenario where the main thread, as the browser process, is attempting to instantiate its ProcessRuntime and ends up racing with the launcher process's telemetry thread which has its own ProcessRuntime. To account for this situation, we add mutual exclusion to the process-wide initialization code. We host this part inside mozglue since that state is shared between both firefox.exe and xul.dll. * We clean up ProcessRuntime::InitializeSecurity by using Vector to set up the EXPLICIT_ACCESS entries. * We remove mscom::MainThreadClientInfo and replace it with a direct call to CoGetCallerTID * We revise all references to this class to use the new name. Differential Revision: https://phabricator.services.mozilla.com/D19551
accessible/windows/msaa/LazyInstantiator.cpp
browser/app/winlauncher/LaunchUnelevated.cpp
dom/ipc/ContentProcess.h
dom/media/ipc/RDDProcessImpl.h
dom/plugins/ipc/PluginProcessChild.h
gfx/ipc/GPUProcessImpl.h
ipc/mscom/ApartmentRegion.h
ipc/mscom/COMApartmentRegion.h
ipc/mscom/EnsureMTA.h
ipc/mscom/MainThreadClientInfo.cpp
ipc/mscom/MainThreadClientInfo.h
ipc/mscom/MainThreadRuntime.cpp
ipc/mscom/MainThreadRuntime.h
ipc/mscom/ProcessRuntime.cpp
ipc/mscom/ProcessRuntime.h
ipc/mscom/Ptr.h
ipc/mscom/moz.build
ipc/mscom/mozglue/ProcessRuntimeShared.cpp
ipc/mscom/mozglue/ProcessRuntimeShared.h
ipc/mscom/mozglue/moz.build
mozglue/build/moz.build
toolkit/xre/nsAppRunner.cpp
widget/windows/JumpListBuilder.cpp
--- a/accessible/windows/msaa/LazyInstantiator.cpp
+++ b/accessible/windows/msaa/LazyInstantiator.cpp
@@ -6,17 +6,17 @@
 
 #include "LazyInstantiator.h"
 
 #include "MainThreadUtils.h"
 #include "mozilla/a11y/Accessible.h"
 #include "mozilla/a11y/Compatibility.h"
 #include "mozilla/a11y/Platform.h"
 #include "mozilla/Assertions.h"
-#include "mozilla/mscom/MainThreadRuntime.h"
+#include "mozilla/mscom/ProcessRuntime.h"
 #include "mozilla/mscom/Registration.h"
 #include "mozilla/UniquePtr.h"
 #include "nsAccessibilityService.h"
 #include "nsWindowsHelpers.h"
 #include "nsCOMPtr.h"
 #include "nsIFile.h"
 #include "nsXPCOM.h"
 #include "RootAccessibleWrap.h"
@@ -308,17 +308,17 @@ void LazyInstantiator::TransplantRefCnt(
 HRESULT
 LazyInstantiator::MaybeResolveRoot() {
   MOZ_ASSERT(NS_IsMainThread());
   if (mWeakAccessible) {
     return S_OK;
   }
 
   if (GetAccService() ||
-      ShouldInstantiate(mscom::MainThreadRuntime::GetClientThreadId())) {
+      ShouldInstantiate(mscom::ProcessRuntime::GetClientThreadId())) {
     mWeakRootAccWrap = ResolveRootAccWrap();
     if (!mWeakRootAccWrap) {
       return E_POINTER;
     }
 
     // Wrap ourselves around the root accessible wrap
     mRealRootUnk =
         mWeakRootAccWrap->Aggregate(static_cast<IAccessible *>(this));
--- a/browser/app/winlauncher/LaunchUnelevated.cpp
+++ b/browser/app/winlauncher/LaunchUnelevated.cpp
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 #include "LaunchUnelevated.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/CmdLineAndEnvUtils.h"
 #include "mozilla/LauncherResult.h"
-#include "mozilla/mscom/COMApartmentRegion.h"
+#include "mozilla/mscom/ApartmentRegion.h"
 #include "mozilla/RefPtr.h"
 #include "nsWindowsHelpers.h"
 
 // For _bstr_t and _variant_t
 #include <comdef.h>
 #include <comutil.h>
 
 #include <windows.h>
--- a/dom/ipc/ContentProcess.h
+++ b/dom/ipc/ContentProcess.h
@@ -7,17 +7,17 @@
 #ifndef dom_tabs_ContentThread_h
 #define dom_tabs_ContentThread_h 1
 
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/ipc/ScopedXREEmbed.h"
 #include "ContentChild.h"
 
 #if defined(XP_WIN)
-#  include "mozilla/mscom/MainThreadRuntime.h"
+#  include "mozilla/mscom/ProcessRuntime.h"
 #endif
 
 namespace mozilla {
 namespace dom {
 
 /**
  * ContentProcess is a singleton on the content process which represents
  * the main thread where tab instances live.
@@ -34,17 +34,17 @@ class ContentProcess : public mozilla::i
   virtual void CleanUp() override;
 
  private:
   ContentChild mContent;
   mozilla::ipc::ScopedXREEmbed mXREEmbed;
 
 #if defined(XP_WIN)
   // This object initializes and configures COM.
-  mozilla::mscom::MainThreadRuntime mCOMRuntime;
+  mozilla::mscom::ProcessRuntime mCOMRuntime;
 #endif
 
   DISALLOW_EVIL_CONSTRUCTORS(ContentProcess);
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
--- a/dom/media/ipc/RDDProcessImpl.h
+++ b/dom/media/ipc/RDDProcessImpl.h
@@ -3,17 +3,17 @@
 /* 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 _include_dom_media_ipc_RDDProcessImpl_h__
 #define _include_dom_media_ipc_RDDProcessImpl_h__
 #include "mozilla/ipc/ProcessChild.h"
 
 #if defined(XP_WIN)
-#  include "mozilla/mscom/MainThreadRuntime.h"
+#  include "mozilla/mscom/ProcessRuntime.h"
 #endif
 
 #include "RDDParent.h"
 
 namespace mozilla {
 
 // This class owns the subprocess instance of a PRDD - which in this case,
 // is a RDDParent. It is instantiated as a singleton in XRE_InitChildProcess.
--- a/dom/plugins/ipc/PluginProcessChild.h
+++ b/dom/plugins/ipc/PluginProcessChild.h
@@ -6,17 +6,17 @@
 
 #ifndef dom_plugins_PluginProcessChild_h
 #define dom_plugins_PluginProcessChild_h 1
 
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/plugins/PluginModuleChild.h"
 
 #if defined(XP_WIN)
-#  include "mozilla/mscom/MainThreadRuntime.h"
+#  include "mozilla/mscom/ProcessRuntime.h"
 #endif
 
 namespace mozilla {
 namespace plugins {
 //-----------------------------------------------------------------------------
 
 class PluginProcessChild : public mozilla::ipc::ProcessChild {
  protected:
@@ -35,17 +35,17 @@ class PluginProcessChild : public mozill
   static PluginProcessChild* current() {
     return static_cast<PluginProcessChild*>(ProcessChild::current());
   }
 
  private:
 #if defined(XP_WIN)
   /* Drag-and-drop depends on the host initializing COM.
    * This object initializes and configures COM. */
-  mozilla::mscom::MainThreadRuntime mCOMRuntime;
+  mozilla::mscom::ProcessRuntime mCOMRuntime;
 #endif
   PluginModuleChild mPlugin;
 
   DISALLOW_EVIL_CONSTRUCTORS(PluginProcessChild);
 };
 
 }  // namespace plugins
 }  // namespace mozilla
--- a/gfx/ipc/GPUProcessImpl.h
+++ b/gfx/ipc/GPUProcessImpl.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _include_gfx_ipc_GPUProcessImpl_h__
 #define _include_gfx_ipc_GPUProcessImpl_h__
 
 #include "mozilla/ipc/ProcessChild.h"
 #include "GPUParent.h"
 
 #if defined(XP_WIN)
-#  include "mozilla/mscom/MainThreadRuntime.h"
+#  include "mozilla/mscom/ProcessRuntime.h"
 #endif
 
 namespace mozilla {
 namespace gfx {
 
 // This class owns the subprocess instance of a PGPU - which in this case,
 // is a GPUParent. It is instantiated as a singleton in XRE_InitChildProcess.
 class GPUProcessImpl final : public ipc::ProcessChild {
@@ -28,16 +28,16 @@ class GPUProcessImpl final : public ipc:
 
  private:
   DISALLOW_COPY_AND_ASSIGN(GPUProcessImpl);
 
   GPUParent mGPU;
 
 #if defined(XP_WIN)
   // This object initializes and configures COM.
-  mozilla::mscom::MainThreadRuntime mCOMRuntime;
+  mozilla::mscom::ProcessRuntime mCOMRuntime;
 #endif
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif  // _include_gfx_ipc_GPUProcessImpl_h__
rename from ipc/mscom/COMApartmentRegion.h
rename to ipc/mscom/ApartmentRegion.h
--- a/ipc/mscom/COMApartmentRegion.h
+++ b/ipc/mscom/ApartmentRegion.h
@@ -1,53 +1,94 @@
 /* -*- 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_COMApartmentRegion_h
-#define mozilla_mscom_COMApartmentRegion_h
+#ifndef mozilla_mscom_ApartmentRegion_h
+#define mozilla_mscom_ApartmentRegion_h
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 
 #include <objbase.h>
 
 namespace mozilla {
 namespace mscom {
 
-template <COINIT T>
-class MOZ_NON_TEMPORARY_CLASS COMApartmentRegion {
+class MOZ_NON_TEMPORARY_CLASS ApartmentRegion {
  public:
-  COMApartmentRegion() : mInitResult(::CoInitializeEx(nullptr, T)) {
+  /**
+   * This constructor is to be used when we want to instantiate the object but
+   * we do not yet know which type of apartment we want. Call Init() to
+   * complete initialization.
+   */
+  ApartmentRegion() : mInitResult(CO_E_NOTINITIALIZED) {}
+
+  explicit ApartmentRegion(COINIT aAptType)
+      : mInitResult(::CoInitializeEx(nullptr, aAptType)) {
     // If this fires then we're probably mixing apartments on the same thread
     MOZ_ASSERT(IsValid());
   }
 
-  ~COMApartmentRegion() {
+  ~ApartmentRegion() {
     if (IsValid()) {
       ::CoUninitialize();
     }
   }
 
+  explicit operator bool() const { return IsValid(); }
+
   bool IsValidOutermost() const { return mInitResult == S_OK; }
 
   bool IsValid() const { return SUCCEEDED(mInitResult); }
 
-  HRESULT GetHResult() const { return mInitResult; }
+  bool Init(COINIT aAptType) {
+    MOZ_ASSERT(mInitResult == CO_E_NOTINITIALIZED);
+    mInitResult = ::CoInitializeEx(nullptr, aAptType);
+    MOZ_ASSERT(IsValid());
+    return IsValid();
+  }
+
+  HRESULT
+  GetHResult() const { return mInitResult; }
 
  private:
-  COMApartmentRegion(const COMApartmentRegion&) = delete;
-  COMApartmentRegion& operator=(const COMApartmentRegion&) = delete;
-  COMApartmentRegion(COMApartmentRegion&&) = delete;
-  COMApartmentRegion& operator=(COMApartmentRegion&&) = delete;
+  ApartmentRegion(const ApartmentRegion&) = delete;
+  ApartmentRegion& operator=(const ApartmentRegion&) = delete;
+  ApartmentRegion(ApartmentRegion&&) = delete;
+  ApartmentRegion& operator=(ApartmentRegion&&) = delete;
 
   HRESULT mInitResult;
 };
 
-typedef COMApartmentRegion<COINIT_APARTMENTTHREADED> STARegion;
-typedef COMApartmentRegion<COINIT_MULTITHREADED> MTARegion;
+template <COINIT T>
+class MOZ_NON_TEMPORARY_CLASS ApartmentRegionT {
+ public:
+  ApartmentRegionT() : mAptRgn(T) {}
+
+  ~ApartmentRegionT() = default;
+
+  explicit operator bool() const { return mAptRgn.IsValid(); }
+
+  bool IsValidOutermost() const { return mAptRgn.IsValidOutermost(); }
+
+  bool IsValid() const { return mAptRgn.IsValid(); }
+
+  HRESULT GetHResult() const { return mAptRgn.GetHResult(); }
+
+ private:
+  ApartmentRegionT(const ApartmentRegionT&) = delete;
+  ApartmentRegionT& operator=(const ApartmentRegionT&) = delete;
+  ApartmentRegionT(ApartmentRegionT&&) = delete;
+  ApartmentRegionT& operator=(ApartmentRegionT&&) = delete;
+
+  ApartmentRegion mAptRgn;
+};
+
+typedef ApartmentRegionT<COINIT_APARTMENTTHREADED> STARegion;
+typedef ApartmentRegionT<COINIT_MULTITHREADED> MTARegion;
 
 }  // namespace mscom
 }  // namespace mozilla
 
-#endif  // mozilla_mscom_COMApartmentRegion_h
+#endif  // mozilla_mscom_ApartmentRegion_h
--- a/ipc/mscom/EnsureMTA.h
+++ b/ipc/mscom/EnsureMTA.h
@@ -6,17 +6,16 @@
 
 #ifndef mozilla_mscom_EnsureMTA_h
 #define mozilla_mscom_EnsureMTA_h
 
 #include "MainThreadUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Unused.h"
-#include "mozilla/mscom/COMApartmentRegion.h"
 #include "mozilla/mscom/Utils.h"
 #include "nsCOMPtr.h"
 #include "nsIThread.h"
 #include "nsThreadUtils.h"
 #include "nsWindowsHelpers.h"
 
 #include <windows.h>
 
deleted file mode 100644
--- a/ipc/mscom/MainThreadClientInfo.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- 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 "MainThreadClientInfo.h"
-
-#include "MainThreadUtils.h"
-#include "mozilla/Assertions.h"
-
-#include <objbase.h>
-
-namespace mozilla {
-namespace mscom {
-
-/* static */
-HRESULT
-MainThreadClientInfo::Create(MainThreadClientInfo** aOutObj) {
-  MOZ_ASSERT(aOutObj && NS_IsMainThread());
-  *aOutObj = nullptr;
-
-  RefPtr<MainThreadClientInfo> obj(new MainThreadClientInfo());
-
-  RefPtr<IMessageFilter> prevFilter;
-  HRESULT hr = ::CoRegisterMessageFilter(obj.get(), getter_AddRefs(prevFilter));
-  if (FAILED(hr)) {
-    return hr;
-  }
-
-  obj->mPrevFilter = prevFilter.forget();
-
-  obj.forget(aOutObj);
-  return S_OK;
-}
-
-DWORD
-MainThreadClientInfo::GetLastRemoteCallThreadId() const {
-  MOZ_ASSERT(NS_IsMainThread());
-  return mLastRemoteCallTid;
-}
-
-HRESULT
-MainThreadClientInfo::QueryInterface(REFIID aIid, void** aOutInterface) {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!aOutInterface) {
-    return E_INVALIDARG;
-  }
-
-  if (aIid == IID_IUnknown || aIid == IID_IMessageFilter) {
-    RefPtr<IMessageFilter> filter(this);
-    filter.forget(aOutInterface);
-    return S_OK;
-  }
-
-  return E_NOINTERFACE;
-}
-
-ULONG
-MainThreadClientInfo::AddRef() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  return ++mRefCnt;
-}
-
-ULONG
-MainThreadClientInfo::Release() {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  ULONG newCount = --mRefCnt;
-  if (!newCount) {
-    delete this;
-  }
-  return newCount;
-}
-
-DWORD
-MainThreadClientInfo::HandleInComingCall(DWORD aCallType, HTASK aCallerTid,
-                                         DWORD aTickCount,
-                                         LPINTERFACEINFO aInterfaceInfo) {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  // aCallerTid is an HTASK for historical reasons but is actually just a
-  // regular DWORD Thread ID.
-  mLastRemoteCallTid =
-      static_cast<DWORD>(reinterpret_cast<uintptr_t>(aCallerTid));
-
-  if (!mPrevFilter) {
-    return SERVERCALL_ISHANDLED;
-  }
-
-  return mPrevFilter->HandleInComingCall(aCallType, aCallerTid, aTickCount,
-                                         aInterfaceInfo);
-}
-
-DWORD
-MainThreadClientInfo::RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount,
-                                        DWORD aRejectType) {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!mPrevFilter) {
-    return 0;
-  }
-
-  return mPrevFilter->RetryRejectedCall(aCalleeTid, aTickCount, aRejectType);
-}
-
-DWORD
-MainThreadClientInfo::MessagePending(HTASK aCalleeTid, DWORD aTickCount,
-                                     DWORD aPendingType) {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!mPrevFilter) {
-    return PENDINGMSG_WAITNOPROCESS;
-  }
-
-  return mPrevFilter->MessagePending(aCalleeTid, aTickCount, aPendingType);
-}
-
-MainThreadClientInfo::MainThreadClientInfo()
-    : mRefCnt(0), mLastRemoteCallTid(0) {
-  MOZ_ASSERT(NS_IsMainThread());
-}
-
-void MainThreadClientInfo::Detach() {
-  MOZ_ASSERT(NS_IsMainThread());
-  ::CoRegisterMessageFilter(mPrevFilter, nullptr);
-  mPrevFilter = nullptr;
-}
-
-}  // namespace mscom
-}  // namespace mozilla
deleted file mode 100644
--- a/ipc/mscom/MainThreadClientInfo.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- 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_MainThreadClientInfo
-#define mozilla_mscom_MainThreadClientInfo
-
-#include "mozilla/RefPtr.h"
-#include "nsString.h"
-
-#include <objidl.h>
-
-namespace mozilla {
-namespace mscom {
-
-class MainThreadClientInfo final : public IMessageFilter {
- public:
-  static HRESULT Create(MainThreadClientInfo** aOutObj);
-
-  DWORD GetLastRemoteCallThreadId() const;
-  void Detach();
-
-  STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override;
-  STDMETHODIMP_(ULONG) AddRef() override;
-  STDMETHODIMP_(ULONG) Release() override;
-
-  STDMETHODIMP_(DWORD)
-  HandleInComingCall(DWORD aCallType, HTASK aCallerTid, DWORD aTickCount,
-                     LPINTERFACEINFO aInterfaceInfo) override;
-  STDMETHODIMP_(DWORD)
-  RetryRejectedCall(HTASK aCalleeTid, DWORD aTickCount,
-                    DWORD aRejectType) override;
-  STDMETHODIMP_(DWORD)
-  MessagePending(HTASK aCalleeTid, DWORD aTickCount,
-                 DWORD aPendingType) override;
-
- private:
-  MainThreadClientInfo();
-  ~MainThreadClientInfo() = default;
-
- private:
-  ULONG mRefCnt;
-  RefPtr<IMessageFilter> mPrevFilter;
-  DWORD mLastRemoteCallTid;
-};
-
-}  // namespace mscom
-}  // namespace mozilla
-
-#endif  // mozilla_mscom_MainThreadClientInfo
rename from ipc/mscom/MainThreadRuntime.cpp
rename to ipc/mscom/ProcessRuntime.cpp
--- a/ipc/mscom/MainThreadRuntime.cpp
+++ b/ipc/mscom/ProcessRuntime.cpp
@@ -1,59 +1,101 @@
 /* -*- 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/MainThreadRuntime.h"
+#include "mozilla/mscom/ProcessRuntime.h"
 
-#if defined(ACCESSIBILITY)
+#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
 #  include "mozilla/a11y/Compatibility.h"
-#endif
-#include "mozilla/ArrayUtils.h"
+#endif  // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
 #include "mozilla/Assertions.h"
+#include "mozilla/DynamicallyLinkedFunctionPtr.h"
+#include "mozilla/mscom/ProcessRuntimeShared.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
+#include "mozilla/Unused.h"
+#include "mozilla/Vector.h"
 #include "mozilla/WindowsVersion.h"
-#if defined(ACCESSIBILITY)
-#  include "nsExceptionHandler.h"
-#endif  // defined(ACCESSIBILITY)
 #include "nsWindowsHelpers.h"
-#include "nsXULAppAPI.h"
+
+#if defined(MOZILLA_INTERNAL_API)
+#  include "mozilla/mscom/EnsureMTA.h"
+#  include "nsThreadManager.h"
+#endif  // defined(MOZILLA_INTERNAL_API)
 
 #include <accctrl.h>
 #include <aclapi.h>
 #include <objbase.h>
 #include <objidl.h>
 
 // This API from oleaut32.dll is not declared in Windows SDK headers
 extern "C" void __cdecl SetOaNoCache(void);
 
+#if (_WIN32_WINNT < 0x0602)
+BOOL WINAPI GetProcessMitigationPolicy(
+    HANDLE hProcess, PROCESS_MITIGATION_POLICY MitigationPolicy, PVOID lpBuffer,
+    SIZE_T dwLength);
+#endif  // (_WIN32_WINNT < 0x0602)
+
 namespace mozilla {
 namespace mscom {
 
-MainThreadRuntime* MainThreadRuntime::sInstance = nullptr;
-
-MainThreadRuntime::MainThreadRuntime()
-    : mInitResult(E_UNEXPECTED)
-#if defined(ACCESSIBILITY)
+ProcessRuntime::ProcessRuntime(GeckoProcessType aProcessType)
+    : mInitResult(CO_E_NOTINITIALIZED),
+      mIsParentProcess(aProcessType == GeckoProcessType_Default)
+#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
       ,
       mActCtxRgn(a11y::Compatibility::GetActCtxResourceId())
-#endif  // defined(ACCESSIBILITY)
+#endif  // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
 {
+#if defined(MOZILLA_INTERNAL_API)
+  // If our process is running under Win32k lockdown, we cannot initialize
+  // COM with single-threaded apartments. This is because STAs create a hidden
+  // window, which implicitly requires user32 and Win32k, which are blocked.
+  // Instead we start a multi-threaded apartment and conduct our process-wide
+  // COM initialization on that MTA background thread.
+  if (IsWin32kLockedDown()) {
+    // It is possible that we're running so early that we might need to start
+    // the thread manager ourselves.
+    nsresult rv = nsThreadManager::get().Init();
+    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
+    if (NS_FAILED(rv)) {
+      return;
+    }
+
+    EnsureMTA([this]() -> void { InitInsideApartment(); });
+    return;
+  }
+#endif  // defined(MOZILLA_INTERNAL_API)
+
+  // Otherwise we initialize a single-threaded apartment on the current thread.
+  mAptRegion.Init(COINIT_APARTMENTTHREADED);
+
   // We must be the outermost COM initialization on this thread. The COM runtime
   // cannot be configured once we start manipulating objects
-  MOZ_ASSERT(mStaRegion.IsValidOutermost());
-  if (NS_WARN_IF(!mStaRegion.IsValidOutermost())) {
+  MOZ_ASSERT(mAptRegion.IsValidOutermost());
+  if (!mAptRegion.IsValidOutermost()) {
+    mInitResult = mAptRegion.GetHResult();
     return;
   }
 
-  // We are required to initialize security in order to configure global
-  // options.
+  InitInsideApartment();
+}
+
+void ProcessRuntime::InitInsideApartment() {
+  ProcessInitLock lock;
+  if (lock.IsInitialized()) {
+    // COM has already been initialized by a previous ProcessRuntime instance
+    return;
+  }
+
+  // We are required to initialize security prior to configuring global options.
   mInitResult = InitializeSecurity();
   MOZ_ASSERT(SUCCEEDED(mInitResult));
   if (FAILED(mInitResult)) {
     return;
   }
 
   RefPtr<IGlobalOptions> globalOpts;
   mInitResult = ::CoCreateInstance(CLSID_GlobalOptions, nullptr,
@@ -71,68 +113,35 @@ MainThreadRuntime::MainThreadRuntime()
 
   // Disable the BSTR cache (as it never invalidates, thus leaking memory)
   ::SetOaNoCache();
 
   if (FAILED(mInitResult)) {
     return;
   }
 
-  if (XRE_IsParentProcess()) {
-    MainThreadClientInfo::Create(getter_AddRefs(mClientInfo));
-  }
-
-  MOZ_ASSERT(!sInstance);
-  sInstance = this;
-}
-
-MainThreadRuntime::~MainThreadRuntime() {
-  if (mClientInfo) {
-    mClientInfo->Detach();
-  }
-
-  MOZ_ASSERT(sInstance == this);
-  if (sInstance == this) {
-    sInstance = nullptr;
-  }
+  lock.SetInitialized();
 }
 
 /* static */
 DWORD
-MainThreadRuntime::GetClientThreadId() {
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(XRE_IsParentProcess(), "Unsupported outside of parent process");
-  if (!XRE_IsParentProcess()) {
-    return 0;
-  }
-
-  // Don't check for a calling executable if the caller is in-process.
-  // We verify this by asking COM for a call context. If none exists, then
-  // we must be a local call.
-  RefPtr<IServerSecurity> serverSecurity;
-  if (FAILED(::CoGetCallContext(IID_IServerSecurity,
-                                getter_AddRefs(serverSecurity)))) {
+ProcessRuntime::GetClientThreadId() {
+  DWORD callerTid;
+  HRESULT hr = ::CoGetCallerTID(&callerTid);
+  // Don't return callerTid unless the call succeeded and returned S_FALSE,
+  // indicating that the caller originates from a different process.
+  if (hr != S_FALSE) {
     return 0;
   }
 
-  MOZ_ASSERT(sInstance);
-  if (!sInstance) {
-    return 0;
-  }
-
-  MOZ_ASSERT(sInstance->mClientInfo);
-  if (!sInstance->mClientInfo) {
-    return 0;
-  }
-
-  return sInstance->mClientInfo->GetLastRemoteCallThreadId();
+  return callerTid;
 }
 
 HRESULT
-MainThreadRuntime::InitializeSecurity() {
+ProcessRuntime::InitializeSecurity() {
   HANDLE rawToken = nullptr;
   BOOL ok = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken);
   if (!ok) {
     return HRESULT_FROM_WIN32(::GetLastError());
   }
   nsAutoHandle token(rawToken);
 
   DWORD len = 0;
@@ -181,57 +190,62 @@ MainThreadRuntime::InitializeSecurity() 
   DWORD adminSidSize = sizeof(adminSid);
   if (!::CreateWellKnownSid(WinBuiltinAdministratorsSid, nullptr, adminSid,
                             &adminSidSize)) {
     return HRESULT_FROM_WIN32(::GetLastError());
   }
 
   BYTE appContainersSid[SECURITY_MAX_SID_SIZE];
   DWORD appContainersSidSize = sizeof(appContainersSid);
-  if (XRE_IsParentProcess() && IsWin8OrLater()) {
+  if (mIsParentProcess && IsWin8OrLater()) {
     if (!::CreateWellKnownSid(WinBuiltinAnyPackageSid, nullptr,
                               appContainersSid, &appContainersSidSize)) {
       return HRESULT_FROM_WIN32(::GetLastError());
     }
   }
 
   // Grant access to SYSTEM, Administrators, the user, and when running as the
   // browser process on Windows 8+, all app containers.
-  EXPLICIT_ACCESS entries[] = {
-      {COM_RIGHTS_EXECUTE,
-       GRANT_ACCESS,
-       NO_INHERITANCE,
-       {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER,
-        reinterpret_cast<LPWSTR>(systemSid)}},
-      {COM_RIGHTS_EXECUTE,
-       GRANT_ACCESS,
-       NO_INHERITANCE,
-       {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID,
-        TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast<LPWSTR>(adminSid)}},
-      {COM_RIGHTS_EXECUTE,
-       GRANT_ACCESS,
-       NO_INHERITANCE,
-       {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER,
-        reinterpret_cast<LPWSTR>(tokenUser.User.Sid)}},
-      // appContainersSid must be the last entry in this array!
-      {COM_RIGHTS_EXECUTE,
-       GRANT_ACCESS,
-       NO_INHERITANCE,
-       {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID,
-        TRUSTEE_IS_WELL_KNOWN_GROUP,
-        reinterpret_cast<LPWSTR>(appContainersSid)}}};
+  const size_t kMaxInlineEntries = 4;
+  mozilla::Vector<EXPLICIT_ACCESS_W, kMaxInlineEntries> entries;
+
+  Unused << entries.append(EXPLICIT_ACCESS_W{
+      COM_RIGHTS_EXECUTE,
+      GRANT_ACCESS,
+      NO_INHERITANCE,
+      {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER,
+       reinterpret_cast<LPWSTR>(systemSid)}});
 
-  ULONG numEntries = ArrayLength(entries);
-  if (!XRE_IsParentProcess() || !IsWin8OrLater()) {
-    // Exclude appContainersSid on Windows 7 and non-parent processes.
-    --numEntries;
+  Unused << entries.append(EXPLICIT_ACCESS_W{
+      COM_RIGHTS_EXECUTE,
+      GRANT_ACCESS,
+      NO_INHERITANCE,
+      {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID,
+       TRUSTEE_IS_WELL_KNOWN_GROUP, reinterpret_cast<LPWSTR>(adminSid)}});
+
+  Unused << entries.append(EXPLICIT_ACCESS_W{
+      COM_RIGHTS_EXECUTE,
+      GRANT_ACCESS,
+      NO_INHERITANCE,
+      {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_USER,
+       reinterpret_cast<LPWSTR>(tokenUser.User.Sid)}});
+
+  if (mIsParentProcess && IsWin8OrLater()) {
+    Unused << entries.append(
+        EXPLICIT_ACCESS_W{COM_RIGHTS_EXECUTE,
+                          GRANT_ACCESS,
+                          NO_INHERITANCE,
+                          {nullptr, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID,
+                           TRUSTEE_IS_WELL_KNOWN_GROUP,
+                           reinterpret_cast<LPWSTR>(appContainersSid)}});
   }
 
   PACL rawDacl = nullptr;
-  win32Error = ::SetEntriesInAcl(numEntries, entries, nullptr, &rawDacl);
+  win32Error =
+      ::SetEntriesInAclW(entries.length(), entries.begin(), nullptr, &rawDacl);
   if (win32Error != ERROR_SUCCESS) {
     return HRESULT_FROM_WIN32(win32Error);
   }
 
   UniquePtr<ACL, LocalFreeDeleter> dacl(rawDacl);
 
   if (!::SetSecurityDescriptorDacl(&sd, TRUE, dacl.get(), FALSE)) {
     return HRESULT_FROM_WIN32(::GetLastError());
@@ -246,10 +260,31 @@ MainThreadRuntime::InitializeSecurity() 
     return HRESULT_FROM_WIN32(::GetLastError());
   }
 
   return ::CoInitializeSecurity(
       &sd, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT,
       RPC_C_IMP_LEVEL_IDENTIFY, nullptr, EOAC_NONE, nullptr);
 }
 
+#if defined(MOZILLA_INTERNAL_API)
+
+/* static */ bool
+ProcessRuntime::IsWin32kLockedDown() {
+  static const DynamicallyLinkedFunctionPtr<decltype(&::GetProcessMitigationPolicy)>
+    pGetProcessMitigationPolicy(L"kernel32.dll", "GetProcessMitigationPolicy");
+  if (!pGetProcessMitigationPolicy) {
+    return false;
+  }
+
+  PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY polInfo;
+  if (!pGetProcessMitigationPolicy(::GetCurrentProcess(),
+      ProcessSystemCallDisablePolicy, &polInfo, sizeof(polInfo))) {
+    return false;
+  }
+
+  return polInfo.DisallowWin32kSystemCalls;
+}
+
+#endif  // defined(MOZILLA_INTERNAL_API)
+
 }  // namespace mscom
 }  // namespace mozilla
rename from ipc/mscom/MainThreadRuntime.h
rename to ipc/mscom/ProcessRuntime.h
--- a/ipc/mscom/MainThreadRuntime.h
+++ b/ipc/mscom/ProcessRuntime.h
@@ -1,58 +1,61 @@
 /* -*- 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_MainThreadRuntime_h
-#define mozilla_mscom_MainThreadRuntime_h
+#ifndef mozilla_mscom_ProcessRuntime_h
+#define mozilla_mscom_ProcessRuntime_h
 
 #include "mozilla/Attributes.h"
-#if defined(ACCESSIBILITY)
+#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
 #  include "mozilla/mscom/ActivationContext.h"
-#endif  // defined(ACCESSIBILITY)
-#include "mozilla/mscom/COMApartmentRegion.h"
-#include "mozilla/mscom/MainThreadClientInfo.h"
-#include "mozilla/RefPtr.h"
+#endif  // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
+#include "mozilla/mscom/ApartmentRegion.h"
+#include "nsXULAppAPI.h"
 
 namespace mozilla {
 namespace mscom {
 
-class MOZ_NON_TEMPORARY_CLASS MainThreadRuntime {
+class MOZ_NON_TEMPORARY_CLASS ProcessRuntime final {
  public:
-  MainThreadRuntime();
-  ~MainThreadRuntime();
+#if defined(MOZILLA_INTERNAL_API)
+  ProcessRuntime() : ProcessRuntime(XRE_GetProcessType()) {}
+#endif  // defined(MOZILLA_INTERNAL_API)
 
-  explicit operator bool() const {
-    return mStaRegion.IsValidOutermost() && SUCCEEDED(mInitResult);
-  }
+  explicit ProcessRuntime(GeckoProcessType aProcessType);
+  ~ProcessRuntime() = default;
+
+  explicit operator bool() const { return SUCCEEDED(mInitResult); }
 
-  MainThreadRuntime(MainThreadRuntime&) = delete;
-  MainThreadRuntime(MainThreadRuntime&&) = delete;
-  MainThreadRuntime& operator=(MainThreadRuntime&) = delete;
-  MainThreadRuntime& operator=(MainThreadRuntime&&) = delete;
+  ProcessRuntime(ProcessRuntime&) = delete;
+  ProcessRuntime(ProcessRuntime&&) = delete;
+  ProcessRuntime& operator=(ProcessRuntime&) = delete;
+  ProcessRuntime& operator=(ProcessRuntime&&) = delete;
 
   /**
    * @return 0 if call is in-process or resolving the calling thread failed,
    *         otherwise contains the thread id of the calling thread.
    */
   static DWORD GetClientThreadId();
 
  private:
+  void InitInsideApartment();
   HRESULT InitializeSecurity();
 
+#if defined(MOZILLA_INTERNAL_API)
+  static bool IsWin32kLockedDown();
+#endif  // defined(MOZILLA_INTERNAL_API)
+
   HRESULT mInitResult;
-#if defined(ACCESSIBILITY)
+  bool mIsParentProcess;
+#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
   ActivationContextRegion mActCtxRgn;
-#endif  // defined(ACCESSIBILITY)
-  STARegion mStaRegion;
-
-  RefPtr<MainThreadClientInfo> mClientInfo;
-
-  static MainThreadRuntime* sInstance;
+#endif  // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
+  ApartmentRegion mAptRegion;
 };
 
 }  // namespace mscom
 }  // namespace mozilla
 
-#endif  // mozilla_mscom_MainThreadRuntime_h
+#endif  // mozilla_mscom_ProcessRuntime_h
--- a/ipc/mscom/Ptr.h
+++ b/ipc/mscom/Ptr.h
@@ -11,16 +11,18 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/mscom/EnsureMTA.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/UniquePtr.h"
 #include "nsError.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 
+#include <objidl.h>
+
 /**
  * The glue code in mozilla::mscom often needs to pass around interface pointers
  * belonging to a different apartment from the current one. We must not touch
  * the reference counts of those objects on the wrong apartment. By using these
  * UniquePtr specializations, we may ensure that the reference counts are always
  * handled correctly.
  */
 
--- a/ipc/mscom/moz.build
+++ b/ipc/mscom/moz.build
@@ -2,40 +2,42 @@
 # 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/.
 
 EXPORTS.mozilla.mscom += [
     'Aggregation.h',
     'AgileReference.h',
+    'ApartmentRegion.h',
     'AsyncInvoker.h',
-    'COMApartmentRegion.h',
     'COMPtrHolder.h',
     'EnsureMTA.h',
-    'MainThreadClientInfo.h',
-    'MainThreadRuntime.h',
     'Objref.h',
     'PassthruProxy.h',
+    'ProcessRuntime.h',
     'ProxyStream.h',
     'Ptr.h',
     'Utils.h',
 ]
 
+DIRS += [
+    'mozglue',
+]
+
 SOURCES += [
     'VTableBuilder.c',
 ]
 
 UNIFIED_SOURCES += [
     'AgileReference.cpp',
     'EnsureMTA.cpp',
-    'MainThreadClientInfo.cpp',
-    'MainThreadRuntime.cpp',
     'Objref.cpp',
     'PassthruProxy.cpp',
+    'ProcessRuntime.cpp',
     'ProxyStream.cpp',
     'RegistrationAnnotator.cpp',
     'Utils.cpp',
 ]
 
 if CONFIG['ACCESSIBILITY']:
     DIRS += [
         'oop',
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/mozglue/ProcessRuntimeShared.cpp
@@ -0,0 +1,33 @@
+/* -*- 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 "MozglueUtils.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 bool gIsProcessInitialized = false;
+
+namespace mozilla {
+namespace mscom {
+namespace detail {
+
+MFBT_API bool&
+BeginProcessRuntimeInit() {
+  gLock.LockExclusive();
+  return gIsProcessInitialized;
+}
+
+MFBT_API void
+EndProcessRuntimeInit() {
+  gLock.UnlockExclusive();
+}
+
+}  //  namespace detail
+}  // namespace mscom
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/mozglue/ProcessRuntimeShared.h
@@ -0,0 +1,54 @@
+/* -*- 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 {
+
+MFBT_API bool& BeginProcessRuntimeInit();
+MFBT_API void EndProcessRuntimeInit();
+
+}  // namespace detail
+
+class MOZ_RAII ProcessInitLock final {
+ public:
+  ProcessInitLock()
+    : mIsProcessInitialized(detail::BeginProcessRuntimeInit()) {
+  }
+
+  ~ProcessInitLock() {
+    detail::EndProcessRuntimeInit();
+  }
+
+  bool IsInitialized() const {
+    return mIsProcessInitialized;
+  }
+
+  void SetInitialized() {
+    MOZ_ASSERT(!mIsProcessInitialized);
+    mIsProcessInitialized = true;
+  }
+
+  ProcessInitLock(const ProcessInitLock&) = delete;
+  ProcessInitLock(ProcessInitLock&&) = delete;
+  ProcessInitLock operator=(const ProcessInitLock&) = delete;
+  ProcessInitLock operator=(ProcessInitLock&&) = delete;
+
+ private:
+  bool& mIsProcessInitialized;
+};
+
+}  // namespace mscom
+}  // namespace mozilla
+
+#endif  // mozilla_mscom_ProcessRuntimeShared_h
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/mozglue/moz.build
@@ -0,0 +1,21 @@
+# -*- 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/.
+
+Library('mscom-mozglue')
+
+EXPORTS.mozilla.mscom += [
+    'ProcessRuntimeShared.h',
+]
+
+LOCAL_INCLUDES += [
+    '/mozglue/build',
+]
+
+DEFINES['IMPL_MFBT'] = True
+
+UNIFIED_SOURCES += [
+    'ProcessRuntimeShared.cpp',
+]
--- a/mozglue/build/moz.build
+++ b/mozglue/build/moz.build
@@ -31,16 +31,19 @@ if CONFIG['MOZ_UBSAN']:
 
 if CONFIG['OS_TARGET'] == 'WINNT':
     DEFFILE = '!mozglue.def'
     # We'll break the DLL blocklist if we immediately load user32.dll
     DELAYLOAD_DLLS += [
         'user32.dll',
     ]
     RCINCLUDE = 'mozglue.rc'
+    USE_LIBS += [
+        'mscom-mozglue',
+    ]
 
     if CONFIG['MOZ_PGO'] and CONFIG['CC_TYPE'] == 'clang-cl':
         SOURCES += ['cygprofile.cpp']
         SOURCES['cygprofile.cpp'].pgo_generate_only = True
 
 if CONFIG['MOZ_WIDGET_TOOLKIT']:
 
     if CONFIG['MOZ_MEMORY'] and FORCE_SHARED_LIB:
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -105,17 +105,17 @@
 #ifdef XP_WIN
 #  include "nsIWinAppHelper.h"
 #  include <windows.h>
 #  include <intrin.h>
 #  include <math.h>
 #  include "cairo/cairo-features.h"
 #  include "mozilla/WindowsDllBlocklist.h"
 #  include "mozilla/WinHeaderOnlyUtils.h"
-#  include "mozilla/mscom/MainThreadRuntime.h"
+#  include "mozilla/mscom/ProcessRuntime.h"
 #  include "mozilla/widget/AudioSession.h"
 
 #  if defined(MOZ_LAUNCHER_PROCESS)
 #    include "mozilla/LauncherRegistryInfo.h"
 #  endif
 
 #  ifndef PROCESS_DEP_ENABLE
 #    define PROCESS_DEP_ENABLE 0x1
@@ -4798,17 +4798,17 @@ int XREMain::XRE_main(int argc, char* ar
 
   mozilla::IOInterposerInit ioInterposerGuard;
 
 #if defined(XP_WIN)
   // Some COM settings are global to the process and must be set before any non-
   // trivial COM is run in the application. Since these settings may affect
   // stability, we should instantiate COM ASAP so that we can ensure that these
   // global settings are configured before anything can interfere.
-  mozilla::mscom::MainThreadRuntime msCOMRuntime;
+  mozilla::mscom::ProcessRuntime msCOMRuntime;
 #endif
 
   // init
   bool exit = false;
   int result = XRE_mainInit(&exit);
   if (result != 0 || exit) return result;
 
   // If we exit gracefully, remove the startup crash canary file.
--- a/widget/windows/JumpListBuilder.cpp
+++ b/widget/windows/JumpListBuilder.cpp
@@ -18,17 +18,17 @@
 #include "mozilla/Preferences.h"
 #include "nsStringStream.h"
 #include "nsThreadUtils.h"
 #include "mozilla/LazyIdleThread.h"
 #include "nsIObserverService.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/mscom/COMApartmentRegion.h"
+#include "mozilla/mscom/ApartmentRegion.h"
 #include "mozilla/mscom/EnsureMTA.h"
 
 #include <shellapi.h>
 #include "WinUtils.h"
 
 using mozilla::dom::Promise;
 
 // The amount of time, in milliseconds, that our IO thread will stay alive after