1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: APNDataObject.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dtrans.hxx"
34 //------------------------------------------------------------------------
36 //------------------------------------------------------------------------
37 #include "APNDataObject.hxx"
38 #include <osl/diagnose.h>
40 #include <systools/win32/comtools.hxx>
42 #define __uuidof(I) IID_##I
45 //------------------------------------------------------------------------
47 //------------------------------------------------------------------------
49 #define FREE_HGLOB_ON_RELEASE TRUE
50 #define KEEP_HGLOB_ON_RELEASE FALSE
52 //------------------------------------------------------------------------
54 //------------------------------------------------------------------------
56 CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject
) :
57 m_rIDataObjectOrg( rIDataObject
),
62 OSL_ENSURE( m_rIDataObjectOrg
.get( ), "constructing CAPNDataObject with empty data object" );
64 // we marshal the IDataObject interface pointer here so
65 // that it can be unmarshaled multiple times when this
66 // class will be used from another apartment
68 HRESULT hr
= CreateStreamOnHGlobal( 0, KEEP_HGLOB_ON_RELEASE
, &pStm
);
70 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid args passed to CreateStreamOnHGlobal" );
72 if ( SUCCEEDED( hr
) )
74 HRESULT hr_marshal
= CoMarshalInterface(
76 __uuidof(IDataObject
),
77 static_cast<LPUNKNOWN
>(m_rIDataObjectOrg
.get()),
80 MSHLFLAGS_TABLEWEAK
);
82 OSL_ENSURE( CO_E_NOTINITIALIZED
!= hr_marshal
, "COM is not initialized" );
84 // marshalling may fail if COM is not initialized
85 // for the calling thread which is a program time
86 // error or because of stream errors which are runtime
87 // errors for instance E_OUTOFMEMORY etc.
89 hr
= GetHGlobalFromStream(pStm
.get(), &m_hGlobal
);
91 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid stream passed to GetHGlobalFromStream" );
93 // if the marshalling failed we free the
94 // global memory again and set m_hGlobal
96 if (FAILED(hr_marshal
))
98 OSL_ENSURE(sal_False
, "marshalling failed");
100 #if OSL_DEBUG_LEVEL > 0
103 GlobalFree(m_hGlobal
);
104 OSL_ENSURE(NULL
== hGlobal
, "GlobalFree failed");
110 CAPNDataObject::~CAPNDataObject( )
115 HRESULT hr
= CreateStreamOnHGlobal(m_hGlobal
, FREE_HGLOB_ON_RELEASE
, &pStm
);
117 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid args passed to CreateStreamOnHGlobal" );
121 hr
= CoReleaseMarshalData(pStm
.get());
122 OSL_ENSURE(SUCCEEDED(hr
), "CoReleaseMarshalData failed");
127 //------------------------------------------------------------------------
128 // IUnknown->QueryInterface
129 //------------------------------------------------------------------------
131 STDMETHODIMP
CAPNDataObject::QueryInterface( REFIID iid
, LPVOID
* ppvObject
)
133 OSL_ASSERT( NULL
!= ppvObject
);
135 if ( NULL
== ppvObject
)
138 HRESULT hr
= E_NOINTERFACE
;
141 if ( ( __uuidof( IUnknown
) == iid
) || ( __uuidof( IDataObject
) == iid
) )
143 *ppvObject
= static_cast< IUnknown
* >( this );
144 ( (LPUNKNOWN
)*ppvObject
)->AddRef( );
151 //------------------------------------------------------------------------
153 //------------------------------------------------------------------------
155 STDMETHODIMP_(ULONG
) CAPNDataObject::AddRef( )
157 return static_cast< ULONG
>( InterlockedIncrement( &m_nRefCnt
) );
160 //------------------------------------------------------------------------
162 //------------------------------------------------------------------------
164 STDMETHODIMP_(ULONG
) CAPNDataObject::Release( )
166 // we need a helper variable because it's not allowed to access
167 // a member variable after an object is destroyed
168 ULONG nRefCnt
= static_cast< ULONG
>( InterlockedDecrement( &m_nRefCnt
) );
176 //------------------------------------------------------------------------
177 // IDataObject->GetData
178 //------------------------------------------------------------------------
180 STDMETHODIMP
CAPNDataObject::GetData( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
)
182 HRESULT hr
= m_rIDataObjectOrg
->GetData( pFormatetc
, pmedium
);
184 if (RPC_E_WRONG_THREAD
== hr
)
186 IDataObjectPtr pIDOTmp
;
187 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
190 hr
= pIDOTmp
->GetData(pFormatetc
, pmedium
);
195 //------------------------------------------------------------------------
196 // IDataObject->EnumFormatEtc
197 //------------------------------------------------------------------------
199 STDMETHODIMP
CAPNDataObject::EnumFormatEtc( DWORD dwDirection
, IEnumFORMATETC
** ppenumFormatetc
)
201 HRESULT hr
= m_rIDataObjectOrg
->EnumFormatEtc(dwDirection
, ppenumFormatetc
);
203 if (RPC_E_WRONG_THREAD
== hr
)
205 IDataObjectPtr pIDOTmp
;
206 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
209 hr
= pIDOTmp
->EnumFormatEtc(dwDirection
, ppenumFormatetc
);
214 //------------------------------------------------------------------------
215 // IDataObject->QueryGetData
216 //------------------------------------------------------------------------
218 STDMETHODIMP
CAPNDataObject::QueryGetData( LPFORMATETC pFormatetc
)
220 HRESULT hr
= m_rIDataObjectOrg
->QueryGetData( pFormatetc
);
222 if (RPC_E_WRONG_THREAD
== hr
)
224 IDataObjectPtr pIDOTmp
;
225 hr
= MarshalIDataObjectIntoCurrentApartment( &pIDOTmp
);
228 hr
= pIDOTmp
->QueryGetData(pFormatetc
);
233 //------------------------------------------------------------------------
234 // IDataObject->GetDataHere
235 //------------------------------------------------------------------------
237 STDMETHODIMP
CAPNDataObject::GetDataHere( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
)
239 HRESULT hr
= m_rIDataObjectOrg
->GetDataHere(pFormatetc
, pmedium
);
241 if (RPC_E_WRONG_THREAD
== hr
)
243 IDataObjectPtr pIDOTmp
;
244 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
247 hr
= pIDOTmp
->GetDataHere(pFormatetc
, pmedium
);
252 //------------------------------------------------------------------------
253 // IDataObject->GetCanonicalFormatEtc
254 //------------------------------------------------------------------------
256 STDMETHODIMP
CAPNDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatectIn
, LPFORMATETC pFormatetcOut
)
258 HRESULT hr
= m_rIDataObjectOrg
->GetCanonicalFormatEtc( pFormatectIn
, pFormatetcOut
);
260 if (RPC_E_WRONG_THREAD
== hr
)
262 IDataObjectPtr pIDOTmp
;
263 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
266 hr
= pIDOTmp
->GetCanonicalFormatEtc(pFormatectIn
, pFormatetcOut
);
271 //------------------------------------------------------------------------
272 // IDataObject->SetData
273 //------------------------------------------------------------------------
275 STDMETHODIMP
CAPNDataObject::SetData( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
, BOOL fRelease
)
277 HRESULT hr
= m_rIDataObjectOrg
->SetData( pFormatetc
, pmedium
, fRelease
);
279 if (RPC_E_WRONG_THREAD
== hr
)
281 IDataObjectPtr pIDOTmp
;
282 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
285 hr
= pIDOTmp
->SetData(pFormatetc
, pmedium
, fRelease
);
290 //------------------------------------------------------------------------
291 // IDataObject->DAdvise
292 //------------------------------------------------------------------------
294 STDMETHODIMP
CAPNDataObject::DAdvise( LPFORMATETC pFormatetc
, DWORD advf
, LPADVISESINK pAdvSink
, DWORD
* pdwConnection
)
296 HRESULT hr
= m_rIDataObjectOrg
->DAdvise(pFormatetc
, advf
, pAdvSink
, pdwConnection
);
298 if (RPC_E_WRONG_THREAD
== hr
)
300 IDataObjectPtr pIDOTmp
;
301 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
304 hr
= pIDOTmp
->DAdvise(pFormatetc
, advf
, pAdvSink
, pdwConnection
);
309 //------------------------------------------------------------------------
310 // IDataObject->DUnadvise
311 //------------------------------------------------------------------------
313 STDMETHODIMP
CAPNDataObject::DUnadvise( DWORD dwConnection
)
315 HRESULT hr
= m_rIDataObjectOrg
->DUnadvise( dwConnection
);
317 if (RPC_E_WRONG_THREAD
== hr
)
319 IDataObjectPtr pIDOTmp
;
320 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
323 hr
= pIDOTmp
->DUnadvise(dwConnection
);
328 //------------------------------------------------------------------------
329 // IDataObject->EnumDAdvise
330 //------------------------------------------------------------------------
332 STDMETHODIMP
CAPNDataObject::EnumDAdvise( LPENUMSTATDATA
* ppenumAdvise
)
334 HRESULT hr
= m_rIDataObjectOrg
->EnumDAdvise(ppenumAdvise
);
336 if (RPC_E_WRONG_THREAD
== hr
)
338 IDataObjectPtr pIDOTmp
;
339 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
342 hr
= pIDOTmp
->EnumDAdvise(ppenumAdvise
);
347 //------------------------------------------------------------------------
348 // for our convenience
349 //------------------------------------------------------------------------
351 CAPNDataObject::operator IDataObject
*( )
353 return static_cast< IDataObject
* >( this );
356 //------------------------------------------------------------------------
358 //------------------------------------------------------------------------
360 HRESULT
CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject
** ppIDataObj
)
362 OSL_ASSERT(NULL
!= ppIDataObj
);
370 hr
= CreateStreamOnHGlobal(m_hGlobal
, KEEP_HGLOB_ON_RELEASE
, &pStm
);
372 OSL_ENSURE(E_INVALIDARG
!= hr
, "CreateStreamOnHGlobal with invalid args called");
376 hr
= CoUnmarshalInterface(pStm
.get(), __uuidof(IDataObject
), (void**)ppIDataObj
);
377 OSL_ENSURE(CO_E_NOTINITIALIZED
!= hr
, "COM is not initialized");