зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1714212 - Ensure COM initialized prior to showing skeleton UI r=Jamie,aklotz,tkikuchi
This implements Jamie's suggested fixes for a screenreader issue when the skeleton UI is enabled. Most of the work here is just pulling out pieces from the files we needed to include in mozglue so that any references to, say, nsString or other pieces from libxul either no longer exist or are only included when building libxul. In a few cases this meant creating whole files to house single functions, which isn't so pretty, but it was the best I could come up with to get the job done. Differential Revision: https://phabricator.services.mozilla.com/D117663
This commit is contained in:
Родитель
31bbc107fb
Коммит
c3702a9447
|
@ -8,7 +8,7 @@
|
|||
#define mozilla_a11y_COMPtrTypes_h
|
||||
|
||||
#include "mozilla/a11y/AccessibleHandler.h"
|
||||
#include "mozilla/a11y/Compatibility.h"
|
||||
#include "mozilla/mscom/ActCtxResource.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/mscom/ActivationContext.h"
|
||||
#include "mozilla/mscom/COMPtrHolder.h"
|
||||
|
@ -33,7 +33,7 @@ class MOZ_RAII IAccessibleEnvironment : public mscom::ProxyStream::Environment {
|
|||
private:
|
||||
static const mscom::ActivationContext& GetActCtx() {
|
||||
static const mscom::ActivationContext sActCtx(
|
||||
Compatibility::GetActCtxResourceId());
|
||||
mscom::ActCtxResource::GetAccessibilityResource());
|
||||
MOZ_DIAGNOSTIC_ASSERT(sActCtx);
|
||||
return sActCtx;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/a11y/AccessibleHandler.h"
|
||||
#include "mozilla/a11y/Compatibility.h"
|
||||
#include "mozilla/a11y/PlatformChild.h"
|
||||
#include "mozilla/mscom/ActCtxResource.h"
|
||||
#include "mozilla/mscom/EnsureMTA.h"
|
||||
#include "mozilla/mscom/InterceptorLog.h"
|
||||
|
||||
|
@ -56,13 +56,13 @@ PlatformChild::PlatformChild()
|
|||
mozilla::mscom::RegistrationFlags::eUseSystemDirectory)),
|
||||
mMiscTypelib(mozilla::mscom::RegisterTypelib(L"Accessible.tlb")),
|
||||
mSdnTypelib(mozilla::mscom::RegisterTypelib(L"AccessibleMarshal.dll")) {
|
||||
WORD actCtxResourceId = Compatibility::GetActCtxResourceId();
|
||||
auto actCtxResource = mscom::ActCtxResource::GetAccessibilityResource();
|
||||
|
||||
mozilla::mscom::MTADeletePtr<mozilla::mscom::ActivationContextRegion>
|
||||
tmpActCtxMTA;
|
||||
mozilla::mscom::EnsureMTA([actCtxResourceId, &tmpActCtxMTA]() -> void {
|
||||
mozilla::mscom::EnsureMTA([actCtxResource, &tmpActCtxMTA]() -> void {
|
||||
tmpActCtxMTA.reset(
|
||||
new mozilla::mscom::ActivationContextRegion(actCtxResourceId));
|
||||
new mozilla::mscom::ActivationContextRegion(actCtxResource));
|
||||
});
|
||||
mActCtxMTA = std::move(tmpActCtxMTA);
|
||||
|
||||
|
|
|
@ -13,15 +13,6 @@ if CONFIG["COMPILE_ENVIRONMENT"] and CONFIG["ACCESSIBILITY"]:
|
|||
if CONFIG["ACCESSIBILITY"]:
|
||||
IPDL_SOURCES += ["PDocAccessible.ipdl"]
|
||||
|
||||
if not CONFIG["HAVE_64BIT_BUILD"]:
|
||||
EXPORTS += [
|
||||
"IAccessible32.manifest",
|
||||
]
|
||||
|
||||
EXPORTS += [
|
||||
"IAccessible64.manifest",
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.a11y += [
|
||||
"COMPtrTypes.h",
|
||||
"DocAccessibleChild.h",
|
||||
|
|
|
@ -225,175 +225,6 @@ void Compatibility::Init() {
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(HAVE_64BIT_BUILD)
|
||||
|
||||
static bool ReadCOMRegDefaultString(const nsString& aRegPath,
|
||||
nsAString& aOutBuf) {
|
||||
aOutBuf.Truncate();
|
||||
|
||||
nsAutoString fullyQualifiedRegPath;
|
||||
fullyQualifiedRegPath.AppendLiteral(u"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 = ::RegGetValue(HKEY_LOCAL_MACHINE, fullyQualifiedRegPath.get(),
|
||||
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.SetLength((bufLen + 1) / sizeof(char16_t));
|
||||
|
||||
result =
|
||||
::RegGetValue(HKEY_LOCAL_MACHINE, fullyQualifiedRegPath.get(), nullptr,
|
||||
flags, nullptr, aOutBuf.BeginWriting(), &bufLen);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
aOutBuf.Truncate();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Truncate terminator
|
||||
aOutBuf.Truncate((bufLen + 1) / sizeof(char16_t) - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsSystemOleAcc(nsCOMPtr<nsIFile>& aFile) {
|
||||
// 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.
|
||||
PWSTR systemPath = nullptr;
|
||||
HRESULT hr =
|
||||
::SHGetKnownFolderPath(FOLDERID_SystemX86, 0, nullptr, &systemPath);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> oleAcc;
|
||||
nsresult rv = NS_NewLocalFile(nsDependentString(systemPath), false,
|
||||
getter_AddRefs(oleAcc));
|
||||
|
||||
::CoTaskMemFree(systemPath);
|
||||
systemPath = nullptr;
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rv = oleAcc->Append(u"oleacc.dll"_ns);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isEqual;
|
||||
rv = oleAcc->Equals(aFile, &isEqual);
|
||||
return NS_SUCCEEDED(rv) && isEqual;
|
||||
}
|
||||
|
||||
static bool IsTypelibPreferred() {
|
||||
// If IAccessible's Proxy/Stub CLSID is kUniversalMarshalerClsid, then any
|
||||
// external a11y clients are expecting to use a typelib.
|
||||
constexpr auto kUniversalMarshalerClsid =
|
||||
u"{00020424-0000-0000-C000-000000000046}"_ns;
|
||||
|
||||
constexpr auto kIAccessiblePSClsidPath =
|
||||
"Interface\\{618736E0-3C3D-11CF-810C-00AA00389B71}"
|
||||
u"\\ProxyStubClsid32"_ns;
|
||||
|
||||
nsAutoString psClsid;
|
||||
if (!ReadCOMRegDefaultString(kIAccessiblePSClsidPath, psClsid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return psClsid.Equals(kUniversalMarshalerClsid,
|
||||
nsCaseInsensitiveStringComparator);
|
||||
}
|
||||
|
||||
static bool IsIAccessibleTypelibRegistered() {
|
||||
// The system default IAccessible typelib is always registered with version
|
||||
// 1.1, under the neutral locale (LCID 0).
|
||||
constexpr auto kIAccessibleTypelibRegPath =
|
||||
u"TypeLib\\{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}\\1.1\\0\\win32"_ns;
|
||||
|
||||
nsAutoString typelibPath;
|
||||
if (!ReadCOMRegDefaultString(kIAccessibleTypelibRegPath, typelibPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> libTestFile;
|
||||
nsresult rv =
|
||||
NS_NewLocalFile(typelibPath, false, getter_AddRefs(libTestFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsSystemOleAcc(libTestFile);
|
||||
}
|
||||
|
||||
static bool IsIAccessiblePSRegistered() {
|
||||
constexpr auto kIAccessiblePSRegPath =
|
||||
u"CLSID\\{03022430-ABC4-11D0-BDE2-00AA001A1953}\\InProcServer32"_ns;
|
||||
|
||||
nsAutoString proxyStubPath;
|
||||
if (!ReadCOMRegDefaultString(kIAccessiblePSRegPath, proxyStubPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> libTestFile;
|
||||
nsresult rv =
|
||||
NS_NewLocalFile(proxyStubPath, false, getter_AddRefs(libTestFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// If we reach this point then something is seriously wrong with the
|
||||
// IAccessible configuration in the computer's registry. Let's annotate this
|
||||
// so that we can easily determine this condition during crash analysis.
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::IAccessibleConfig, "NoSystemTypeLibOrPS"_ns);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // !defined(HAVE_64BIT_BUILD)
|
||||
|
||||
uint16_t Compatibility::GetActCtxResourceId() {
|
||||
#if defined(HAVE_64BIT_BUILD)
|
||||
// The manifest for 64-bit Windows is embedded with resource ID 64.
|
||||
return 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()) {
|
||||
return 64;
|
||||
}
|
||||
|
||||
return 32;
|
||||
#endif // defined(HAVE_64BIT_BUILD)
|
||||
}
|
||||
|
||||
// static
|
||||
void Compatibility::GetHumanReadableConsumersStr(nsAString& aResult) {
|
||||
bool appened = false;
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include <windows.h>
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsString.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -48,12 +47,6 @@ class Compatibility {
|
|||
*/
|
||||
static bool IsVisperoShared() { return !!(sConsumers & VISPEROSHARED); }
|
||||
|
||||
/**
|
||||
* @return ID of a11y manifest resource to be passed to
|
||||
* mscom::ActivationContext
|
||||
*/
|
||||
static uint16_t GetActCtxResourceId();
|
||||
|
||||
/**
|
||||
* Return a string describing sConsumers suitable for about:support.
|
||||
* Exposed through nsIXULRuntime.accessibilityInstantiator.
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#if defined(XP_WIN)
|
||||
# include <windows.h>
|
||||
# include <stdlib.h>
|
||||
# include "mozilla/PreXULSkeletonUI.h"
|
||||
#elif defined(XP_UNIX)
|
||||
# include <sys/resource.h>
|
||||
# include <unistd.h>
|
||||
|
@ -25,6 +24,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "mozilla/PreXULSkeletonUI.h"
|
||||
# include "freestanding/SharedSection.h"
|
||||
# include "LauncherProcessWin.h"
|
||||
# include "mozilla/WindowsDllBlocklist.h"
|
||||
|
@ -377,6 +377,10 @@ int main(int argc, char* argv[], char* envp[]) {
|
|||
|
||||
int result = do_main(argc, argv, envp);
|
||||
|
||||
#if defined(XP_WIN)
|
||||
CleanupProcessRuntime();
|
||||
#endif
|
||||
|
||||
gBootstrap->NS_LogTerm();
|
||||
|
||||
#if defined(DEBUG) && defined(HAS_DLL_BLOCKLIST)
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
# endif
|
||||
|
||||
# include "mozilla/NativeNt.h"
|
||||
# include "mozilla/CacheNtDllThunk.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||
|
@ -228,7 +229,7 @@ class WindowsProcessLauncher : public BaseProcessLauncher {
|
|||
std::vector<std::string>&& aExtraOpts)
|
||||
: BaseProcessLauncher(aHost, std::move(aExtraOpts)),
|
||||
mProfileDir(aHost->mProfileDir),
|
||||
mCachedNtdllThunk(aHost->sCachedNtDllThunk),
|
||||
mCachedNtdllThunk(GetCachedNtDllThunk()),
|
||||
mWerDataPointer(&(aHost->mWerData)) {}
|
||||
|
||||
protected:
|
||||
|
@ -242,7 +243,7 @@ class WindowsProcessLauncher : public BaseProcessLauncher {
|
|||
|
||||
nsCOMPtr<nsIFile> mProfileDir;
|
||||
|
||||
const StaticAutoPtr<Buffer<IMAGE_THUNK_DATA>>& mCachedNtdllThunk;
|
||||
const Buffer<IMAGE_THUNK_DATA>* mCachedNtdllThunk;
|
||||
CrashReporter::WindowsErrorReportingData const* mWerDataPointer;
|
||||
};
|
||||
typedef WindowsProcessLauncher ProcessLauncher;
|
||||
|
@ -351,51 +352,6 @@ mozilla::StaticAutoPtr<mozilla::LinkedList<GeckoChildProcessHost>>
|
|||
|
||||
mozilla::StaticMutex GeckoChildProcessHost::sMutex;
|
||||
|
||||
#ifdef XP_WIN
|
||||
mozilla::StaticAutoPtr<Buffer<IMAGE_THUNK_DATA>>
|
||||
GeckoChildProcessHost::sCachedNtDllThunk;
|
||||
|
||||
// This static method initializes sCachedNtDllThunk. Because it's called in
|
||||
// XREMain::XRE_main, which happens long before WindowsProcessLauncher's ctor
|
||||
// accesses sCachedNtDllThunk, there is no race on sCachedNtDllThunk, thus
|
||||
// no mutex is needed.
|
||||
/* static */
|
||||
void GeckoChildProcessHost::CacheNtDllThunk() {
|
||||
if (sCachedNtDllThunk) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
nt::PEHeaders ourExeImage(::GetModuleHandleW(nullptr));
|
||||
if (!ourExeImage) {
|
||||
break;
|
||||
}
|
||||
|
||||
nt::PEHeaders ntdllImage(::GetModuleHandleW(L"ntdll.dll"));
|
||||
if (!ntdllImage) {
|
||||
break;
|
||||
}
|
||||
|
||||
Maybe<Range<const uint8_t>> ntdllBoundaries = ntdllImage.GetBounds();
|
||||
if (!ntdllBoundaries) {
|
||||
break;
|
||||
}
|
||||
|
||||
Maybe<Span<IMAGE_THUNK_DATA>> maybeNtDllThunks =
|
||||
ourExeImage.GetIATThunksForModule("ntdll.dll", ntdllBoundaries.ptr());
|
||||
if (maybeNtDllThunks.isNothing()) {
|
||||
break;
|
||||
}
|
||||
|
||||
sCachedNtDllThunk = new Buffer<IMAGE_THUNK_DATA>(maybeNtDllThunks.value());
|
||||
return;
|
||||
} while (false);
|
||||
|
||||
// Failed to cache IAT. Initializing the variable with nullptr.
|
||||
sCachedNtDllThunk = new Buffer<IMAGE_THUNK_DATA>();
|
||||
}
|
||||
#endif
|
||||
|
||||
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
|
||||
bool aIsFileContent)
|
||||
: mProcessType(aProcessType),
|
||||
|
|
|
@ -142,7 +142,6 @@ class GeckoChildProcessHost : public ChildProcessHost,
|
|||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
static void CacheNtDllThunk();
|
||||
|
||||
void AddHandleToShare(HANDLE aHandle) {
|
||||
mLaunchOptions->handles_to_inherit.push_back(aHandle);
|
||||
|
@ -291,9 +290,6 @@ class GeckoChildProcessHost : public ChildProcessHost,
|
|||
static uint32_t sNextUniqueID;
|
||||
static StaticAutoPtr<LinkedList<GeckoChildProcessHost>>
|
||||
sGeckoChildProcessHosts;
|
||||
#ifdef XP_WIN
|
||||
static StaticAutoPtr<Buffer<IMAGE_THUNK_DATA>> sCachedNtDllThunk;
|
||||
#endif
|
||||
static StaticMutex sMutex;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,23 +13,22 @@
|
|||
namespace mozilla {
|
||||
namespace mscom {
|
||||
|
||||
ActivationContext::ActivationContext(WORD aResourceId)
|
||||
: ActivationContext(reinterpret_cast<HMODULE>(GetContainingModuleHandle()),
|
||||
aResourceId) {}
|
||||
ActivationContext::ActivationContext(ActCtxResource aResource)
|
||||
: ActivationContext(aResource.mModule, aResource.mId) {}
|
||||
|
||||
ActivationContext::ActivationContext(HMODULE aLoadFromModule, WORD aResourceId)
|
||||
: mActCtx(INVALID_HANDLE_VALUE) {
|
||||
ACTCTX actCtx = {sizeof(actCtx)};
|
||||
ACTCTXW actCtx = {sizeof(actCtx)};
|
||||
actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
|
||||
actCtx.lpResourceName = MAKEINTRESOURCE(aResourceId);
|
||||
actCtx.lpResourceName = MAKEINTRESOURCEW(aResourceId);
|
||||
actCtx.hModule = aLoadFromModule;
|
||||
|
||||
Init(actCtx);
|
||||
}
|
||||
|
||||
void ActivationContext::Init(ACTCTX& aActCtx) {
|
||||
void ActivationContext::Init(ACTCTXW& aActCtx) {
|
||||
MOZ_ASSERT(mActCtx == INVALID_HANDLE_VALUE);
|
||||
mActCtx = ::CreateActCtx(&aActCtx);
|
||||
mActCtx = ::CreateActCtxW(&aActCtx);
|
||||
MOZ_ASSERT(mActCtx != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/mscom/ActCtxResource.h"
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
# include "mozilla/ResultVariant.h"
|
||||
|
@ -29,7 +30,7 @@ class ActivationContext final {
|
|||
|
||||
ActivationContext() : mActCtx(INVALID_HANDLE_VALUE) {}
|
||||
|
||||
explicit ActivationContext(WORD aResourceId);
|
||||
explicit ActivationContext(ActCtxResource aResource);
|
||||
explicit ActivationContext(HMODULE aLoadFromModule,
|
||||
WORD aResourceId = kDllManifestDefaultResourceId);
|
||||
|
||||
|
@ -49,7 +50,7 @@ class ActivationContext final {
|
|||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
private:
|
||||
void Init(ACTCTX& aActCtx);
|
||||
void Init(ACTCTXW& aActCtx);
|
||||
void AddRef();
|
||||
void Release();
|
||||
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
#include "mozilla/mscom/ProcessRuntime.h"
|
||||
|
||||
#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
|
||||
# include "mozilla/a11y/Compatibility.h"
|
||||
#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
|
||||
#if defined(ACCESSIBILITY) && \
|
||||
(defined(MOZILLA_INTERNAL_API) || defined(MOZ_HAS_MOZGLUE))
|
||||
# include "mozilla/mscom/ActCtxResource.h"
|
||||
#endif // defined(ACCESSIBILITY) && (defined(MOZILLA_INTERNAL_API) ||
|
||||
// defined(MOZ_HAS_MOZGLUE))
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DynamicallyLinkedFunctionPtr.h"
|
||||
#include "mozilla/mscom/ProcessRuntimeShared.h"
|
||||
|
@ -49,13 +51,22 @@ ProcessRuntime::ProcessRuntime(const GeckoProcessType aProcessType)
|
|||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
ProcessRuntime::ProcessRuntime(const ProcessCategory aProcessCategory)
|
||||
: mInitResult(CO_E_NOTINITIALIZED),
|
||||
mProcessCategory(aProcessCategory)
|
||||
#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
|
||||
,
|
||||
mActCtxRgn(a11y::Compatibility::GetActCtxResourceId())
|
||||
#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
|
||||
{
|
||||
: mInitResult(CO_E_NOTINITIALIZED), mProcessCategory(aProcessCategory) {
|
||||
#if defined(ACCESSIBILITY)
|
||||
# if defined(MOZILLA_INTERNAL_API)
|
||||
// If we're inside XUL, and we're the parent process, then we trust that
|
||||
// this has already been initialized for us prior to XUL being loaded.
|
||||
if (aProcessCategory != ProcessCategory::GeckoBrowserParent) {
|
||||
mActCtxRgn.emplace(ActCtxResource::GetAccessibilityResource());
|
||||
}
|
||||
# elif defined(MOZ_HAS_MOZGLUE)
|
||||
// If we're here, then we're in mozglue and initializing this for the parent
|
||||
// process.
|
||||
MOZ_ASSERT(aProcessCategory == ProcessCategory::GeckoBrowserParent);
|
||||
mActCtxRgn.emplace(ActCtxResource::GetAccessibilityResource());
|
||||
# endif
|
||||
#endif // defined(ACCESSIBILITY)
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
MOZ_DIAGNOSTIC_ASSERT(!sInstance);
|
||||
sInstance = this;
|
||||
|
@ -120,11 +131,29 @@ ProcessRuntime::ProcessRuntime(const ProcessCategory aProcessCategory)
|
|||
|
||||
mAptRegion.Init(GetDesiredApartmentType(mProcessCategory));
|
||||
|
||||
// We must be the outermost COM initialization on this thread. The COM runtime
|
||||
// cannot be configured once we start manipulating objects
|
||||
MOZ_ASSERT(mAptRegion.IsValidOutermost());
|
||||
// It can happen that we are not the outermost COM initialization on this
|
||||
// thread. In fact it should regularly be the case that the outermost
|
||||
// initialization occurs from outside of XUL, before we show the skeleton UI,
|
||||
// at which point we still need to run some things here from within XUL.
|
||||
if (!mAptRegion.IsValidOutermost()) {
|
||||
mInitResult = mAptRegion.GetHResult();
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
MOZ_ASSERT(mProcessCategory == ProcessCategory::GeckoBrowserParent);
|
||||
if (mProcessCategory != ProcessCategory::GeckoBrowserParent) {
|
||||
// This is unexpected unless we're GeckoBrowserParent
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessInitLock lock;
|
||||
|
||||
// Is another instance of ProcessRuntime responsible for the outer
|
||||
// initialization?
|
||||
const bool prevInit = lock.IsInitialized();
|
||||
MOZ_ASSERT(prevInit);
|
||||
if (prevInit) {
|
||||
PostInit();
|
||||
}
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
#define mozilla_mscom_ProcessRuntime_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
|
||||
#if defined(ACCESSIBILITY)
|
||||
# include "mozilla/mscom/ActivationContext.h"
|
||||
#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
|
||||
# include "mozilla/Maybe.h"
|
||||
#endif // defined(ACCESSIBILITY)
|
||||
#include "mozilla/mscom/ApartmentRegion.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
|
@ -76,9 +77,11 @@ class MOZ_NON_TEMPORARY_CLASS ProcessRuntime final {
|
|||
private:
|
||||
HRESULT mInitResult;
|
||||
const ProcessCategory mProcessCategory;
|
||||
#if defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
|
||||
ActivationContextRegion mActCtxRgn;
|
||||
#endif // defined(ACCESSIBILITY) && defined(MOZILLA_INTERNAL_API)
|
||||
#if defined(ACCESSIBILITY) && \
|
||||
(defined(MOZILLA_INTERNAL_API) || defined(MOZ_HAS_MOZGLUE))
|
||||
Maybe<ActivationContextRegion> mActCtxRgn;
|
||||
#endif // defined(ACCESSIBILITY) && (defined(MOZILLA_INTERNAL_API) ||
|
||||
// defined(MOZ_HAS_MOZGLUE))
|
||||
ApartmentRegion mAptRegion;
|
||||
|
||||
private:
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include <guiddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct IStream;
|
||||
struct IUnknown;
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
/* 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 (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCTSTR>(&GetContainingModuleHandle),
|
||||
&thisModule)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return thisModule;
|
||||
}
|
||||
|
||||
ActCtxResource ActCtxResource::GetAccessibilityResource() {
|
||||
ActCtxResource result = {};
|
||||
result.mModule = GetContainingModuleHandle();
|
||||
#if defined(HAVE_64BIT_BUILD)
|
||||
// The manifest for 64-bit Windows is embedded with resource ID 64.
|
||||
result.mId = 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()) {
|
||||
result.mId = 64;
|
||||
} else {
|
||||
result.mId = 32;
|
||||
}
|
||||
#endif // defined(HAVE_64BIT_BUILD)
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,29 @@
|
|||
/* 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;
|
||||
|
||||
/**
|
||||
* @return ActCtxResource of a11y manifest resource to be passed to
|
||||
* mscom::ActivationContext
|
||||
*/
|
||||
static MFBT_API ActCtxResource GetAccessibilityResource();
|
||||
};
|
||||
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -7,9 +7,11 @@
|
|||
FINAL_LIBRARY = "mozglue"
|
||||
|
||||
EXPORTS.mozilla.mscom += [
|
||||
"ActCtxResource.h",
|
||||
"ProcessRuntimeShared.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"ActCtxResource.cpp",
|
||||
"ProcessRuntimeShared.cpp",
|
||||
]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity type="win32" name="Mozilla.Firefox.xul" version="1.0.0.0" />
|
||||
<file name="xul.dll" />
|
||||
<assemblyIdentity type="win32" name="Mozilla.Firefox.mozglue" version="1.0.0.0" />
|
||||
<file name="mozglue.dll" />
|
||||
<comInterfaceExternalProxyStub
|
||||
iid="{618736E0-3C3D-11CF-810C-00AA00389B71}"
|
||||
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity type="win32" name="Mozilla.Firefox.xul" version="1.0.0.0" />
|
||||
<file name="xul.dll" />
|
||||
<assemblyIdentity type="win32" name="Mozilla.Firefox.mozglue" version="1.0.0.0" />
|
||||
<file name="mozglue.dll" />
|
||||
<comInterfaceExternalProxyStub
|
||||
iid="{618736E0-3C3D-11CF-810C-00AA00389B71}"
|
||||
proxyStubClsid32="{03022430-ABC4-11D0-BDE2-00AA001A1953}"
|
|
@ -99,6 +99,18 @@ USE_LIBS += [
|
|||
"mfbt",
|
||||
]
|
||||
|
||||
if CONFIG["OS_ARCH"] == "WINNT":
|
||||
RCINCLUDE = "/mozglue/mozglue.rc"
|
||||
|
||||
if not CONFIG["HAVE_64BIT_BUILD"]:
|
||||
EXPORTS += [
|
||||
"IAccessible32.manifest",
|
||||
]
|
||||
|
||||
EXPORTS += [
|
||||
"IAccessible64.manifest",
|
||||
]
|
||||
|
||||
LIBRARY_DEFINES["IMPL_MFBT"] = True
|
||||
LIBRARY_DEFINES["MOZ_HAS_MOZGLUE"] = True
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* -*- 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 "CacheNtDllThunk.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Span.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static StaticAutoPtr<Buffer<IMAGE_THUNK_DATA>> sCachedNtDllThunk;
|
||||
|
||||
// This static method initializes sCachedNtDllThunk. Because it's called in
|
||||
// XREMain::XRE_main, which happens long before WindowsProcessLauncher's ctor
|
||||
// accesses sCachedNtDllThunk, there is no race on sCachedNtDllThunk, thus
|
||||
// no mutex is needed.
|
||||
static void CacheNtDllThunk() {
|
||||
if (sCachedNtDllThunk) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
nt::PEHeaders ourExeImage(::GetModuleHandleW(nullptr));
|
||||
if (!ourExeImage) {
|
||||
break;
|
||||
}
|
||||
|
||||
nt::PEHeaders ntdllImage(::GetModuleHandleW(L"ntdll.dll"));
|
||||
if (!ntdllImage) {
|
||||
break;
|
||||
}
|
||||
|
||||
Maybe<Range<const uint8_t>> ntdllBoundaries = ntdllImage.GetBounds();
|
||||
if (!ntdllBoundaries) {
|
||||
break;
|
||||
}
|
||||
|
||||
Maybe<Span<IMAGE_THUNK_DATA>> maybeNtDllThunks =
|
||||
ourExeImage.GetIATThunksForModule("ntdll.dll", ntdllBoundaries.ptr());
|
||||
if (maybeNtDllThunks.isNothing()) {
|
||||
break;
|
||||
}
|
||||
|
||||
sCachedNtDllThunk = new Buffer<IMAGE_THUNK_DATA>(maybeNtDllThunks.value());
|
||||
return;
|
||||
} while (false);
|
||||
|
||||
// Failed to cache IAT. Initializing the variable with nullptr.
|
||||
sCachedNtDllThunk = new Buffer<IMAGE_THUNK_DATA>();
|
||||
}
|
||||
|
||||
static Buffer<IMAGE_THUNK_DATA>* GetCachedNtDllThunk() {
|
||||
return sCachedNtDllThunk;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,21 @@
|
|||
/* -*- 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_CacheNtDllThunk_h
|
||||
#define mozilla_CacheNtDllThunk_h
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/Buffer.h"
|
||||
#include "mozilla/NativeNt.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
MFBT_API void CacheNtDllThunk();
|
||||
MFBT_API Buffer<IMAGE_THUNK_DATA>* GetCachedNtDllThunk();
|
||||
|
||||
}; // namespace mozilla
|
||||
|
||||
#endif // mozilla_CacheNtDllThunk_h
|
|
@ -18,6 +18,11 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"]:
|
|||
"WindowsFallbackLoaderAPI.cpp",
|
||||
]
|
||||
|
||||
if not CONFIG["JS_STANDALONE"]:
|
||||
UNIFIED_SOURCES += [
|
||||
"CacheNtDllThunk.cpp",
|
||||
]
|
||||
|
||||
OS_LIBS += [
|
||||
"crypt32",
|
||||
"ntdll",
|
||||
|
@ -32,6 +37,7 @@ DELAYLOAD_DLLS += [
|
|||
|
||||
EXPORTS.mozilla += [
|
||||
"Authenticode.h",
|
||||
"CacheNtDllThunk.h",
|
||||
"LoaderAPIInterfaces.h",
|
||||
"ModuleLoadInfo.h",
|
||||
"WindowsDllBlocklist.h",
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* 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 "GetKnownFolderPath.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
UniquePtr<wchar_t, LoadedCoTaskMemFreeDeleter> GetKnownFolderPath(
|
||||
REFKNOWNFOLDERID folderId) {
|
||||
static decltype(SHGetKnownFolderPath)* shGetKnownFolderPath = nullptr;
|
||||
if (!shGetKnownFolderPath) {
|
||||
// We could go out of our way to `FreeLibrary` on this, decrementing its
|
||||
// ref count and potentially unloading it. However doing so would be either
|
||||
// effectively a no-op, or counterproductive. Just let it get cleaned up
|
||||
// when the process is terminated, because we're going to load it anyway
|
||||
// elsewhere.
|
||||
HMODULE shell32Dll = ::LoadLibraryW(L"shell32");
|
||||
if (!shell32Dll) {
|
||||
return nullptr;
|
||||
}
|
||||
shGetKnownFolderPath = reinterpret_cast<decltype(shGetKnownFolderPath)>(
|
||||
::GetProcAddress(shell32Dll, "SHGetKnownFolderPath"));
|
||||
if (!shGetKnownFolderPath) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
PWSTR path = nullptr;
|
||||
shGetKnownFolderPath(folderId, 0, nullptr, &path);
|
||||
return UniquePtr<wchar_t, LoadedCoTaskMemFreeDeleter>(path);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,45 @@
|
|||
/* 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_GetKnownFolderPath_h
|
||||
#define mozilla_GetKnownFolderPath_h
|
||||
|
||||
#include <windows.h>
|
||||
#include <objbase.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "mozilla/glue/Debug.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct LoadedCoTaskMemFreeDeleter {
|
||||
void operator()(void* ptr) {
|
||||
static decltype(CoTaskMemFree)* coTaskMemFree = nullptr;
|
||||
if (!coTaskMemFree) {
|
||||
// Just let this get cleaned up when the process is terminated, because
|
||||
// we're going to load it anyway elsewhere.
|
||||
HMODULE ole32Dll = ::LoadLibraryW(L"ole32");
|
||||
if (!ole32Dll) {
|
||||
printf_stderr(
|
||||
"Could not load ole32 - will not free with CoTaskMemFree");
|
||||
return;
|
||||
}
|
||||
coTaskMemFree = reinterpret_cast<decltype(coTaskMemFree)>(
|
||||
::GetProcAddress(ole32Dll, "CoTaskMemFree"));
|
||||
if (!coTaskMemFree) {
|
||||
printf_stderr("Could not find CoTaskMemFree");
|
||||
return;
|
||||
}
|
||||
}
|
||||
coTaskMemFree(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
UniquePtr<wchar_t, LoadedCoTaskMemFreeDeleter> GetKnownFolderPath(
|
||||
REFKNOWNFOLDERID folderId);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -17,12 +17,15 @@
|
|||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/BaseProfilerMarkers.h"
|
||||
#include "mozilla/CacheNtDllThunk.h"
|
||||
#include "mozilla/FStream.h"
|
||||
#include "mozilla/GetKnownFolderPath.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/HelperMacros.h"
|
||||
#include "mozilla/glue/Debug.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/mscom/ProcessRuntime.h"
|
||||
#include "mozilla/ResultVariant.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -30,6 +33,7 @@
|
|||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/WindowsDpiAwareness.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "mozilla/WindowsProcessMitigations.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -104,6 +108,7 @@ static LPWSTR const gIDCWait = MAKEINTRESOURCEW(32514);
|
|||
static HANDLE sPreXULSKeletonUIAnimationThread;
|
||||
static HANDLE sPreXULSKeletonUILockFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
static mozilla::mscom::ProcessRuntime* sProcessRuntime;
|
||||
static uint32_t* sPixelBuffer = nullptr;
|
||||
static Vector<ColorRect>* sAnimatedRects = nullptr;
|
||||
static int sTotalChromeHeight = 0;
|
||||
|
@ -189,29 +194,6 @@ static const wchar_t* sThemeRegSuffix = L"|Theme";
|
|||
static const wchar_t* sFlagsRegSuffix = L"|Flags";
|
||||
static const wchar_t* sProgressSuffix = L"|Progress";
|
||||
|
||||
struct LoadedCoTaskMemFreeDeleter {
|
||||
void operator()(void* ptr) {
|
||||
static decltype(CoTaskMemFree)* coTaskMemFree = nullptr;
|
||||
if (!coTaskMemFree) {
|
||||
// Just let this get cleaned up when the process is terminated, because
|
||||
// we're going to load it anyway elsewhere.
|
||||
HMODULE ole32Dll = ::LoadLibraryW(L"ole32");
|
||||
if (!ole32Dll) {
|
||||
printf_stderr(
|
||||
"Could not load ole32 - will not free with CoTaskMemFree");
|
||||
return;
|
||||
}
|
||||
coTaskMemFree = reinterpret_cast<decltype(coTaskMemFree)>(
|
||||
::GetProcAddress(ole32Dll, "CoTaskMemFree"));
|
||||
if (!coTaskMemFree) {
|
||||
printf_stderr("Could not find CoTaskMemFree");
|
||||
return;
|
||||
}
|
||||
}
|
||||
coTaskMemFree(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
std::wstring GetRegValueName(const wchar_t* prefix, const wchar_t* suffix) {
|
||||
std::wstring result(prefix);
|
||||
result.append(suffix);
|
||||
|
@ -255,30 +237,6 @@ static bool PreXULSkeletonUIDisallowed() {
|
|||
*sErrorReason == PreXULSkeletonUIError::EnvVars);
|
||||
}
|
||||
|
||||
static UniquePtr<wchar_t, LoadedCoTaskMemFreeDeleter> GetKnownFolderPath(
|
||||
REFKNOWNFOLDERID folderId) {
|
||||
static decltype(SHGetKnownFolderPath)* shGetKnownFolderPath = nullptr;
|
||||
if (!shGetKnownFolderPath) {
|
||||
// We could go out of our way to `FreeLibrary` on this, decrementing its
|
||||
// ref count and potentially unloading it. However doing so would be either
|
||||
// effectively a no-op, or counterproductive. Just let it get cleaned up
|
||||
// when the process is terminated, because we're going to load it anyway
|
||||
// elsewhere.
|
||||
HMODULE shell32Dll = ::LoadLibraryW(L"shell32");
|
||||
if (!shell32Dll) {
|
||||
return nullptr;
|
||||
}
|
||||
shGetKnownFolderPath = reinterpret_cast<decltype(shGetKnownFolderPath)>(
|
||||
::GetProcAddress(shell32Dll, "SHGetKnownFolderPath"));
|
||||
if (!shGetKnownFolderPath) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
PWSTR path = nullptr;
|
||||
shGetKnownFolderPath(folderId, 0, nullptr, &path);
|
||||
return UniquePtr<wchar_t, LoadedCoTaskMemFreeDeleter>(path);
|
||||
}
|
||||
|
||||
// Note: this is specifically *not* a robust, multi-locale lowercasing
|
||||
// operation. It is not intended to be such. It is simply intended to match the
|
||||
// way in which we look for other instances of firefox to remote into.
|
||||
|
@ -1307,6 +1265,12 @@ DWORD WINAPI AnimateSkeletonUI(void* aUnused) {
|
|||
|
||||
LRESULT WINAPI PreXULSkeletonUIProc(HWND hWnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
// Exposing a generic oleacc proxy for the skeleton isn't useful and may cause
|
||||
// screen readers to report spurious information when the skeleton appears.
|
||||
if (msg == WM_GETOBJECT && sPreXULSkeletonUIWindow) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// NOTE: this block was copied from WinUtils.cpp, and needs to be kept in
|
||||
// sync.
|
||||
if (msg == WM_NCCREATE && sEnableNonClientDpiScaling) {
|
||||
|
@ -1841,6 +1805,31 @@ static Result<Ok, PreXULSkeletonUIError> WriteRegBool(
|
|||
|
||||
static Result<Ok, PreXULSkeletonUIError> CreateAndStorePreXULSkeletonUIImpl(
|
||||
HINSTANCE hInstance, int argc, char** argv) {
|
||||
// Initializing COM below may load modules via SetWindowHookEx, some of
|
||||
// which may modify the executable's IAT for ntdll.dll. If that happens,
|
||||
// this browser process fails to launch sandbox processes because we cannot
|
||||
// copy a modified IAT into a remote process (See SandboxBroker::LaunchApp).
|
||||
// To prevent that, we cache the intact IAT before COM initialization.
|
||||
// If EAF+ is enabled, CacheNtDllThunk() causes a crash, but EAF+ will
|
||||
// also prevent an injected module from parsing the PE headers and modifying
|
||||
// the IAT. Therefore, we can skip CacheNtDllThunk().
|
||||
if (!mozilla::IsEafPlusEnabled()) {
|
||||
CacheNtDllThunk();
|
||||
}
|
||||
|
||||
// NOTE: it's important that we initialize sProcessRuntime before showing a
|
||||
// window. Historically we ran into issues where showing the window would
|
||||
// cause an accessibility win event to fire, which could cause in-process
|
||||
// system or third party components to initialize COM and prevent us from
|
||||
// initializing it with important settings we need.
|
||||
|
||||
// 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.
|
||||
sProcessRuntime = new mscom::ProcessRuntime(
|
||||
mscom::ProcessRuntime::ProcessCategory::GeckoBrowserParent);
|
||||
|
||||
const TimeStamp skeletonStart = TimeStamp::NowUnfuzzed();
|
||||
|
||||
if (!IsWin10OrLater()) {
|
||||
|
@ -2052,6 +2041,11 @@ void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance, int argc,
|
|||
}
|
||||
}
|
||||
|
||||
void CleanupProcessRuntime() {
|
||||
delete sProcessRuntime;
|
||||
sProcessRuntime = nullptr;
|
||||
}
|
||||
|
||||
bool WasPreXULSkeletonUIMaximized() { return sMaximized; }
|
||||
|
||||
bool GetPreXULSkeletonUIWasShown() {
|
||||
|
|
|
@ -166,6 +166,7 @@ enum class PreXULSkeletonUIProgress : uint32_t {
|
|||
|
||||
MFBT_API void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance, int argc,
|
||||
char** argv);
|
||||
MFBT_API void CleanupProcessRuntime();
|
||||
MFBT_API bool GetPreXULSkeletonUIWasShown();
|
||||
MFBT_API HWND ConsumePreXULSkeletonUIHandle();
|
||||
MFBT_API Maybe<PreXULSkeletonUIError> GetPreXULSkeletonUIErrorReason();
|
||||
|
|
|
@ -29,6 +29,7 @@ EXPORTS.mozilla.glue += [
|
|||
|
||||
if CONFIG["OS_ARCH"] == "WINNT":
|
||||
EXPORTS.mozilla += [
|
||||
"GetKnownFolderPath.h",
|
||||
"PreXULSkeletonUI.h",
|
||||
"StackWalk_windows.h",
|
||||
"StackWalkThread.h",
|
||||
|
@ -68,14 +69,26 @@ if CONFIG["OS_ARCH"] == "WINNT":
|
|||
"WindowsUnicode.h",
|
||||
]
|
||||
SOURCES += [
|
||||
"PreXULSkeletonUI.cpp",
|
||||
"GetKnownFolderPath.cpp",
|
||||
"TimeStamp_windows.cpp",
|
||||
"WindowsDpiInitialization.cpp",
|
||||
"WindowsMapRemoteView.cpp",
|
||||
"WindowsProcessMitigations.cpp",
|
||||
"WindowsUnicode.cpp",
|
||||
]
|
||||
OS_LIBS += ["dbghelp"]
|
||||
|
||||
OS_LIBS += [
|
||||
"dbghelp",
|
||||
"oleaut32",
|
||||
"ole32",
|
||||
]
|
||||
|
||||
if CONFIG["ACCESSIBILITY"]:
|
||||
SOURCES += [
|
||||
"/ipc/mscom/ActivationContext.cpp",
|
||||
"/ipc/mscom/ProcessRuntime.cpp",
|
||||
"PreXULSkeletonUI.cpp",
|
||||
]
|
||||
elif CONFIG["HAVE_CLOCK_MONOTONIC"]:
|
||||
SOURCES += [
|
||||
"TimeStamp_posix.cpp",
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#include "mozilla-config.h"
|
||||
#ifdef ACCESSIBILITY
|
||||
64 24 IAccessible64.manifest
|
||||
#ifndef HAVE_64BIT_BUILD
|
||||
32 24 IAccessible32.manifest
|
||||
#endif
|
||||
#endif
|
|
@ -407,6 +407,8 @@ class ChildProcess final {
|
|||
|
||||
template <typename MMPolicy>
|
||||
TestResult BasicTest(const MMPolicy& aMMPolicy) {
|
||||
const bool isAppHelpLoaded = ::GetModuleHandleW(L"apphelp.dll");
|
||||
|
||||
// Use ntdll.dll because it does not have any forwarder RVA.
|
||||
HMODULE ntdllImageBase = ::GetModuleHandleW(L"ntdll.dll");
|
||||
auto ntdllExports = PEExportSection<MMPolicy>::Get(ntdllImageBase, aMMPolicy);
|
||||
|
@ -417,6 +419,13 @@ TestResult BasicTest(const MMPolicy& aMMPolicy) {
|
|||
for (DWORD i = 0; i < exportDir->NumberOfNames; ++i) {
|
||||
const auto name =
|
||||
ntdllExports.template RVAToPtr<const char*>(tableOfNames[i]);
|
||||
|
||||
if (isAppHelpLoaded && strcmp(name, "NtdllDefWindowProc_W") == 0) {
|
||||
// In this case, GetProcAddress will return
|
||||
// apphelp!DWM8AND16BitHook_DefWindowProcW.
|
||||
continue;
|
||||
}
|
||||
|
||||
auto funcEntry = ntdllExports.FindExportAddressTableEntry(name);
|
||||
if (ntdllExports.template RVAToPtr<const void*>(*funcEntry) !=
|
||||
::GetProcAddress(ntdllImageBase, name)) {
|
||||
|
|
|
@ -6,8 +6,4 @@
|
|||
#include "widget.rc"
|
||||
#ifdef ACCESSIBILITY
|
||||
1 typelib IGeckoCustom.tlb
|
||||
64 24 IAccessible64.manifest
|
||||
#ifndef HAVE_64BIT_BUILD
|
||||
32 24 IAccessible32.manifest
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5402,22 +5402,9 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
|
|||
mozilla::IOInterposerInit ioInterposerGuard;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// Initializing COM below may load modules via SetWindowHookEx, some of
|
||||
// which may modify the executable's IAT for ntdll.dll. If that happens,
|
||||
// this browser process fails to launch sandbox processes because we cannot
|
||||
// copy a modified IAT into a remote process (See SandboxBroker::LaunchApp).
|
||||
// To prevent that, we cache the intact IAT before COM initialization.
|
||||
// If EAF+ is enabled, CacheNtDllThunk() causes a crash, but EAF+ will
|
||||
// also prevent an injected module from parsing the PE headers and modifying
|
||||
// the IAT. Therefore, we can skip CacheNtDllThunk().
|
||||
if (!mozilla::IsEafPlusEnabled()) {
|
||||
mozilla::ipc::GeckoChildProcessHost::CacheNtDllThunk();
|
||||
}
|
||||
|
||||
// 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.
|
||||
// We should have already done this when we created the skeleton UI. However,
|
||||
// there is code in here which needs xul in order to work, like EnsureMTA. It
|
||||
// should be setup that running it again is safe.
|
||||
mozilla::mscom::ProcessRuntime msCOMRuntime;
|
||||
#endif
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче