1*48123e16SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*48123e16SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*48123e16SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*48123e16SAndrew Rist * distributed with this work for additional information 6*48123e16SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*48123e16SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*48123e16SAndrew Rist * "License"); you may not use this file except in compliance 9*48123e16SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*48123e16SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*48123e16SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*48123e16SAndrew Rist * software distributed under the License is distributed on an 15*48123e16SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*48123e16SAndrew Rist * KIND, either express or implied. See the License for the 17*48123e16SAndrew Rist * specific language governing permissions and limitations 18*48123e16SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*48123e16SAndrew Rist *************************************************************/ 21*48123e16SAndrew Rist 22*48123e16SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_dtrans.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir //------------------------------------------------------------------------ 28cdf0e10cSrcweir // includes 29cdf0e10cSrcweir //------------------------------------------------------------------------ 30cdf0e10cSrcweir #include "APNDataObject.hxx" 31cdf0e10cSrcweir #include <osl/diagnose.h> 32cdf0e10cSrcweir 33cdf0e10cSrcweir #include <systools/win32/comtools.hxx> 34cdf0e10cSrcweir #ifdef __MINGW32__ 35cdf0e10cSrcweir #define __uuidof(I) IID_##I 36cdf0e10cSrcweir #endif 37cdf0e10cSrcweir 38cdf0e10cSrcweir //------------------------------------------------------------------------ 39cdf0e10cSrcweir // defines 40cdf0e10cSrcweir //------------------------------------------------------------------------ 41cdf0e10cSrcweir 42cdf0e10cSrcweir #define FREE_HGLOB_ON_RELEASE TRUE 43cdf0e10cSrcweir #define KEEP_HGLOB_ON_RELEASE FALSE 44cdf0e10cSrcweir 45cdf0e10cSrcweir //------------------------------------------------------------------------ 46cdf0e10cSrcweir // ctor 47cdf0e10cSrcweir //------------------------------------------------------------------------ 48cdf0e10cSrcweir 49cdf0e10cSrcweir CAPNDataObject::CAPNDataObject( IDataObjectPtr rIDataObject ) : 50cdf0e10cSrcweir m_rIDataObjectOrg( rIDataObject ), 51cdf0e10cSrcweir m_hGlobal( NULL ), 52cdf0e10cSrcweir m_nRefCnt( 0 ) 53cdf0e10cSrcweir { 54cdf0e10cSrcweir 55cdf0e10cSrcweir OSL_ENSURE( m_rIDataObjectOrg.get( ), "constructing CAPNDataObject with empty data object" ); 56cdf0e10cSrcweir 57cdf0e10cSrcweir // we marshal the IDataObject interface pointer here so 58cdf0e10cSrcweir // that it can be unmarshaled multiple times when this 59cdf0e10cSrcweir // class will be used from another apartment 60cdf0e10cSrcweir IStreamPtr pStm; 61cdf0e10cSrcweir HRESULT hr = CreateStreamOnHGlobal( 0, KEEP_HGLOB_ON_RELEASE, &pStm ); 62cdf0e10cSrcweir 63cdf0e10cSrcweir OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" ); 64cdf0e10cSrcweir 65cdf0e10cSrcweir if ( SUCCEEDED( hr ) ) 66cdf0e10cSrcweir { 67cdf0e10cSrcweir HRESULT hr_marshal = CoMarshalInterface( 68cdf0e10cSrcweir pStm.get(), 69cdf0e10cSrcweir __uuidof(IDataObject), 70cdf0e10cSrcweir static_cast<LPUNKNOWN>(m_rIDataObjectOrg.get()), 71cdf0e10cSrcweir MSHCTX_LOCAL, 72cdf0e10cSrcweir NULL, 73cdf0e10cSrcweir MSHLFLAGS_TABLEWEAK ); 74cdf0e10cSrcweir 75cdf0e10cSrcweir OSL_ENSURE( CO_E_NOTINITIALIZED != hr_marshal, "COM is not initialized" ); 76cdf0e10cSrcweir 77cdf0e10cSrcweir // marshalling may fail if COM is not initialized 78cdf0e10cSrcweir // for the calling thread which is a program time 79cdf0e10cSrcweir // error or because of stream errors which are runtime 80cdf0e10cSrcweir // errors for instance E_OUTOFMEMORY etc. 81cdf0e10cSrcweir 82cdf0e10cSrcweir hr = GetHGlobalFromStream(pStm.get(), &m_hGlobal ); 83cdf0e10cSrcweir 84cdf0e10cSrcweir OSL_ENSURE( E_INVALIDARG != hr, "invalid stream passed to GetHGlobalFromStream" ); 85cdf0e10cSrcweir 86cdf0e10cSrcweir // if the marshalling failed we free the 87cdf0e10cSrcweir // global memory again and set m_hGlobal 88cdf0e10cSrcweir // to a defined value 89cdf0e10cSrcweir if (FAILED(hr_marshal)) 90cdf0e10cSrcweir { 91cdf0e10cSrcweir OSL_ENSURE(sal_False, "marshalling failed"); 92cdf0e10cSrcweir 93cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 94cdf0e10cSrcweir HGLOBAL hGlobal = 95cdf0e10cSrcweir #endif 96cdf0e10cSrcweir GlobalFree(m_hGlobal); 97cdf0e10cSrcweir OSL_ENSURE(NULL == hGlobal, "GlobalFree failed"); 98cdf0e10cSrcweir m_hGlobal = NULL; 99cdf0e10cSrcweir } 100cdf0e10cSrcweir } 101cdf0e10cSrcweir } 102cdf0e10cSrcweir 103cdf0e10cSrcweir CAPNDataObject::~CAPNDataObject( ) 104cdf0e10cSrcweir { 105cdf0e10cSrcweir if (m_hGlobal) 106cdf0e10cSrcweir { 107cdf0e10cSrcweir IStreamPtr pStm; 108cdf0e10cSrcweir HRESULT hr = CreateStreamOnHGlobal(m_hGlobal, FREE_HGLOB_ON_RELEASE, &pStm); 109cdf0e10cSrcweir 110cdf0e10cSrcweir OSL_ENSURE( E_INVALIDARG != hr, "invalid args passed to CreateStreamOnHGlobal" ); 111cdf0e10cSrcweir 112cdf0e10cSrcweir if (SUCCEEDED(hr)) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir hr = CoReleaseMarshalData(pStm.get()); 115cdf0e10cSrcweir OSL_ENSURE(SUCCEEDED(hr), "CoReleaseMarshalData failed"); 116cdf0e10cSrcweir } 117cdf0e10cSrcweir } 118cdf0e10cSrcweir } 119cdf0e10cSrcweir 120cdf0e10cSrcweir //------------------------------------------------------------------------ 121cdf0e10cSrcweir // IUnknown->QueryInterface 122cdf0e10cSrcweir //------------------------------------------------------------------------ 123cdf0e10cSrcweir 124cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject ) 125cdf0e10cSrcweir { 126cdf0e10cSrcweir OSL_ASSERT( NULL != ppvObject ); 127cdf0e10cSrcweir 128cdf0e10cSrcweir if ( NULL == ppvObject ) 129cdf0e10cSrcweir return E_INVALIDARG; 130cdf0e10cSrcweir 131cdf0e10cSrcweir HRESULT hr = E_NOINTERFACE; 132cdf0e10cSrcweir *ppvObject = NULL; 133cdf0e10cSrcweir 134cdf0e10cSrcweir if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) ) 135cdf0e10cSrcweir { 136cdf0e10cSrcweir *ppvObject = static_cast< IUnknown* >( this ); 137cdf0e10cSrcweir ( (LPUNKNOWN)*ppvObject )->AddRef( ); 138cdf0e10cSrcweir hr = S_OK; 139cdf0e10cSrcweir } 140cdf0e10cSrcweir 141cdf0e10cSrcweir return hr; 142cdf0e10cSrcweir } 143cdf0e10cSrcweir 144cdf0e10cSrcweir //------------------------------------------------------------------------ 145cdf0e10cSrcweir // IUnknown->AddRef 146cdf0e10cSrcweir //------------------------------------------------------------------------ 147cdf0e10cSrcweir 148cdf0e10cSrcweir STDMETHODIMP_(ULONG) CAPNDataObject::AddRef( ) 149cdf0e10cSrcweir { 150cdf0e10cSrcweir return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) ); 151cdf0e10cSrcweir } 152cdf0e10cSrcweir 153cdf0e10cSrcweir //------------------------------------------------------------------------ 154cdf0e10cSrcweir // IUnknown->Release 155cdf0e10cSrcweir //------------------------------------------------------------------------ 156cdf0e10cSrcweir 157cdf0e10cSrcweir STDMETHODIMP_(ULONG) CAPNDataObject::Release( ) 158cdf0e10cSrcweir { 159cdf0e10cSrcweir // we need a helper variable because it's not allowed to access 160cdf0e10cSrcweir // a member variable after an object is destroyed 161cdf0e10cSrcweir ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) ); 162cdf0e10cSrcweir 163cdf0e10cSrcweir if ( 0 == nRefCnt ) 164cdf0e10cSrcweir delete this; 165cdf0e10cSrcweir 166cdf0e10cSrcweir return nRefCnt; 167cdf0e10cSrcweir } 168cdf0e10cSrcweir 169cdf0e10cSrcweir //------------------------------------------------------------------------ 170cdf0e10cSrcweir // IDataObject->GetData 171cdf0e10cSrcweir //------------------------------------------------------------------------ 172cdf0e10cSrcweir 173cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) 174cdf0e10cSrcweir { 175cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->GetData( pFormatetc, pmedium ); 176cdf0e10cSrcweir 177cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 178cdf0e10cSrcweir { 179cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 180cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); 181cdf0e10cSrcweir 182cdf0e10cSrcweir if (SUCCEEDED(hr)) 183cdf0e10cSrcweir hr = pIDOTmp->GetData(pFormatetc, pmedium); 184cdf0e10cSrcweir } 185cdf0e10cSrcweir return hr; 186cdf0e10cSrcweir } 187cdf0e10cSrcweir 188cdf0e10cSrcweir //------------------------------------------------------------------------ 189cdf0e10cSrcweir // IDataObject->EnumFormatEtc 190cdf0e10cSrcweir //------------------------------------------------------------------------ 191cdf0e10cSrcweir 192cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ) 193cdf0e10cSrcweir { 194cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->EnumFormatEtc(dwDirection, ppenumFormatetc); 195cdf0e10cSrcweir 196cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 197cdf0e10cSrcweir { 198cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 199cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); 200cdf0e10cSrcweir 201cdf0e10cSrcweir if (SUCCEEDED(hr)) 202cdf0e10cSrcweir hr = pIDOTmp->EnumFormatEtc(dwDirection, ppenumFormatetc); 203cdf0e10cSrcweir } 204cdf0e10cSrcweir return hr; 205cdf0e10cSrcweir } 206cdf0e10cSrcweir 207cdf0e10cSrcweir //------------------------------------------------------------------------ 208cdf0e10cSrcweir // IDataObject->QueryGetData 209cdf0e10cSrcweir //------------------------------------------------------------------------ 210cdf0e10cSrcweir 211cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::QueryGetData( LPFORMATETC pFormatetc ) 212cdf0e10cSrcweir { 213cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->QueryGetData( pFormatetc ); 214cdf0e10cSrcweir 215cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 216cdf0e10cSrcweir { 217cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 218cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment( &pIDOTmp ); 219cdf0e10cSrcweir 220cdf0e10cSrcweir if (SUCCEEDED(hr)) 221cdf0e10cSrcweir hr = pIDOTmp->QueryGetData(pFormatetc); 222cdf0e10cSrcweir } 223cdf0e10cSrcweir return hr; 224cdf0e10cSrcweir } 225cdf0e10cSrcweir 226cdf0e10cSrcweir //------------------------------------------------------------------------ 227cdf0e10cSrcweir // IDataObject->GetDataHere 228cdf0e10cSrcweir //------------------------------------------------------------------------ 229cdf0e10cSrcweir 230cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::GetDataHere( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) 231cdf0e10cSrcweir { 232cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->GetDataHere(pFormatetc, pmedium); 233cdf0e10cSrcweir 234cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 235cdf0e10cSrcweir { 236cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 237cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); 238cdf0e10cSrcweir 239cdf0e10cSrcweir if (SUCCEEDED(hr)) 240cdf0e10cSrcweir hr = pIDOTmp->GetDataHere(pFormatetc, pmedium); 241cdf0e10cSrcweir } 242cdf0e10cSrcweir return hr; 243cdf0e10cSrcweir } 244cdf0e10cSrcweir 245cdf0e10cSrcweir //------------------------------------------------------------------------ 246cdf0e10cSrcweir // IDataObject->GetCanonicalFormatEtc 247cdf0e10cSrcweir //------------------------------------------------------------------------ 248cdf0e10cSrcweir 249cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatectIn, LPFORMATETC pFormatetcOut) 250cdf0e10cSrcweir { 251cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->GetCanonicalFormatEtc( pFormatectIn, pFormatetcOut ); 252cdf0e10cSrcweir 253cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 254cdf0e10cSrcweir { 255cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 256cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); 257cdf0e10cSrcweir 258cdf0e10cSrcweir if (SUCCEEDED(hr)) 259cdf0e10cSrcweir hr = pIDOTmp->GetCanonicalFormatEtc(pFormatectIn, pFormatetcOut); 260cdf0e10cSrcweir } 261cdf0e10cSrcweir return hr; 262cdf0e10cSrcweir } 263cdf0e10cSrcweir 264cdf0e10cSrcweir //------------------------------------------------------------------------ 265cdf0e10cSrcweir // IDataObject->SetData 266cdf0e10cSrcweir //------------------------------------------------------------------------ 267cdf0e10cSrcweir 268cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::SetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium, BOOL fRelease ) 269cdf0e10cSrcweir { 270cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->SetData( pFormatetc, pmedium, fRelease ); 271cdf0e10cSrcweir 272cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 275cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); 276cdf0e10cSrcweir 277cdf0e10cSrcweir if (SUCCEEDED(hr)) 278cdf0e10cSrcweir hr = pIDOTmp->SetData(pFormatetc, pmedium, fRelease); 279cdf0e10cSrcweir } 280cdf0e10cSrcweir return hr; 281cdf0e10cSrcweir } 282cdf0e10cSrcweir 283cdf0e10cSrcweir //------------------------------------------------------------------------ 284cdf0e10cSrcweir // IDataObject->DAdvise 285cdf0e10cSrcweir //------------------------------------------------------------------------ 286cdf0e10cSrcweir 287cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::DAdvise( LPFORMATETC pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection ) 288cdf0e10cSrcweir { 289cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection); 290cdf0e10cSrcweir 291cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 292cdf0e10cSrcweir { 293cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 294cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); 295cdf0e10cSrcweir 296cdf0e10cSrcweir if (SUCCEEDED(hr)) 297cdf0e10cSrcweir hr = pIDOTmp->DAdvise(pFormatetc, advf, pAdvSink, pdwConnection); 298cdf0e10cSrcweir } 299cdf0e10cSrcweir return hr; 300cdf0e10cSrcweir } 301cdf0e10cSrcweir 302cdf0e10cSrcweir //------------------------------------------------------------------------ 303cdf0e10cSrcweir // IDataObject->DUnadvise 304cdf0e10cSrcweir //------------------------------------------------------------------------ 305cdf0e10cSrcweir 306cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::DUnadvise( DWORD dwConnection ) 307cdf0e10cSrcweir { 308cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->DUnadvise( dwConnection ); 309cdf0e10cSrcweir 310cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 311cdf0e10cSrcweir { 312cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 313cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); 314cdf0e10cSrcweir 315cdf0e10cSrcweir if (SUCCEEDED(hr)) 316cdf0e10cSrcweir hr = pIDOTmp->DUnadvise(dwConnection); 317cdf0e10cSrcweir } 318cdf0e10cSrcweir return hr; 319cdf0e10cSrcweir } 320cdf0e10cSrcweir 321cdf0e10cSrcweir //------------------------------------------------------------------------ 322cdf0e10cSrcweir // IDataObject->EnumDAdvise 323cdf0e10cSrcweir //------------------------------------------------------------------------ 324cdf0e10cSrcweir 325cdf0e10cSrcweir STDMETHODIMP CAPNDataObject::EnumDAdvise( LPENUMSTATDATA * ppenumAdvise ) 326cdf0e10cSrcweir { 327cdf0e10cSrcweir HRESULT hr = m_rIDataObjectOrg->EnumDAdvise(ppenumAdvise); 328cdf0e10cSrcweir 329cdf0e10cSrcweir if (RPC_E_WRONG_THREAD == hr) 330cdf0e10cSrcweir { 331cdf0e10cSrcweir IDataObjectPtr pIDOTmp; 332cdf0e10cSrcweir hr = MarshalIDataObjectIntoCurrentApartment(&pIDOTmp); 333cdf0e10cSrcweir 334cdf0e10cSrcweir if (SUCCEEDED(hr)) 335cdf0e10cSrcweir hr = pIDOTmp->EnumDAdvise(ppenumAdvise); 336cdf0e10cSrcweir } 337cdf0e10cSrcweir return hr; 338cdf0e10cSrcweir } 339cdf0e10cSrcweir 340cdf0e10cSrcweir //------------------------------------------------------------------------ 341cdf0e10cSrcweir // for our convenience 342cdf0e10cSrcweir //------------------------------------------------------------------------ 343cdf0e10cSrcweir 344cdf0e10cSrcweir CAPNDataObject::operator IDataObject*( ) 345cdf0e10cSrcweir { 346cdf0e10cSrcweir return static_cast< IDataObject* >( this ); 347cdf0e10cSrcweir } 348cdf0e10cSrcweir 349cdf0e10cSrcweir //------------------------------------------------------------------------ 350cdf0e10cSrcweir // helper function 351cdf0e10cSrcweir //------------------------------------------------------------------------ 352cdf0e10cSrcweir 353cdf0e10cSrcweir HRESULT CAPNDataObject::MarshalIDataObjectIntoCurrentApartment( IDataObject** ppIDataObj ) 354cdf0e10cSrcweir { 355cdf0e10cSrcweir OSL_ASSERT(NULL != ppIDataObj); 356cdf0e10cSrcweir 357cdf0e10cSrcweir *ppIDataObj = NULL; 358cdf0e10cSrcweir HRESULT hr = E_FAIL; 359cdf0e10cSrcweir 360cdf0e10cSrcweir if (m_hGlobal) 361cdf0e10cSrcweir { 362cdf0e10cSrcweir IStreamPtr pStm; 363cdf0e10cSrcweir hr = CreateStreamOnHGlobal(m_hGlobal, KEEP_HGLOB_ON_RELEASE, &pStm); 364cdf0e10cSrcweir 365cdf0e10cSrcweir OSL_ENSURE(E_INVALIDARG != hr, "CreateStreamOnHGlobal with invalid args called"); 366cdf0e10cSrcweir 367cdf0e10cSrcweir if (SUCCEEDED(hr)) 368cdf0e10cSrcweir { 369cdf0e10cSrcweir hr = CoUnmarshalInterface(pStm.get(), __uuidof(IDataObject), (void**)ppIDataObj); 370cdf0e10cSrcweir OSL_ENSURE(CO_E_NOTINITIALIZED != hr, "COM is not initialized"); 371cdf0e10cSrcweir } 372cdf0e10cSrcweir } 373cdf0e10cSrcweir return hr; 374cdf0e10cSrcweir } 375