xref: /AOO41X/main/dtrans/source/win32/dtobj/APNDataObject.cxx (revision 48123e16153c92857455f9e7a0d17cc19307983f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dtrans.hxx"
26 
27 //------------------------------------------------------------------------
28 // includes
29 //------------------------------------------------------------------------
30 #include "APNDataObject.hxx"
31 #include <osl/diagnose.h>
32 
33 #include <systools/win32/comtools.hxx>
34 #ifdef __MINGW32__
35 #define __uuidof(I) IID_##I
36 #endif
37 
38 //------------------------------------------------------------------------
39 // defines
40 //------------------------------------------------------------------------
41 
42 #define FREE_HGLOB_ON_RELEASE   TRUE
43 #define KEEP_HGLOB_ON_RELEASE   FALSE
44 
45 //------------------------------------------------------------------------
46 // ctor
47 //------------------------------------------------------------------------
48 
CAPNDataObject(IDataObjectPtr rIDataObject)49 CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject ) :
50     m_rIDataObjectOrg( rIDataObject ),
51     m_hGlobal( NULL ),
52     m_nRefCnt( 0 )
53 {
54 
55     OSL_ENSURE( m_rIDataObjectOrg.get( ), "constructing CAPNDataObject with empty data object" );
56 
57     // we marshal the IDataObject interface pointer here so
58     // that it can be unmarshaled multiple times when this
59     // class will be used from another apartment
60     IStreamPtr pStm;
61     HRESULT hr = CreateStreamOnHGlobal( 0, KEEP_HGLOB_ON_RELEASE, &pStm );
62 
63     OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" );
64 
65     if ( SUCCEEDED( hr ) )
66     {
67         HRESULT hr_marshal = CoMarshalInterface(
68             pStm.get(),
69             __uuidof(IDataObject),
70             static_cast<LPUNKNOWN>(m_rIDataObjectOrg.get()),
71             MSHCTX_LOCAL,
72             NULL,
73             MSHLFLAGS_TABLEWEAK );
74 
75         OSL_ENSURE( CO_E_NOTINITIALIZED != hr_marshal, "COM is not initialized" );
76 
77         // marshalling may fail if COM is not initialized
78         // for the calling thread which is a program time
79         // error or because of stream errors which are runtime
80         // errors for instance E_OUTOFMEMORY etc.
81 
82         hr = GetHGlobalFromStream(pStm.get(), &m_hGlobal );
83 
84         OSL_ENSURE( E_INVALIDARG != hr, "invalid stream passed to GetHGlobalFromStream" );
85 
86         // if the marshalling failed we free the
87         // global memory again and set m_hGlobal
88         // to a defined value
89         if (FAILED(hr_marshal))
90         {
91             OSL_ENSURE(sal_False, "marshalling failed");
92 
93             #if OSL_DEBUG_LEVEL > 0
94             HGLOBAL hGlobal =
95             #endif
96                 GlobalFree(m_hGlobal);
97             OSL_ENSURE(NULL == hGlobal, "GlobalFree failed");
98             m_hGlobal = NULL;
99         }
100     }
101 }
102 
~CAPNDataObject()103 CAPNDataObject::~CAPNDataObject( )
104 {
105     if (m_hGlobal)
106     {
107         IStreamPtr pStm;
108         HRESULT  hr = CreateStreamOnHGlobal(m_hGlobal, FREE_HGLOB_ON_RELEASE, &pStm);
109 
110         OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" );
111 
112         if (SUCCEEDED(hr))
113         {
114             hr = CoReleaseMarshalData(pStm.get());
115             OSL_ENSURE(SUCCEEDED(hr), "CoReleaseMarshalData failed");
116         }
117     }
118 }
119 
120 //------------------------------------------------------------------------
121 // IUnknown->QueryInterface
122 //------------------------------------------------------------------------
123 
QueryInterface(REFIID iid,LPVOID * ppvObject)124 STDMETHODIMP CAPNDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject )
125 {
126     OSL_ASSERT( NULL != ppvObject );
127 
128     if ( NULL == ppvObject )
129         return E_INVALIDARG;
130 
131     HRESULT hr = E_NOINTERFACE;
132     *ppvObject = NULL;
133 
134     if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) )
135     {
136         *ppvObject = static_cast< IUnknown* >( this );
137         ( (LPUNKNOWN)*ppvObject )->AddRef( );
138         hr = S_OK;
139     }
140 
141     return hr;
142 }
143 
144 //------------------------------------------------------------------------
145 // IUnknown->AddRef
146 //------------------------------------------------------------------------
147 
STDMETHODIMP_(ULONG)148 STDMETHODIMP_(ULONG) CAPNDataObject::AddRef( )
149 {
150     return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
151 }
152 
153 //------------------------------------------------------------------------
154 // IUnknown->Release
155 //------------------------------------------------------------------------
156 
STDMETHODIMP_(ULONG)157 STDMETHODIMP_(ULONG) CAPNDataObject::Release( )
158 {
159     // we need a helper variable because it's not allowed to access
160     // a member variable after an object is destroyed
161     ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) );
162 
163     if ( 0 == nRefCnt )
164         delete this;
165 
166     return nRefCnt;
167 }
168 
169 //------------------------------------------------------------------------
170 // IDataObject->GetData
171 //------------------------------------------------------------------------
172 
GetData(LPFORMATETC pFormatetc,LPSTGMEDIUM pmedium)173 STDMETHODIMP CAPNDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
174 {
175     HRESULT hr = m_rIDataObjectOrg->GetData( pFormatetc, pmedium );
176 
177     if (RPC_E_WRONG_THREAD == hr)
178     {
179         IDataObjectPtr pIDOTmp;
180         hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);
181 
182         if (SUCCEEDED(hr))
183             hr = pIDOTmp->GetData(pFormatetc, pmedium);
184     }
185     return hr;
186 }
187 
188 //------------------------------------------------------------------------
189 // IDataObject->EnumFormatEtc
190 //------------------------------------------------------------------------
191 
EnumFormatEtc(DWORD dwDirection,IEnumFORMATETC ** ppenumFormatetc)192 STDMETHODIMP CAPNDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
193 {
194     HRESULT hr = m_rIDataObjectOrg->EnumFormatEtc(dwDirection, ppenumFormatetc);
195 
196     if (RPC_E_WRONG_THREAD == hr)
197     {
198         IDataObjectPtr pIDOTmp;
199         hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);
200 
201         if (SUCCEEDED(hr))
202             hr = pIDOTmp->EnumFormatEtc(dwDirection, ppenumFormatetc);
203     }
204     return hr;
205 }
206 
207 //------------------------------------------------------------------------
208 // IDataObject->QueryGetData
209 //------------------------------------------------------------------------
210 
QueryGetData(LPFORMATETC pFormatetc)211 STDMETHODIMP CAPNDataObject::QueryGetData( LPFORMATETC pFormatetc )
212 {
213     HRESULT hr = m_rIDataObjectOrg->QueryGetData( pFormatetc );
214 
215     if (RPC_E_WRONG_THREAD == hr)
216     {
217         IDataObjectPtr pIDOTmp;
218         hr = MarshalIDataObjectIntoCurrentApartment( &pIDOTmp );
219 
220         if (SUCCEEDED(hr))
221             hr = pIDOTmp->QueryGetData(pFormatetc);
222     }
223     return hr;
224 }
225 
226 //------------------------------------------------------------------------
227 // IDataObject->GetDataHere
228 //------------------------------------------------------------------------
229 
GetDataHere(LPFORMATETC pFormatetc,LPSTGMEDIUM pmedium)230 STDMETHODIMP CAPNDataObject::GetDataHere( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
231 {
232     HRESULT hr = m_rIDataObjectOrg->GetDataHere(pFormatetc, pmedium);
233 
234     if (RPC_E_WRONG_THREAD == hr)
235     {
236         IDataObjectPtr pIDOTmp;
237         hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);
238 
239         if (SUCCEEDED(hr))
240             hr = pIDOTmp->GetDataHere(pFormatetc, pmedium);
241     }
242     return hr;
243 }
244 
245 //------------------------------------------------------------------------
246 // IDataObject->GetCanonicalFormatEtc
247 //------------------------------------------------------------------------
248 
GetCanonicalFormatEtc(LPFORMATETC pFormatectIn,LPFORMATETC pFormatetcOut)249 STDMETHODIMP CAPNDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatectIn, LPFORMATETC pFormatetcOut)
250 {
251     HRESULT hr = m_rIDataObjectOrg->GetCanonicalFormatEtc( pFormatectIn, pFormatetcOut );
252 
253     if (RPC_E_WRONG_THREAD == hr)
254     {
255         IDataObjectPtr pIDOTmp;
256         hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);
257 
258         if (SUCCEEDED(hr))
259             hr = pIDOTmp->GetCanonicalFormatEtc(pFormatectIn, pFormatetcOut);
260     }
261     return hr;
262 }
263 
264 //------------------------------------------------------------------------
265 // IDataObject->SetData
266 //------------------------------------------------------------------------
267 
SetData(LPFORMATETC pFormatetc,LPSTGMEDIUM pmedium,BOOL fRelease)268 STDMETHODIMP CAPNDataObject::SetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium, BOOL fRelease )
269 {
270     HRESULT hr = m_rIDataObjectOrg->SetData( pFormatetc, pmedium, fRelease );
271 
272     if (RPC_E_WRONG_THREAD == hr)
273     {
274         IDataObjectPtr pIDOTmp;
275         hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);
276 
277         if (SUCCEEDED(hr))
278             hr = pIDOTmp->SetData(pFormatetc, pmedium, fRelease);
279     }
280     return hr;
281 }
282 
283 //------------------------------------------------------------------------
284 // IDataObject->DAdvise
285 //------------------------------------------------------------------------
286 
DAdvise(LPFORMATETC pFormatetc,DWORD advf,LPADVISESINK pAdvSink,DWORD * pdwConnection)287 STDMETHODIMP CAPNDataObject::DAdvise( LPFORMATETC pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection )
288 {
289     HRESULT hr = m_rIDataObjectOrg->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection);
290 
291     if (RPC_E_WRONG_THREAD == hr)
292     {
293         IDataObjectPtr pIDOTmp;
294         hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);
295 
296         if (SUCCEEDED(hr))
297             hr = pIDOTmp->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection);
298     }
299     return hr;
300 }
301 
302 //------------------------------------------------------------------------
303 // IDataObject->DUnadvise
304 //------------------------------------------------------------------------
305 
DUnadvise(DWORD dwConnection)306 STDMETHODIMP CAPNDataObject::DUnadvise( DWORD dwConnection )
307 {
308     HRESULT hr = m_rIDataObjectOrg->DUnadvise( dwConnection );
309 
310     if (RPC_E_WRONG_THREAD == hr)
311     {
312         IDataObjectPtr pIDOTmp;
313         hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);
314 
315         if (SUCCEEDED(hr))
316             hr = pIDOTmp->DUnadvise(dwConnection);
317     }
318     return hr;
319 }
320 
321 //------------------------------------------------------------------------
322 // IDataObject->EnumDAdvise
323 //------------------------------------------------------------------------
324 
EnumDAdvise(LPENUMSTATDATA * ppenumAdvise)325 STDMETHODIMP CAPNDataObject::EnumDAdvise( LPENUMSTATDATA * ppenumAdvise )
326 {
327     HRESULT hr = m_rIDataObjectOrg->EnumDAdvise(ppenumAdvise);
328 
329     if (RPC_E_WRONG_THREAD == hr)
330     {
331         IDataObjectPtr pIDOTmp;
332         hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp);
333 
334         if (SUCCEEDED(hr))
335             hr = pIDOTmp->EnumDAdvise(ppenumAdvise);
336     }
337     return hr;
338 }
339 
340 //------------------------------------------------------------------------
341 // for our convenience
342 //------------------------------------------------------------------------
343 
operator IDataObject*()344 CAPNDataObject::operator IDataObject*( )
345 {
346     return static_cast< IDataObject* >( this );
347 }
348 
349 //------------------------------------------------------------------------
350 // helper function
351 //------------------------------------------------------------------------
352 
MarshalIDataObjectIntoCurrentApartment(IDataObject ** ppIDataObj)353 HRESULT CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject** ppIDataObj )
354 {
355     OSL_ASSERT(NULL != ppIDataObj);
356 
357     *ppIDataObj = NULL;
358     HRESULT hr = E_FAIL;
359 
360     if (m_hGlobal)
361     {
362         IStreamPtr pStm;
363         hr = CreateStreamOnHGlobal(m_hGlobal, KEEP_HGLOB_ON_RELEASE, &pStm);
364 
365         OSL_ENSURE(E_INVALIDARG != hr, "CreateStreamOnHGlobal with invalid args called");
366 
367         if (SUCCEEDED(hr))
368         {
369             hr = CoUnmarshalInterface(pStm.get(), __uuidof(IDataObject), (void**)ppIDataObj);
370             OSL_ENSURE(CO_E_NOTINITIALIZED != hr, "COM is not initialized");
371         }
372     }
373     return hr;
374 }
375