Bug 1796811 - Update in-tree zlib to version 1.2.13. r=aosmond
[gecko.git] / ipc / mscom / DispatchForwarder.cpp
blobe55b1316d0c9c58470bcba04bf2827aece8b7fda
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/. */
7 #include "mozilla/mscom/DispatchForwarder.h"
9 #include <oleauto.h>
11 #include <utility>
13 #include "mozilla/mscom/MainThreadInvoker.h"
15 namespace mozilla {
16 namespace mscom {
18 /* static */
19 HRESULT DispatchForwarder::Create(IInterceptor* aInterceptor,
20 STAUniquePtr<IDispatch>& aTarget,
21 IUnknown** aOutput) {
22 MOZ_ASSERT(aInterceptor && aOutput);
23 if (!aOutput) {
24 return E_INVALIDARG;
26 *aOutput = nullptr;
27 if (!aInterceptor) {
28 return E_INVALIDARG;
30 DispatchForwarder* forwarder = new DispatchForwarder(aInterceptor, aTarget);
31 HRESULT hr = forwarder->QueryInterface(IID_IDispatch, (void**)aOutput);
32 forwarder->Release();
33 return hr;
36 DispatchForwarder::DispatchForwarder(IInterceptor* aInterceptor,
37 STAUniquePtr<IDispatch>& aTarget)
38 : mRefCnt(1), mInterceptor(aInterceptor), mTarget(std::move(aTarget)) {}
40 DispatchForwarder::~DispatchForwarder() {}
42 HRESULT
43 DispatchForwarder::QueryInterface(REFIID riid, void** ppv) {
44 if (!ppv) {
45 return E_INVALIDARG;
48 // Since this class implements a tearoff, any interfaces that are not
49 // IDispatch must be routed to the original object's QueryInterface.
50 // This is especially important for IUnknown since COM uses that interface
51 // to determine object identity.
52 if (riid != IID_IDispatch) {
53 return mInterceptor->QueryInterface(riid, ppv);
56 IUnknown* punk = static_cast<IDispatch*>(this);
57 *ppv = punk;
58 if (!punk) {
59 return E_NOINTERFACE;
62 punk->AddRef();
63 return S_OK;
66 ULONG
67 DispatchForwarder::AddRef() {
68 return (ULONG)InterlockedIncrement((LONG*)&mRefCnt);
71 ULONG
72 DispatchForwarder::Release() {
73 ULONG newRefCnt = (ULONG)InterlockedDecrement((LONG*)&mRefCnt);
74 if (newRefCnt == 0) {
75 delete this;
77 return newRefCnt;
80 HRESULT
81 DispatchForwarder::GetTypeInfoCount(UINT* pctinfo) {
82 if (!pctinfo) {
83 return E_INVALIDARG;
85 *pctinfo = 1;
86 return S_OK;
89 HRESULT
90 DispatchForwarder::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) {
91 // ITypeInfo as implemented by COM is apartment-neutral, so we don't need
92 // to wrap it (yay!)
93 if (mTypeInfo) {
94 RefPtr<ITypeInfo> copy(mTypeInfo);
95 copy.forget(ppTInfo);
96 return S_OK;
98 HRESULT hr = E_UNEXPECTED;
99 auto fn = [&]() -> void { hr = mTarget->GetTypeInfo(iTInfo, lcid, ppTInfo); };
100 MainThreadInvoker invoker;
101 if (!invoker.Invoke(
102 NS_NewRunnableFunction("DispatchForwarder::GetTypeInfo", fn))) {
103 return E_UNEXPECTED;
105 if (FAILED(hr)) {
106 return hr;
108 mTypeInfo = *ppTInfo;
109 return hr;
112 HRESULT
113 DispatchForwarder::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
114 LCID lcid, DISPID* rgDispId) {
115 HRESULT hr = E_UNEXPECTED;
116 auto fn = [&]() -> void {
117 hr = mTarget->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId);
119 MainThreadInvoker invoker;
120 if (!invoker.Invoke(
121 NS_NewRunnableFunction("DispatchForwarder::GetIDsOfNames", fn))) {
122 return E_UNEXPECTED;
124 return hr;
127 HRESULT
128 DispatchForwarder::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
129 WORD wFlags, DISPPARAMS* pDispParams,
130 VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
131 UINT* puArgErr) {
132 HRESULT hr;
133 if (!mInterface) {
134 if (!mTypeInfo) {
135 return E_UNEXPECTED;
137 TYPEATTR* typeAttr = nullptr;
138 hr = mTypeInfo->GetTypeAttr(&typeAttr);
139 if (FAILED(hr)) {
140 return hr;
142 hr = mInterceptor->QueryInterface(typeAttr->guid,
143 (void**)getter_AddRefs(mInterface));
144 mTypeInfo->ReleaseTypeAttr(typeAttr);
145 if (FAILED(hr)) {
146 return hr;
149 // We don't invoke IDispatch on the target, but rather on the interceptor!
150 hr = ::DispInvoke(mInterface.get(), mTypeInfo, dispIdMember, wFlags,
151 pDispParams, pVarResult, pExcepInfo, puArgErr);
152 return hr;
155 } // namespace mscom
156 } // namespace mozilla