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
36 CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject
) :
37 m_rIDataObjectOrg( rIDataObject
),
42 OSL_ENSURE( m_rIDataObjectOrg
.get( ), "constructing CAPNDataObject with empty data object" );
44 // we marshal the IDataObject interface pointer here so
45 // that it can be unmarshaled multiple times when this
46 // class will be used from another apartment
48 HRESULT hr
= CreateStreamOnHGlobal( 0, KEEP_HGLOB_ON_RELEASE
, &pStm
);
50 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid args passed to CreateStreamOnHGlobal" );
52 if ( SUCCEEDED( hr
) )
54 HRESULT hr_marshal
= CoMarshalInterface(
56 __uuidof(IDataObject
),
57 static_cast<LPUNKNOWN
>(m_rIDataObjectOrg
.get()),
60 MSHLFLAGS_TABLEWEAK
);
62 OSL_ENSURE( CO_E_NOTINITIALIZED
!= hr_marshal
, "COM is not initialized" );
64 // marshalling may fail if COM is not initialized
65 // for the calling thread which is a program time
66 // error or because of stream errors which are runtime
67 // errors for instance E_OUTOFMEMORY etc.
69 hr
= GetHGlobalFromStream(pStm
.get(), &m_hGlobal
);
71 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid stream passed to GetHGlobalFromStream" );
73 // if the marshalling failed we free the
74 // global memory again and set m_hGlobal
76 if (FAILED(hr_marshal
))
78 OSL_FAIL("marshalling failed");
80 #if OSL_DEBUG_LEVEL > 0
83 GlobalFree(m_hGlobal
);
84 OSL_ENSURE(NULL
== hGlobal
, "GlobalFree failed");
90 CAPNDataObject::~CAPNDataObject( )
95 HRESULT hr
= CreateStreamOnHGlobal(m_hGlobal
, FREE_HGLOB_ON_RELEASE
, &pStm
);
97 OSL_ENSURE( E_INVALIDARG
!= hr
, "invalid args passed to CreateStreamOnHGlobal" );
101 hr
= CoReleaseMarshalData(pStm
.get());
102 OSL_ENSURE(SUCCEEDED(hr
), "CoReleaseMarshalData failed");
107 // IUnknown->QueryInterface
109 STDMETHODIMP
CAPNDataObject::QueryInterface( REFIID iid
, LPVOID
* ppvObject
)
111 OSL_ASSERT( NULL
!= ppvObject
);
113 if ( NULL
== ppvObject
)
116 HRESULT hr
= E_NOINTERFACE
;
119 if ( ( __uuidof( IUnknown
) == iid
) || ( __uuidof( IDataObject
) == iid
) )
121 *ppvObject
= static_cast< IUnknown
* >( this );
122 ( (LPUNKNOWN
)*ppvObject
)->AddRef( );
131 STDMETHODIMP_(ULONG
) CAPNDataObject::AddRef( )
133 return static_cast< ULONG
>( InterlockedIncrement( &m_nRefCnt
) );
138 STDMETHODIMP_(ULONG
) CAPNDataObject::Release( )
140 // we need a helper variable because it's not allowed to access
141 // a member variable after an object is destroyed
142 ULONG nRefCnt
= static_cast< ULONG
>( InterlockedDecrement( &m_nRefCnt
) );
150 // IDataObject->GetData
152 STDMETHODIMP
CAPNDataObject::GetData( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
)
154 HRESULT hr
= m_rIDataObjectOrg
->GetData( pFormatetc
, pmedium
);
156 if (RPC_E_WRONG_THREAD
== hr
)
158 IDataObjectPtr pIDOTmp
;
159 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
162 hr
= pIDOTmp
->GetData(pFormatetc
, pmedium
);
167 // IDataObject->EnumFormatEtc
169 STDMETHODIMP
CAPNDataObject::EnumFormatEtc( DWORD dwDirection
, IEnumFORMATETC
** ppenumFormatetc
)
171 HRESULT hr
= m_rIDataObjectOrg
->EnumFormatEtc(dwDirection
, ppenumFormatetc
);
173 if (RPC_E_WRONG_THREAD
== hr
)
175 IDataObjectPtr pIDOTmp
;
176 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
179 hr
= pIDOTmp
->EnumFormatEtc(dwDirection
, ppenumFormatetc
);
184 // IDataObject->QueryGetData
186 STDMETHODIMP
CAPNDataObject::QueryGetData( LPFORMATETC pFormatetc
)
188 HRESULT hr
= m_rIDataObjectOrg
->QueryGetData( pFormatetc
);
190 if (RPC_E_WRONG_THREAD
== hr
)
192 IDataObjectPtr pIDOTmp
;
193 hr
= MarshalIDataObjectIntoCurrentApartment( &pIDOTmp
);
196 hr
= pIDOTmp
->QueryGetData(pFormatetc
);
201 // IDataObject->GetDataHere
203 STDMETHODIMP
CAPNDataObject::GetDataHere( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
)
205 HRESULT hr
= m_rIDataObjectOrg
->GetDataHere(pFormatetc
, pmedium
);
207 if (RPC_E_WRONG_THREAD
== hr
)
209 IDataObjectPtr pIDOTmp
;
210 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
213 hr
= pIDOTmp
->GetDataHere(pFormatetc
, pmedium
);
218 // IDataObject->GetCanonicalFormatEtc
220 STDMETHODIMP
CAPNDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatectIn
, LPFORMATETC pFormatetcOut
)
222 HRESULT hr
= m_rIDataObjectOrg
->GetCanonicalFormatEtc( pFormatectIn
, pFormatetcOut
);
224 if (RPC_E_WRONG_THREAD
== hr
)
226 IDataObjectPtr pIDOTmp
;
227 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
230 hr
= pIDOTmp
->GetCanonicalFormatEtc(pFormatectIn
, pFormatetcOut
);
235 // IDataObject->SetData
237 STDMETHODIMP
CAPNDataObject::SetData( LPFORMATETC pFormatetc
, LPSTGMEDIUM pmedium
, BOOL fRelease
)
239 HRESULT hr
= m_rIDataObjectOrg
->SetData( pFormatetc
, pmedium
, fRelease
);
241 if (RPC_E_WRONG_THREAD
== hr
)
243 IDataObjectPtr pIDOTmp
;
244 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
247 hr
= pIDOTmp
->SetData(pFormatetc
, pmedium
, fRelease
);
252 // IDataObject->DAdvise
254 STDMETHODIMP
CAPNDataObject::DAdvise( LPFORMATETC pFormatetc
, DWORD advf
, LPADVISESINK pAdvSink
, DWORD
* pdwConnection
)
256 HRESULT hr
= m_rIDataObjectOrg
->DAdvise(pFormatetc
, advf
, pAdvSink
, pdwConnection
);
258 if (RPC_E_WRONG_THREAD
== hr
)
260 IDataObjectPtr pIDOTmp
;
261 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
264 hr
= pIDOTmp
->DAdvise(pFormatetc
, advf
, pAdvSink
, pdwConnection
);
269 // IDataObject->DUnadvise
271 STDMETHODIMP
CAPNDataObject::DUnadvise( DWORD dwConnection
)
273 HRESULT hr
= m_rIDataObjectOrg
->DUnadvise( dwConnection
);
275 if (RPC_E_WRONG_THREAD
== hr
)
277 IDataObjectPtr pIDOTmp
;
278 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
281 hr
= pIDOTmp
->DUnadvise(dwConnection
);
286 // IDataObject->EnumDAdvise
288 STDMETHODIMP
CAPNDataObject::EnumDAdvise( LPENUMSTATDATA
* ppenumAdvise
)
290 HRESULT hr
= m_rIDataObjectOrg
->EnumDAdvise(ppenumAdvise
);
292 if (RPC_E_WRONG_THREAD
== hr
)
294 IDataObjectPtr pIDOTmp
;
295 hr
= MarshalIDataObjectIntoCurrentApartment(&pIDOTmp
);
298 hr
= pIDOTmp
->EnumDAdvise(ppenumAdvise
);
303 // for our convenience
305 CAPNDataObject::operator IDataObject
*( )
307 return static_cast< IDataObject
* >( this );
312 HRESULT
CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject
** ppIDataObj
)
314 OSL_ASSERT(NULL
!= ppIDataObj
);
322 hr
= CreateStreamOnHGlobal(m_hGlobal
, KEEP_HGLOB_ON_RELEASE
, &pStm
);
324 OSL_ENSURE(E_INVALIDARG
!= hr
, "CreateStreamOnHGlobal with invalid args called");
328 hr
= CoUnmarshalInterface(pStm
.get(), __uuidof(IDataObject
), (void**)ppIDataObj
);
329 OSL_ENSURE(CO_E_NOTINITIALIZED
!= hr
, "COM is not initialized");
335 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */