diff options
Diffstat (limited to '')
-rw-r--r-- | ipc/mscom/ActivationContext.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/ipc/mscom/ActivationContext.cpp b/ipc/mscom/ActivationContext.cpp new file mode 100644 index 0000000000..c5ee9d1419 --- /dev/null +++ b/ipc/mscom/ActivationContext.cpp @@ -0,0 +1,223 @@ +/* -*- 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/ActivationContext.h" + +#include "mozilla/Assertions.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/mscom/Utils.h" + +namespace mozilla { +namespace mscom { + +ActivationContext::ActivationContext(ActCtxResource aResource) + : ActivationContext(aResource.mModule, aResource.mId) {} + +ActivationContext::ActivationContext(HMODULE aLoadFromModule, WORD aResourceId) + : mActCtx(INVALID_HANDLE_VALUE) { + ACTCTXW actCtx = {sizeof(actCtx)}; + actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; + actCtx.lpResourceName = MAKEINTRESOURCEW(aResourceId); + actCtx.hModule = aLoadFromModule; + + Init(actCtx); +} + +void ActivationContext::Init(ACTCTXW& aActCtx) { + MOZ_ASSERT(mActCtx == INVALID_HANDLE_VALUE); + mActCtx = ::CreateActCtxW(&aActCtx); + MOZ_ASSERT(mActCtx != INVALID_HANDLE_VALUE); +} + +void ActivationContext::AddRef() { + if (mActCtx == INVALID_HANDLE_VALUE) { + return; + } + ::AddRefActCtx(mActCtx); +} + +ActivationContext::ActivationContext(ActivationContext&& aOther) + : mActCtx(aOther.mActCtx) { + aOther.mActCtx = INVALID_HANDLE_VALUE; +} + +ActivationContext& ActivationContext::operator=(ActivationContext&& aOther) { + Release(); + + mActCtx = aOther.mActCtx; + aOther.mActCtx = INVALID_HANDLE_VALUE; + return *this; +} + +ActivationContext::ActivationContext(const ActivationContext& aOther) + : mActCtx(aOther.mActCtx) { + AddRef(); +} + +ActivationContext& ActivationContext::operator=( + const ActivationContext& aOther) { + Release(); + mActCtx = aOther.mActCtx; + AddRef(); + return *this; +} + +void ActivationContext::Release() { + if (mActCtx == INVALID_HANDLE_VALUE) { + return; + } + ::ReleaseActCtx(mActCtx); + mActCtx = INVALID_HANDLE_VALUE; +} + +ActivationContext::~ActivationContext() { Release(); } + +#if defined(MOZILLA_INTERNAL_API) + +/* static */ Result<uintptr_t, HRESULT> ActivationContext::GetCurrent() { + HANDLE actCtx; + if (!::GetCurrentActCtx(&actCtx)) { + return Result<uintptr_t, HRESULT>(HRESULT_FROM_WIN32(::GetLastError())); + } + + return reinterpret_cast<uintptr_t>(actCtx); +} + +/* static */ +HRESULT ActivationContext::GetCurrentManifestPath(nsAString& aOutManifestPath) { + aOutManifestPath.Truncate(); + + SIZE_T bytesNeeded; + BOOL ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr, + nullptr, ActivationContextDetailedInformation, + nullptr, 0, &bytesNeeded); + if (!ok) { + DWORD err = ::GetLastError(); + if (err != ERROR_INSUFFICIENT_BUFFER) { + return HRESULT_FROM_WIN32(err); + } + } + + auto ctxBuf = MakeUnique<BYTE[]>(bytesNeeded); + + ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr, nullptr, + ActivationContextDetailedInformation, ctxBuf.get(), + bytesNeeded, nullptr); + if (!ok) { + return HRESULT_FROM_WIN32(::GetLastError()); + } + + auto ctxInfo = + reinterpret_cast<ACTIVATION_CONTEXT_DETAILED_INFORMATION*>(ctxBuf.get()); + + // assemblyIndex is 1-based, and we want the last index, so we can just copy + // ctxInfo->ulAssemblyCount directly. + DWORD assemblyIndex = ctxInfo->ulAssemblyCount; + ok = ::QueryActCtxW( + QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr, &assemblyIndex, + AssemblyDetailedInformationInActivationContext, nullptr, 0, &bytesNeeded); + if (!ok) { + DWORD err = ::GetLastError(); + if (err != ERROR_INSUFFICIENT_BUFFER) { + return HRESULT_FROM_WIN32(err); + } + } + + auto assemblyBuf = MakeUnique<BYTE[]>(bytesNeeded); + + ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr, + &assemblyIndex, + AssemblyDetailedInformationInActivationContext, + assemblyBuf.get(), bytesNeeded, &bytesNeeded); + if (!ok) { + return HRESULT_FROM_WIN32(::GetLastError()); + } + + auto assemblyInfo = + reinterpret_cast<ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION*>( + assemblyBuf.get()); + aOutManifestPath = nsDependentString( + assemblyInfo->lpAssemblyManifestPath, + (assemblyInfo->ulManifestPathLength + 1) / sizeof(wchar_t)); + + return S_OK; +} + +#endif // defined(MOZILLA_INTERNAL_API) + +ActivationContextRegion::ActivationContextRegion() : mActCookie(0) {} + +ActivationContextRegion::ActivationContextRegion( + const ActivationContext& aActCtx) + : mActCtx(aActCtx), mActCookie(0) { + Activate(); +} + +ActivationContextRegion& ActivationContextRegion::operator=( + const ActivationContext& aActCtx) { + Deactivate(); + mActCtx = aActCtx; + Activate(); + return *this; +} + +ActivationContextRegion::ActivationContextRegion(ActivationContext&& aActCtx) + : mActCtx(std::move(aActCtx)), mActCookie(0) { + Activate(); +} + +ActivationContextRegion& ActivationContextRegion::operator=( + ActivationContext&& aActCtx) { + Deactivate(); + mActCtx = std::move(aActCtx); + Activate(); + return *this; +} + +ActivationContextRegion::ActivationContextRegion(ActivationContextRegion&& aRgn) + : mActCtx(std::move(aRgn.mActCtx)), mActCookie(aRgn.mActCookie) { + aRgn.mActCookie = 0; +} + +ActivationContextRegion& ActivationContextRegion::operator=( + ActivationContextRegion&& aRgn) { + Deactivate(); + mActCtx = std::move(aRgn.mActCtx); + mActCookie = aRgn.mActCookie; + aRgn.mActCookie = 0; + return *this; +} + +void ActivationContextRegion::Activate() { + if (mActCtx.mActCtx == INVALID_HANDLE_VALUE) { + return; + } + +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED + BOOL activated = +#endif + ::ActivateActCtx(mActCtx.mActCtx, &mActCookie); + MOZ_DIAGNOSTIC_ASSERT(activated); +} + +bool ActivationContextRegion::Deactivate() { + if (!mActCookie) { + return true; + } + + BOOL deactivated = ::DeactivateActCtx(0, mActCookie); + MOZ_DIAGNOSTIC_ASSERT(deactivated); + if (deactivated) { + mActCookie = 0; + } + + return !!deactivated; +} + +ActivationContextRegion::~ActivationContextRegion() { Deactivate(); } + +} // namespace mscom +} // namespace mozilla |