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>
28 #define __uuidof(I) IID_##I
31 #define FREE_HGLOB_ON_RELEASE TRUE
32 #define KEEP_HGLOB_ON_RELEASE FALSE
34 //------------------------------------------------------------------------
36 //------------------------------------------------------------------------
38 CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject
) :
39 m_rIDataObjectOrg( rIDataObject
),
44 OSL_ENSURE( m_rIDataObjectOrg
.get( ), "constructing CAPNDataObject with empty data object" );
46 // we marshal the IDataObject interface pointer here so
47 // that it can be unmarshaled multiple times when this
48 // class will be used from another apartment
50 HRESULT hr
= CreateStreamOnHGlobal( 0, KEEP_HGLOB_ON_RELEASE
, &pStm
);
52 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid args passed to CreateStreamOnHGlobal" );
54 if ( SUCCEEDED( hr
) )
56 HRESULT hr_marshal
= CoMarshalInterface(
58 __uuidof(IDataObject
),
59 static_cast<LPUNKNOWN
>(m_rIDataObjectOrg
.get()),
62 MSHLFLAGS_TABLEWEAK
);
64 OSL_ENSURE( CO_E_NOTINITIALIZED
!= hr_marshal
, "COM is not initialized" );
66 // marshalling may fail if COM is not initialized
67 // for the calling thread which is a program time
68 // error or because of stream errors which are runtime
69 // errors for instance E_OUTOFMEMORY etc.
71 hr
= GetHGlobalFromStream(pStm
.get(), &m_hGlobal
);
73 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid stream passed to GetHGlobalFromStream" );
75 // if the marshalling failed we free the
76 // global memory again and set m_hGlobal
78 if (FAILED(hr_marshal
))
80 OSL_FAIL("marshalling failed");
82 #if OSL_DEBUG_LEVEL > 0
85 GlobalFree(m_hGlobal
);
86 OSL_ENSURE(NULL
== hGlobal
, "GlobalFree failed");
92 CAPNDataObject::~CAPNDataObject( )
97 HRESULT hr
= CreateStreamOnHGlobal(m_hGlobal
, FREE_HGLOB_ON_RELEASE
, &pStm
);
99 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid args passed to CreateStreamOnHGlobal" );
103 hr
= CoReleaseMarshalData(pStm
.get());
104 OSL_ENSURE(SUCCEEDED(hr
), "CoReleaseMarshalData failed");
109 //------------------------------------------------------------------------
110 // IUnknown->QueryInterface
111 //------------------------------------------------------------------------
113 STDMETHODIMP
CAPNDataObject::QueryInterface( REFIID iid
, LPVOID
* ppvObject
)
115 OSL_ASSERT( NULL
!= ppvObject
);
117 if ( NULL
== ppvObject
)
120 HRESULT hr
= E_NOINTERFACE
;
123 if ( ( __uuidof( IUnknown
) == iid
) || ( __uuidof( IDataObject
) == iid
) )
125 *ppvObject
= static_cast< IUnknown
* >( this );
126 ( (LPUNKNOWN
)*ppvObject
)->AddRef( );
133 //------------------------------------------------------------------------
135 //------------------------------------------------------------------------
137 STDMETHODIMP_(ULONG
) CAPNDataObject::AddRef( )
139 return static_cast< ULONG
>( InterlockedIncrement( &m_nRefCnt
) );
142 //------------------------------------------------------------------------
144 //------------------------------------------------------------------------
146 STDMETHODIMP_(ULONG
) CAPNDataObject::Release( )
148 // we need a helper variable because it's not allowed to access
149 // a member variable after an object is destroyed
150 ULONG nRefCnt
= static_cast< ULONG
>( InterlockedDecrement( &m_nRefCnt
) );
158 //------------------------------------------------------------------------
159 // IDataObject->GetData
160 //------------------------------------------------------------------------
162 STDMETHODIMP
CAPNDataObject::GetData( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
)
164 HRESULT hr
= m_rIDataObjectOrg
->GetData( pFormatetc
, pmedium
);
166 if (RPC_E_WRONG_THREAD
== hr
)
168 IDataObjectPtr pIDOTmp
;
169 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
172 hr
= pIDOTmp
->GetData(pFormatetc
, pmedium
);
177 //------------------------------------------------------------------------
178 // IDataObject->EnumFormatEtc
179 //------------------------------------------------------------------------
181 STDMETHODIMP
CAPNDataObject::EnumFormatEtc( DWORD dwDirection
, IEnumFORMATETC
** ppenumFormatetc
)
183 HRESULT hr
= m_rIDataObjectOrg
->EnumFormatEtc(dwDirection
, ppenumFormatetc
);
185 if (RPC_E_WRONG_THREAD
== hr
)
187 IDataObjectPtr pIDOTmp
;
188 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
191 hr
= pIDOTmp
->EnumFormatEtc(dwDirection
, ppenumFormatetc
);
196 //------------------------------------------------------------------------
197 // IDataObject->QueryGetData
198 //------------------------------------------------------------------------
200 STDMETHODIMP
CAPNDataObject::QueryGetData( LPFORMATETC pFormatetc
)
202 HRESULT hr
= m_rIDataObjectOrg
->QueryGetData( pFormatetc
);
204 if (RPC_E_WRONG_THREAD
== hr
)
206 IDataObjectPtr pIDOTmp
;
207 hr
= MarshalIDataObjectIntoCurrentApartment( &pIDOTmp
);
210 hr
= pIDOTmp
->QueryGetData(pFormatetc
);
215 //------------------------------------------------------------------------
216 // IDataObject->GetDataHere
217 //------------------------------------------------------------------------
219 STDMETHODIMP
CAPNDataObject::GetDataHere( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
)
221 HRESULT hr
= m_rIDataObjectOrg
->GetDataHere(pFormatetc
, pmedium
);
223 if (RPC_E_WRONG_THREAD
== hr
)
225 IDataObjectPtr pIDOTmp
;
226 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
229 hr
= pIDOTmp
->GetDataHere(pFormatetc
, pmedium
);
234 //------------------------------------------------------------------------
235 // IDataObject->GetCanonicalFormatEtc
236 //------------------------------------------------------------------------
238 STDMETHODIMP
CAPNDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatectIn
, LPFORMATETC pFormatetcOut
)
240 HRESULT hr
= m_rIDataObjectOrg
->GetCanonicalFormatEtc( pFormatectIn
, pFormatetcOut
);
242 if (RPC_E_WRONG_THREAD
== hr
)
244 IDataObjectPtr pIDOTmp
;
245 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
248 hr
= pIDOTmp
->GetCanonicalFormatEtc(pFormatectIn
, pFormatetcOut
);
253 //------------------------------------------------------------------------
254 // IDataObject->SetData
255 //------------------------------------------------------------------------
257 STDMETHODIMP
CAPNDataObject::SetData( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
, BOOL fRelease
)
259 HRESULT hr
= m_rIDataObjectOrg
->SetData( pFormatetc
, pmedium
, fRelease
);
261 if (RPC_E_WRONG_THREAD
== hr
)
263 IDataObjectPtr pIDOTmp
;
264 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
267 hr
= pIDOTmp
->SetData(pFormatetc
, pmedium
, fRelease
);
272 //------------------------------------------------------------------------
273 // IDataObject->DAdvise
274 //------------------------------------------------------------------------
276 STDMETHODIMP
CAPNDataObject::DAdvise( LPFORMATETC pFormatetc
, DWORD advf
, LPADVISESINK pAdvSink
, DWORD
* pdwConnection
)
278 HRESULT hr
= m_rIDataObjectOrg
->DAdvise(pFormatetc
, advf
, pAdvSink
, pdwConnection
);
280 if (RPC_E_WRONG_THREAD
== hr
)
282 IDataObjectPtr pIDOTmp
;
283 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
286 hr
= pIDOTmp
->DAdvise(pFormatetc
, advf
, pAdvSink
, pdwConnection
);
291 //------------------------------------------------------------------------
292 // IDataObject->DUnadvise
293 //------------------------------------------------------------------------
295 STDMETHODIMP
CAPNDataObject::DUnadvise( DWORD dwConnection
)
297 HRESULT hr
= m_rIDataObjectOrg
->DUnadvise( dwConnection
);
299 if (RPC_E_WRONG_THREAD
== hr
)
301 IDataObjectPtr pIDOTmp
;
302 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
305 hr
= pIDOTmp
->DUnadvise(dwConnection
);
310 //------------------------------------------------------------------------
311 // IDataObject->EnumDAdvise
312 //------------------------------------------------------------------------
314 STDMETHODIMP
CAPNDataObject::EnumDAdvise( LPENUMSTATDATA
* ppenumAdvise
)
316 HRESULT hr
= m_rIDataObjectOrg
->EnumDAdvise(ppenumAdvise
);
318 if (RPC_E_WRONG_THREAD
== hr
)
320 IDataObjectPtr pIDOTmp
;
321 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
324 hr
= pIDOTmp
->EnumDAdvise(ppenumAdvise
);
329 //------------------------------------------------------------------------
330 // for our convenience
331 //------------------------------------------------------------------------
333 CAPNDataObject::operator IDataObject
*( )
335 return static_cast< IDataObject
* >( this );
338 //------------------------------------------------------------------------
340 //------------------------------------------------------------------------
342 HRESULT
CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject
** ppIDataObj
)
344 OSL_ASSERT(NULL
!= ppIDataObj
);
352 hr
= CreateStreamOnHGlobal(m_hGlobal
, KEEP_HGLOB_ON_RELEASE
, &pStm
);
354 OSL_ENSURE(E_INVALIDARG
!= hr
, "CreateStreamOnHGlobal with invalid args called");
358 hr
= CoUnmarshalInterface(pStm
.get(), __uuidof(IDataObject
), (void**)ppIDataObj
);
359 OSL_ENSURE(CO_E_NOTINITIALIZED
!= hr
, "COM is not initialized");
365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */