1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "mozilla/mscom/ActivationContext.h"
8
9 #include "mozilla/Assertions.h"
10 #include "mozilla/DebugOnly.h"
11 #include "mozilla/mscom/Utils.h"
12
13 namespace mozilla {
14 namespace mscom {
15
ActivationContext(WORD aResourceId)16 ActivationContext::ActivationContext(WORD aResourceId)
17 : ActivationContext(reinterpret_cast<HMODULE>(GetContainingModuleHandle()),
18 aResourceId) {}
19
ActivationContext(HMODULE aLoadFromModule,WORD aResourceId)20 ActivationContext::ActivationContext(HMODULE aLoadFromModule, WORD aResourceId)
21 : mActCtx(INVALID_HANDLE_VALUE) {
22 ACTCTX actCtx = {sizeof(actCtx)};
23 actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
24 actCtx.lpResourceName = MAKEINTRESOURCE(aResourceId);
25 actCtx.hModule = aLoadFromModule;
26
27 Init(actCtx);
28 }
29
Init(ACTCTX & aActCtx)30 void ActivationContext::Init(ACTCTX& aActCtx) {
31 MOZ_ASSERT(mActCtx == INVALID_HANDLE_VALUE);
32 mActCtx = ::CreateActCtx(&aActCtx);
33 MOZ_ASSERT(mActCtx != INVALID_HANDLE_VALUE);
34 }
35
AddRef()36 void ActivationContext::AddRef() {
37 if (mActCtx == INVALID_HANDLE_VALUE) {
38 return;
39 }
40 ::AddRefActCtx(mActCtx);
41 }
42
ActivationContext(ActivationContext && aOther)43 ActivationContext::ActivationContext(ActivationContext&& aOther)
44 : mActCtx(aOther.mActCtx) {
45 aOther.mActCtx = INVALID_HANDLE_VALUE;
46 }
47
operator =(ActivationContext && aOther)48 ActivationContext& ActivationContext::operator=(ActivationContext&& aOther) {
49 Release();
50
51 mActCtx = aOther.mActCtx;
52 aOther.mActCtx = INVALID_HANDLE_VALUE;
53 return *this;
54 }
55
ActivationContext(const ActivationContext & aOther)56 ActivationContext::ActivationContext(const ActivationContext& aOther)
57 : mActCtx(aOther.mActCtx) {
58 AddRef();
59 }
60
operator =(const ActivationContext & aOther)61 ActivationContext& ActivationContext::operator=(
62 const ActivationContext& aOther) {
63 Release();
64 mActCtx = aOther.mActCtx;
65 AddRef();
66 return *this;
67 }
68
Release()69 void ActivationContext::Release() {
70 if (mActCtx == INVALID_HANDLE_VALUE) {
71 return;
72 }
73 ::ReleaseActCtx(mActCtx);
74 mActCtx = INVALID_HANDLE_VALUE;
75 }
76
~ActivationContext()77 ActivationContext::~ActivationContext() { Release(); }
78
79 #if defined(MOZILLA_INTERNAL_API)
80
GetCurrent()81 /* static */ Result<uintptr_t, HRESULT> ActivationContext::GetCurrent() {
82 HANDLE actCtx;
83 if (!::GetCurrentActCtx(&actCtx)) {
84 return Result<uintptr_t, HRESULT>(HRESULT_FROM_WIN32(::GetLastError()));
85 }
86
87 return reinterpret_cast<uintptr_t>(actCtx);
88 }
89
90 /* static */
GetCurrentManifestPath(nsAString & aOutManifestPath)91 HRESULT ActivationContext::GetCurrentManifestPath(nsAString& aOutManifestPath) {
92 aOutManifestPath.Truncate();
93
94 SIZE_T bytesNeeded;
95 BOOL ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr,
96 nullptr, ActivationContextDetailedInformation,
97 nullptr, 0, &bytesNeeded);
98 if (!ok) {
99 DWORD err = ::GetLastError();
100 if (err != ERROR_INSUFFICIENT_BUFFER) {
101 return HRESULT_FROM_WIN32(err);
102 }
103 }
104
105 auto ctxBuf = MakeUnique<BYTE[]>(bytesNeeded);
106
107 ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr, nullptr,
108 ActivationContextDetailedInformation, ctxBuf.get(),
109 bytesNeeded, nullptr);
110 if (!ok) {
111 return HRESULT_FROM_WIN32(::GetLastError());
112 }
113
114 auto ctxInfo =
115 reinterpret_cast<ACTIVATION_CONTEXT_DETAILED_INFORMATION*>(ctxBuf.get());
116
117 // assemblyIndex is 1-based, and we want the last index, so we can just copy
118 // ctxInfo->ulAssemblyCount directly.
119 DWORD assemblyIndex = ctxInfo->ulAssemblyCount;
120 ok = ::QueryActCtxW(
121 QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr, &assemblyIndex,
122 AssemblyDetailedInformationInActivationContext, nullptr, 0, &bytesNeeded);
123 if (!ok) {
124 DWORD err = ::GetLastError();
125 if (err != ERROR_INSUFFICIENT_BUFFER) {
126 return HRESULT_FROM_WIN32(err);
127 }
128 }
129
130 auto assemblyBuf = MakeUnique<BYTE[]>(bytesNeeded);
131
132 ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr,
133 &assemblyIndex,
134 AssemblyDetailedInformationInActivationContext,
135 assemblyBuf.get(), bytesNeeded, &bytesNeeded);
136 if (!ok) {
137 return HRESULT_FROM_WIN32(::GetLastError());
138 }
139
140 auto assemblyInfo =
141 reinterpret_cast<ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION*>(
142 assemblyBuf.get());
143 aOutManifestPath = nsDependentString(
144 assemblyInfo->lpAssemblyManifestPath,
145 (assemblyInfo->ulManifestPathLength + 1) / sizeof(wchar_t));
146
147 return S_OK;
148 }
149
150 #endif // defined(MOZILLA_INTERNAL_API)
151
ActivationContextRegion()152 ActivationContextRegion::ActivationContextRegion() : mActCookie(0) {}
153
ActivationContextRegion(const ActivationContext & aActCtx)154 ActivationContextRegion::ActivationContextRegion(
155 const ActivationContext& aActCtx)
156 : mActCtx(aActCtx), mActCookie(0) {
157 Activate();
158 }
159
operator =(const ActivationContext & aActCtx)160 ActivationContextRegion& ActivationContextRegion::operator=(
161 const ActivationContext& aActCtx) {
162 Deactivate();
163 mActCtx = aActCtx;
164 Activate();
165 return *this;
166 }
167
ActivationContextRegion(ActivationContext && aActCtx)168 ActivationContextRegion::ActivationContextRegion(ActivationContext&& aActCtx)
169 : mActCtx(std::move(aActCtx)), mActCookie(0) {
170 Activate();
171 }
172
operator =(ActivationContext && aActCtx)173 ActivationContextRegion& ActivationContextRegion::operator=(
174 ActivationContext&& aActCtx) {
175 Deactivate();
176 mActCtx = std::move(aActCtx);
177 Activate();
178 return *this;
179 }
180
ActivationContextRegion(ActivationContextRegion && aRgn)181 ActivationContextRegion::ActivationContextRegion(ActivationContextRegion&& aRgn)
182 : mActCtx(std::move(aRgn.mActCtx)), mActCookie(aRgn.mActCookie) {
183 aRgn.mActCookie = 0;
184 }
185
operator =(ActivationContextRegion && aRgn)186 ActivationContextRegion& ActivationContextRegion::operator=(
187 ActivationContextRegion&& aRgn) {
188 Deactivate();
189 mActCtx = std::move(aRgn.mActCtx);
190 mActCookie = aRgn.mActCookie;
191 aRgn.mActCookie = 0;
192 return *this;
193 }
194
Activate()195 void ActivationContextRegion::Activate() {
196 if (mActCtx.mActCtx == INVALID_HANDLE_VALUE) {
197 return;
198 }
199
200 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
201 BOOL activated =
202 #endif
203 ::ActivateActCtx(mActCtx.mActCtx, &mActCookie);
204 MOZ_DIAGNOSTIC_ASSERT(activated);
205 }
206
Deactivate()207 bool ActivationContextRegion::Deactivate() {
208 if (!mActCookie) {
209 return true;
210 }
211
212 BOOL deactivated = ::DeactivateActCtx(0, mActCookie);
213 MOZ_DIAGNOSTIC_ASSERT(deactivated);
214 if (deactivated) {
215 mActCookie = 0;
216 }
217
218 return !!deactivated;
219 }
220
~ActivationContextRegion()221 ActivationContextRegion::~ActivationContextRegion() { Deactivate(); }
222
223 } // namespace mscom
224 } // namespace mozilla
225