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"
13 #include "mozilla/mscom/MainThreadInvoker.h"
19 HRESULT
DispatchForwarder::Create(IInterceptor
* aInterceptor
,
20 STAUniquePtr
<IDispatch
>& aTarget
,
22 MOZ_ASSERT(aInterceptor
&& aOutput
);
30 DispatchForwarder
* forwarder
= new DispatchForwarder(aInterceptor
, aTarget
);
31 HRESULT hr
= forwarder
->QueryInterface(IID_IDispatch
, (void**)aOutput
);
36 DispatchForwarder::DispatchForwarder(IInterceptor
* aInterceptor
,
37 STAUniquePtr
<IDispatch
>& aTarget
)
38 : mRefCnt(1), mInterceptor(aInterceptor
), mTarget(std::move(aTarget
)) {}
40 DispatchForwarder::~DispatchForwarder() {}
43 DispatchForwarder::QueryInterface(REFIID riid
, void** ppv
) {
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);
67 DispatchForwarder::AddRef() {
68 return (ULONG
)InterlockedIncrement((LONG
*)&mRefCnt
);
72 DispatchForwarder::Release() {
73 ULONG newRefCnt
= (ULONG
)InterlockedDecrement((LONG
*)&mRefCnt
);
81 DispatchForwarder::GetTypeInfoCount(UINT
* pctinfo
) {
90 DispatchForwarder::GetTypeInfo(UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
) {
91 // ITypeInfo as implemented by COM is apartment-neutral, so we don't need
94 RefPtr
<ITypeInfo
> copy(mTypeInfo
);
98 HRESULT hr
= E_UNEXPECTED
;
99 auto fn
= [&]() -> void { hr
= mTarget
->GetTypeInfo(iTInfo
, lcid
, ppTInfo
); };
100 MainThreadInvoker invoker
;
102 NS_NewRunnableFunction("DispatchForwarder::GetTypeInfo", fn
))) {
108 mTypeInfo
= *ppTInfo
;
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
;
121 NS_NewRunnableFunction("DispatchForwarder::GetIDsOfNames", fn
))) {
128 DispatchForwarder::Invoke(DISPID dispIdMember
, REFIID riid
, LCID lcid
,
129 WORD wFlags
, DISPPARAMS
* pDispParams
,
130 VARIANT
* pVarResult
, EXCEPINFO
* pExcepInfo
,
137 TYPEATTR
* typeAttr
= nullptr;
138 hr
= mTypeInfo
->GetTypeAttr(&typeAttr
);
142 hr
= mInterceptor
->QueryInterface(typeAttr
->guid
,
143 (void**)getter_AddRefs(mInterface
));
144 mTypeInfo
->ReleaseTypeAttr(typeAttr
);
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
);
156 } // namespace mozilla