1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "APNDataObject.hxx"
21 #include <osl/diagnose.h>
23 #include <systools/win32/comtools.hxx>
25 #define FREE_HGLOB_ON_RELEASE TRUE
26 #define KEEP_HGLOB_ON_RELEASE FALSE
30 CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject
) :
31 m_rIDataObjectOrg( rIDataObject
),
36 OSL_ENSURE( m_rIDataObjectOrg
.get( ), "constructing CAPNDataObject with empty data object" );
38 // we marshal the IDataObject interface pointer here so
39 // that it can be unmarshalled multiple times when this
40 // class will be used from another apartment
42 HRESULT hr
= CreateStreamOnHGlobal( nullptr, KEEP_HGLOB_ON_RELEASE
, &pStm
);
44 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid args passed to CreateStreamOnHGlobal" );
46 if ( SUCCEEDED( hr
) )
48 HRESULT hr_marshal
= CoMarshalInterface(
50 __uuidof(IDataObject
),
51 static_cast<LPUNKNOWN
>(m_rIDataObjectOrg
.get()),
54 MSHLFLAGS_TABLEWEAK
);
56 OSL_ENSURE( CO_E_NOTINITIALIZED
!= hr_marshal
, "COM is not initialized" );
58 // marshalling may fail if COM is not initialized
59 // for the calling thread which is a program time
60 // error or because of stream errors which are runtime
61 // errors for instance E_OUTOFMEMORY etc.
63 hr
= GetHGlobalFromStream(pStm
.get(), &m_hGlobal
);
65 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid stream passed to GetHGlobalFromStream" );
67 // if the marshalling failed we free the
68 // global memory again and set m_hGlobal
70 if (FAILED(hr_marshal
))
72 OSL_FAIL("marshalling failed");
75 GlobalFree(m_hGlobal
);
76 OSL_ENSURE(nullptr == hGlobal
, "GlobalFree failed");
82 CAPNDataObject::~CAPNDataObject( )
87 HRESULT hr
= CreateStreamOnHGlobal(m_hGlobal
, FREE_HGLOB_ON_RELEASE
, &pStm
);
89 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid args passed to CreateStreamOnHGlobal" );
93 hr
= CoReleaseMarshalData(pStm
.get());
94 OSL_ENSURE(SUCCEEDED(hr
), "CoReleaseMarshalData failed");
99 // IUnknown->QueryInterface
101 STDMETHODIMP
CAPNDataObject::QueryInterface( REFIID iid
, void** ppvObject
)
103 OSL_ASSERT( nullptr != ppvObject
);
105 if ( nullptr == ppvObject
)
108 HRESULT hr
= E_NOINTERFACE
;
109 *ppvObject
= nullptr;
111 if ( ( __uuidof( IUnknown
) == iid
) || ( __uuidof( IDataObject
) == iid
) )
113 *ppvObject
= static_cast< IUnknown
* >( this );
114 static_cast<LPUNKNOWN
>(*ppvObject
)->AddRef( );
123 STDMETHODIMP_(ULONG
) CAPNDataObject::AddRef( )
125 return static_cast< ULONG
>( InterlockedIncrement( &m_nRefCnt
) );
130 STDMETHODIMP_(ULONG
) CAPNDataObject::Release( )
132 // we need a helper variable because it's not allowed to access
133 // a member variable after an object is destroyed
134 ULONG nRefCnt
= static_cast< ULONG
>( InterlockedDecrement( &m_nRefCnt
) );
142 // IDataObject->GetData
144 STDMETHODIMP
CAPNDataObject::GetData( FORMATETC
* pFormatetc
, STGMEDIUM
* pmedium
)
146 HRESULT hr
= m_rIDataObjectOrg
->GetData( pFormatetc
, pmedium
);
148 if (RPC_E_WRONG_THREAD
== hr
)
150 IDataObjectPtr pIDOTmp
;
151 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
154 hr
= pIDOTmp
->GetData(pFormatetc
, pmedium
);
159 // IDataObject->EnumFormatEtc
161 STDMETHODIMP
CAPNDataObject::EnumFormatEtc( DWORD dwDirection
, IEnumFORMATETC
** ppenumFormatetc
)
163 HRESULT hr
= m_rIDataObjectOrg
->EnumFormatEtc(dwDirection
, ppenumFormatetc
);
165 if (RPC_E_WRONG_THREAD
== hr
)
167 IDataObjectPtr pIDOTmp
;
168 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
171 hr
= pIDOTmp
->EnumFormatEtc(dwDirection
, ppenumFormatetc
);
176 // IDataObject->QueryGetData
178 STDMETHODIMP
CAPNDataObject::QueryGetData( FORMATETC
* pFormatetc
)
180 HRESULT hr
= m_rIDataObjectOrg
->QueryGetData( pFormatetc
);
182 if (RPC_E_WRONG_THREAD
== hr
)
184 IDataObjectPtr pIDOTmp
;
185 hr
= MarshalIDataObjectIntoCurrentApartment( &pIDOTmp
);
188 hr
= pIDOTmp
->QueryGetData(pFormatetc
);
193 // IDataObject->GetDataHere
195 STDMETHODIMP
CAPNDataObject::GetDataHere( FORMATETC
* pFormatetc
, STGMEDIUM
* pmedium
)
197 HRESULT hr
= m_rIDataObjectOrg
->GetDataHere(pFormatetc
, pmedium
);
199 if (RPC_E_WRONG_THREAD
== hr
)
201 IDataObjectPtr pIDOTmp
;
202 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
205 hr
= pIDOTmp
->GetDataHere(pFormatetc
, pmedium
);
210 // IDataObject->GetCanonicalFormatEtc
212 STDMETHODIMP
CAPNDataObject::GetCanonicalFormatEtc(FORMATETC
* pFormatectIn
, FORMATETC
* pFormatetcOut
)
214 HRESULT hr
= m_rIDataObjectOrg
->GetCanonicalFormatEtc( pFormatectIn
, pFormatetcOut
);
216 if (RPC_E_WRONG_THREAD
== hr
)
218 IDataObjectPtr pIDOTmp
;
219 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
222 hr
= pIDOTmp
->GetCanonicalFormatEtc(pFormatectIn
, pFormatetcOut
);
227 // IDataObject->SetData
229 STDMETHODIMP
CAPNDataObject::SetData( FORMATETC
* pFormatetc
, STGMEDIUM
* pmedium
, BOOL fRelease
)
231 HRESULT hr
= m_rIDataObjectOrg
->SetData( pFormatetc
, pmedium
, fRelease
);
233 if (RPC_E_WRONG_THREAD
== hr
)
235 IDataObjectPtr pIDOTmp
;
236 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
239 hr
= pIDOTmp
->SetData(pFormatetc
, pmedium
, fRelease
);
244 // IDataObject->DAdvise
246 STDMETHODIMP
CAPNDataObject::DAdvise( FORMATETC
* pFormatetc
, DWORD advf
, IAdviseSink
* pAdvSink
, DWORD
* pdwConnection
)
248 HRESULT hr
= m_rIDataObjectOrg
->DAdvise(pFormatetc
, advf
, pAdvSink
, pdwConnection
);
250 if (RPC_E_WRONG_THREAD
== hr
)
252 IDataObjectPtr pIDOTmp
;
253 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
256 hr
= pIDOTmp
->DAdvise(pFormatetc
, advf
, pAdvSink
, pdwConnection
);
261 // IDataObject->DUnadvise
263 STDMETHODIMP
CAPNDataObject::DUnadvise( DWORD dwConnection
)
265 HRESULT hr
= m_rIDataObjectOrg
->DUnadvise( dwConnection
);
267 if (RPC_E_WRONG_THREAD
== hr
)
269 IDataObjectPtr pIDOTmp
;
270 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
273 hr
= pIDOTmp
->DUnadvise(dwConnection
);
278 // IDataObject->EnumDAdvise
280 STDMETHODIMP
CAPNDataObject::EnumDAdvise( IEnumSTATDATA
** ppenumAdvise
)
282 HRESULT hr
= m_rIDataObjectOrg
->EnumDAdvise(ppenumAdvise
);
284 if (RPC_E_WRONG_THREAD
== hr
)
286 IDataObjectPtr pIDOTmp
;
287 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
290 hr
= pIDOTmp
->EnumDAdvise(ppenumAdvise
);
295 // for our convenience
297 CAPNDataObject::operator IDataObject
*( )
299 return static_cast< IDataObject
* >( this );
304 HRESULT
CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject
** ppIDataObj
)
306 OSL_ASSERT(nullptr != ppIDataObj
);
308 *ppIDataObj
= nullptr;
314 hr
= CreateStreamOnHGlobal(m_hGlobal
, KEEP_HGLOB_ON_RELEASE
, &pStm
);
316 OSL_ENSURE(E_INVALIDARG
!= hr
, "CreateStreamOnHGlobal with invalid args called");
320 hr
= CoUnmarshalInterface(pStm
.get(), __uuidof(IDataObject
), reinterpret_cast<void**>(ppIDataObj
));
321 OSL_ENSURE(CO_E_NOTINITIALIZED
!= hr
, "COM is not initialized");
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */