Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / dtrans / source / win32 / dtobj / APNDataObject.cxx
blob53342f21f379de813d9c96b32b102ad288d67292
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
28 // ctor
30 CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject ) :
31 m_rIDataObjectOrg( rIDataObject ),
32 m_hGlobal( nullptr ),
33 m_nRefCnt( 0 )
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
41 IStreamPtr pStm;
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(
49 pStm.get(),
50 __uuidof(IDataObject),
51 static_cast<LPUNKNOWN>(m_rIDataObjectOrg.get()),
52 MSHCTX_LOCAL,
53 nullptr,
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
69 // to a defined value
70 if (FAILED(hr_marshal))
72 OSL_FAIL("marshalling failed");
74 HGLOBAL hGlobal =
75 GlobalFree(m_hGlobal);
76 OSL_ENSURE(nullptr == hGlobal, "GlobalFree failed");
77 m_hGlobal = nullptr;
82 CAPNDataObject::~CAPNDataObject( )
84 if (m_hGlobal)
86 IStreamPtr pStm;
87 HRESULT hr = CreateStreamOnHGlobal(m_hGlobal, FREE_HGLOB_ON_RELEASE, &pStm);
89 OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" );
91 if (SUCCEEDED(hr))
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 )
106 return E_INVALIDARG;
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( );
115 hr = S_OK;
118 return hr;
121 // IUnknown->AddRef
123 STDMETHODIMP_(ULONG) CAPNDataObject::AddRef( )
125 return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
128 // IUnknown->Release
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 ) );
136 if ( 0 == nRefCnt )
137 delete this;
139 return 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);
153 if (SUCCEEDED(hr))
154 hr = pIDOTmp->GetData(pFormatetc, pmedium);
156 return hr;
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);
170 if (SUCCEEDED(hr))
171 hr = pIDOTmp->EnumFormatEtc(dwDirection, ppenumFormatetc);
173 return hr;
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 );
187 if (SUCCEEDED(hr))
188 hr = pIDOTmp->QueryGetData(pFormatetc);
190 return hr;
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);
204 if (SUCCEEDED(hr))
205 hr = pIDOTmp->GetDataHere(pFormatetc, pmedium);
207 return hr;
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);
221 if (SUCCEEDED(hr))
222 hr = pIDOTmp->GetCanonicalFormatEtc(pFormatectIn, pFormatetcOut);
224 return hr;
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);
238 if (SUCCEEDED(hr))
239 hr = pIDOTmp->SetData(pFormatetc, pmedium, fRelease);
241 return hr;
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);
255 if (SUCCEEDED(hr))
256 hr = pIDOTmp->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection);
258 return hr;
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);
272 if (SUCCEEDED(hr))
273 hr = pIDOTmp->DUnadvise(dwConnection);
275 return hr;
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);
289 if (SUCCEEDED(hr))
290 hr = pIDOTmp->EnumDAdvise(ppenumAdvise);
292 return hr;
295 // for our convenience
297 CAPNDataObject::operator IDataObject*( )
299 return static_cast< IDataObject* >( this );
302 // helper function
304 HRESULT CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject** ppIDataObj )
306 OSL_ASSERT(nullptr != ppIDataObj);
308 *ppIDataObj = nullptr;
309 HRESULT hr = E_FAIL;
311 if (m_hGlobal)
313 IStreamPtr pStm;
314 hr = CreateStreamOnHGlobal(m_hGlobal, KEEP_HGLOB_ON_RELEASE, &pStm);
316 OSL_ENSURE(E_INVALIDARG != hr, "CreateStreamOnHGlobal with invalid args called");
318 if (SUCCEEDED(hr))
320 hr = CoUnmarshalInterface(pStm.get(), __uuidof(IDataObject), reinterpret_cast<void**>(ppIDataObj));
321 OSL_ENSURE(CO_E_NOTINITIALIZED != hr, "COM is not initialized");
324 return hr;
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */