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/FastMarshaler.h"
8 
9 #include "mozilla/mscom/Utils.h"
10 
11 #include <objbase.h>
12 
13 namespace mozilla {
14 namespace mscom {
15 
16 HRESULT
Create(IUnknown * aOuter,IUnknown ** aOutMarshalerUnk)17 FastMarshaler::Create(IUnknown* aOuter, IUnknown** aOutMarshalerUnk) {
18   MOZ_ASSERT(XRE_IsContentProcess());
19 
20   if (!aOuter || !aOutMarshalerUnk) {
21     return E_INVALIDARG;
22   }
23 
24   *aOutMarshalerUnk = nullptr;
25 
26   HRESULT hr;
27   RefPtr<FastMarshaler> fm(new FastMarshaler(aOuter, &hr));
28   if (FAILED(hr)) {
29     return hr;
30   }
31 
32   return fm->InternalQueryInterface(IID_IUnknown, (void**)aOutMarshalerUnk);
33 }
34 
FastMarshaler(IUnknown * aOuter,HRESULT * aResult)35 FastMarshaler::FastMarshaler(IUnknown* aOuter, HRESULT* aResult)
36     : mRefCnt(0), mOuter(aOuter), mStdMarshalWeak(nullptr) {
37   *aResult =
38       ::CoGetStdMarshalEx(aOuter, SMEXF_SERVER, getter_AddRefs(mStdMarshalUnk));
39   if (FAILED(*aResult)) {
40     return;
41   }
42 
43   *aResult =
44       mStdMarshalUnk->QueryInterface(IID_IMarshal, (void**)&mStdMarshalWeak);
45   if (FAILED(*aResult)) {
46     return;
47   }
48 
49   // mStdMarshalWeak is weak
50   mStdMarshalWeak->Release();
51 }
52 
53 HRESULT
InternalQueryInterface(REFIID riid,void ** ppv)54 FastMarshaler::InternalQueryInterface(REFIID riid, void** ppv) {
55   if (!ppv) {
56     return E_INVALIDARG;
57   }
58 
59   if (riid == IID_IUnknown) {
60     RefPtr<IUnknown> punk(static_cast<IUnknown*>(&mInternalUnknown));
61     punk.forget(ppv);
62     return S_OK;
63   }
64 
65   if (riid == IID_IMarshal) {
66     RefPtr<IMarshal> ptr(this);
67     ptr.forget(ppv);
68     return S_OK;
69   }
70 
71   return mStdMarshalUnk->QueryInterface(riid, ppv);
72 }
73 
74 ULONG
InternalAddRef()75 FastMarshaler::InternalAddRef() { return ++mRefCnt; }
76 
77 ULONG
InternalRelease()78 FastMarshaler::InternalRelease() {
79   ULONG result = --mRefCnt;
80   if (!result) {
81     delete this;
82   }
83 
84   return result;
85 }
86 
87 DWORD
GetMarshalFlags(DWORD aDestContext,DWORD aMshlFlags)88 FastMarshaler::GetMarshalFlags(DWORD aDestContext, DWORD aMshlFlags) {
89   // Only worry about local contexts.
90   if (aDestContext != MSHCTX_LOCAL) {
91     return aMshlFlags;
92   }
93 
94   return aMshlFlags | MSHLFLAGS_NOPING;
95 }
96 
97 HRESULT
GetUnmarshalClass(REFIID riid,void * pv,DWORD dwDestContext,void * pvDestContext,DWORD mshlflags,CLSID * pCid)98 FastMarshaler::GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext,
99                                  void* pvDestContext, DWORD mshlflags,
100                                  CLSID* pCid) {
101   if (!mStdMarshalWeak) {
102     return E_POINTER;
103   }
104 
105   return mStdMarshalWeak->GetUnmarshalClass(
106       riid, pv, dwDestContext, pvDestContext,
107       GetMarshalFlags(dwDestContext, mshlflags), pCid);
108 }
109 
110 HRESULT
GetMarshalSizeMax(REFIID riid,void * pv,DWORD dwDestContext,void * pvDestContext,DWORD mshlflags,DWORD * pSize)111 FastMarshaler::GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext,
112                                  void* pvDestContext, DWORD mshlflags,
113                                  DWORD* pSize) {
114   if (!mStdMarshalWeak) {
115     return E_POINTER;
116   }
117 
118   return mStdMarshalWeak->GetMarshalSizeMax(
119       riid, pv, dwDestContext, pvDestContext,
120       GetMarshalFlags(dwDestContext, mshlflags), pSize);
121 }
122 
123 HRESULT
MarshalInterface(IStream * pStm,REFIID riid,void * pv,DWORD dwDestContext,void * pvDestContext,DWORD mshlflags)124 FastMarshaler::MarshalInterface(IStream* pStm, REFIID riid, void* pv,
125                                 DWORD dwDestContext, void* pvDestContext,
126                                 DWORD mshlflags) {
127   if (!mStdMarshalWeak) {
128     return E_POINTER;
129   }
130 
131   return mStdMarshalWeak->MarshalInterface(
132       pStm, riid, pv, dwDestContext, pvDestContext,
133       GetMarshalFlags(dwDestContext, mshlflags));
134 }
135 
136 HRESULT
UnmarshalInterface(IStream * pStm,REFIID riid,void ** ppv)137 FastMarshaler::UnmarshalInterface(IStream* pStm, REFIID riid, void** ppv) {
138   if (!mStdMarshalWeak) {
139     return E_POINTER;
140   }
141 
142   return mStdMarshalWeak->UnmarshalInterface(pStm, riid, ppv);
143 }
144 
145 HRESULT
ReleaseMarshalData(IStream * pStm)146 FastMarshaler::ReleaseMarshalData(IStream* pStm) {
147   if (!mStdMarshalWeak) {
148     return E_POINTER;
149   }
150 
151   return mStdMarshalWeak->ReleaseMarshalData(pStm);
152 }
153 
154 HRESULT
DisconnectObject(DWORD dwReserved)155 FastMarshaler::DisconnectObject(DWORD dwReserved) {
156   if (!mStdMarshalWeak) {
157     return E_POINTER;
158   }
159 
160   return mStdMarshalWeak->DisconnectObject(dwReserved);
161 }
162 
163 }  // namespace mscom
164 }  // namespace mozilla
165