| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_dtrans.hxx" |
| |
| //------------------------------------------------------------------------ |
| // includes |
| //------------------------------------------------------------------------ |
| #include <osl/diagnose.h> |
| |
| #ifndef _TXDATAOBJECT_HXX_ |
| #include "XTDataObject.hxx" |
| #endif |
| #include <com/sun/star/datatransfer/DataFlavor.hpp> |
| #include "..\misc\ImplHelper.hxx" |
| #include "DTransHelper.hxx" |
| #include "TxtCnvtHlp.hxx" |
| #include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp> |
| #include "FmtFilter.hxx" |
| |
| #if defined _MSC_VER |
| #pragma warning(push,1) |
| #pragma warning(disable:4917) |
| #endif |
| #include <windows.h> |
| #include <shlobj.h> |
| #if defined _MSC_VER |
| #pragma warning(pop) |
| #endif |
| |
| #ifdef __MINGW32__ |
| #define __uuidof(I) IID_##I |
| #endif |
| |
| //------------------------------------------------------------------------ |
| // namespace directives |
| //------------------------------------------------------------------------ |
| |
| using namespace com::sun::star::datatransfer; |
| using namespace com::sun::star::datatransfer::clipboard; |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::lang; |
| using namespace rtl; |
| |
| //------------------------------------------------------------------------ |
| // a helper class that will be thrown by the function validateFormatEtc |
| //------------------------------------------------------------------------ |
| |
| class CInvalidFormatEtcException |
| { |
| public: |
| HRESULT m_hr; |
| CInvalidFormatEtcException( HRESULT hr ) : m_hr( hr ) {}; |
| }; |
| |
| //------------------------------------------------------------------------ |
| // ctor |
| //------------------------------------------------------------------------ |
| |
| CXTDataObject::CXTDataObject( const Reference< XMultiServiceFactory >& aServiceManager, |
| const Reference< XTransferable >& aXTransferable ) : |
| m_nRefCnt( 0 ), |
| m_SrvMgr( aServiceManager ), |
| m_XTransferable( aXTransferable ), |
| m_DataFormatTranslator( aServiceManager ), |
| m_bFormatEtcContainerInitialized( sal_False ), |
| m_FormatRegistrar( m_SrvMgr, m_DataFormatTranslator ) |
| { |
| } |
| |
| //------------------------------------------------------------------------ |
| // IUnknown->QueryInterface |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject ) |
| { |
| if ( NULL == ppvObject ) |
| return E_INVALIDARG; |
| |
| HRESULT hr = E_NOINTERFACE; |
| |
| *ppvObject = NULL; |
| if ( ( __uuidof( IUnknown ) == iid ) || |
| ( __uuidof( IDataObject ) == iid ) ) |
| { |
| *ppvObject = static_cast< IUnknown* >( this ); |
| ( (LPUNKNOWN)*ppvObject )->AddRef( ); |
| hr = S_OK; |
| } |
| |
| return hr; |
| } |
| |
| //------------------------------------------------------------------------ |
| // IUnknown->AddRef |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP_(ULONG) CXTDataObject::AddRef( ) |
| { |
| return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // IUnknown->Release |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP_(ULONG) CXTDataObject::Release( ) |
| { |
| ULONG nRefCnt = |
| static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) ); |
| |
| if ( 0 == nRefCnt ) |
| delete this; |
| |
| return nRefCnt; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) |
| { |
| if ( !(pFormatetc && pmedium) ) |
| return E_INVALIDARG; |
| |
| try |
| { |
| // prepare data transfer |
| invalidateStgMedium( *pmedium ); |
| validateFormatEtc( pFormatetc ); |
| |
| // handle locale request, because locale is a artificial format for us |
| if ( CF_LOCALE == pFormatetc->cfFormat ) |
| renderLocaleAndSetupStgMedium( *pFormatetc, *pmedium ); |
| else if ( CF_UNICODETEXT == pFormatetc->cfFormat ) |
| renderUnicodeAndSetupStgMedium( *pFormatetc, *pmedium ); |
| else |
| renderAnyDataAndSetupStgMedium( *pFormatetc, *pmedium ); |
| } |
| catch(UnsupportedFlavorException&) |
| { |
| HRESULT hr = DV_E_FORMATETC; |
| |
| if ( m_FormatRegistrar.isSynthesizeableFormat( *pFormatetc ) ) |
| hr = renderSynthesizedFormatAndSetupStgMedium( *pFormatetc, *pmedium ); |
| |
| return hr; |
| } |
| catch( CInvalidFormatEtcException& ex ) |
| { |
| return ex.m_hr; |
| } |
| catch( CStgTransferHelper::CStgTransferException& ex ) |
| { |
| return translateStgExceptionCode( ex.m_hr ); |
| } |
| catch(...) |
| { |
| return E_UNEXPECTED; |
| } |
| |
| return S_OK; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| // inline |
| void SAL_CALL CXTDataObject::renderDataAndSetupStgMedium( |
| const sal_Int8* lpStorage, const FORMATETC& fetc, sal_uInt32 nInitStgSize, |
| sal_uInt32 nBytesToTransfer, STGMEDIUM& stgmedium ) |
| { |
| OSL_PRECOND( !nInitStgSize || nInitStgSize && (nInitStgSize >= nBytesToTransfer), |
| "Memory size less than number of bytes to transfer" ); |
| |
| CStgTransferHelper stgTransfHelper( AUTO_INIT ); |
| |
| // setup storage size |
| if ( nInitStgSize > 0 ) |
| stgTransfHelper.init( nInitStgSize, GHND ); |
| |
| #if OSL_DEBUG_LEVEL > 0 |
| sal_uInt32 nBytesWritten = 0; |
| stgTransfHelper.write( lpStorage, nBytesToTransfer, &nBytesWritten ); |
| OSL_ASSERT( nBytesWritten == nBytesToTransfer ); |
| #else |
| stgTransfHelper.write( lpStorage, nBytesToTransfer ); |
| #endif |
| |
| setupStgMedium( fetc, stgTransfHelper, stgmedium ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| //inline |
| void SAL_CALL CXTDataObject::renderLocaleAndSetupStgMedium( |
| FORMATETC& fetc, STGMEDIUM& stgmedium ) |
| { |
| if ( m_FormatRegistrar.hasSynthesizedLocale( ) ) |
| { |
| LCID lcid = m_FormatRegistrar.getSynthesizedLocale( ); |
| renderDataAndSetupStgMedium( |
| reinterpret_cast< sal_Int8* >( &lcid ), |
| fetc, |
| 0, |
| sizeof( LCID ), |
| stgmedium ); |
| } |
| else |
| throw CInvalidFormatEtcException( DV_E_FORMATETC ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| //inline |
| void SAL_CALL CXTDataObject::renderUnicodeAndSetupStgMedium( |
| FORMATETC& fetc, STGMEDIUM& stgmedium ) |
| { |
| DataFlavor aFlavor = formatEtcToDataFlavor( fetc ); |
| |
| Any aAny = m_XTransferable->getTransferData( aFlavor ); |
| |
| // unfortunately not all transferables fulfill the |
| // spec. an do throw an UnsupportedFlavorException |
| // so we must check the any |
| if ( !aAny.hasValue( ) ) |
| { |
| OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); |
| throw UnsupportedFlavorException( ); |
| } |
| |
| OUString aText; |
| aAny >>= aText; |
| |
| sal_uInt32 nBytesToTransfer = aText.getLength( ) * sizeof( sal_Unicode ); |
| |
| // to be sure there is an ending 0 |
| sal_uInt32 nRequiredMemSize = nBytesToTransfer + sizeof( sal_Unicode ); |
| |
| renderDataAndSetupStgMedium( |
| reinterpret_cast< const sal_Int8* >( aText.getStr( ) ), |
| fetc, |
| nRequiredMemSize, |
| nBytesToTransfer, |
| stgmedium ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| //inline |
| void SAL_CALL CXTDataObject::renderAnyDataAndSetupStgMedium( |
| FORMATETC& fetc, STGMEDIUM& stgmedium ) |
| { |
| DataFlavor aFlavor = formatEtcToDataFlavor( fetc ); |
| |
| Any aAny = m_XTransferable->getTransferData( aFlavor ); |
| |
| // unfortunately not all transferables fulfill the |
| // spec. an do throw an UnsupportedFlavorException |
| // so we must check the any |
| if ( !aAny.hasValue( ) ) |
| { |
| OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); |
| throw UnsupportedFlavorException( ); |
| } |
| |
| // unfortunately not all transferables fulfill the |
| // spec. an do throw an UnsupportedFlavorException |
| // so we must check the any |
| if ( !aAny.hasValue( ) ) |
| throw UnsupportedFlavorException( ); |
| |
| Sequence< sal_Int8 > clipDataStream; |
| aAny >>= clipDataStream; |
| |
| sal_uInt32 nRequiredMemSize = 0; |
| if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) ) |
| nRequiredMemSize = sizeof( sal_Int8 ) * clipDataStream.getLength( ) + 1; |
| |
| // prepare data for transmision |
| // #124085# DIBV5 should not happen for now, but keep as hint here |
| if ( CF_DIBV5 == fetc.cfFormat || CF_DIB == fetc.cfFormat ) |
| { |
| #ifdef DBG_UTIL |
| if(CF_DIBV5 == fetc.cfFormat) |
| { |
| OSL_ENSURE(clipDataStream.getLength( ) > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPV5HEADER)), "Wrong size on CF_DIBV5 data (!)"); |
| } |
| else // CF_DIB == fetc.cfFormat |
| { |
| OSL_ENSURE(clipDataStream.getLength( ) > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)), "Wrong size on CF_DIB data (!)"); |
| } |
| #endif |
| |
| // remove BITMAPFILEHEADER |
| clipDataStream = OOBmpToWinDIB( clipDataStream ); |
| } |
| |
| if ( CF_METAFILEPICT == fetc.cfFormat ) |
| { |
| stgmedium.tymed = TYMED_MFPICT; |
| stgmedium.hMetaFilePict = OOMFPictToWinMFPict( clipDataStream ); |
| stgmedium.pUnkForRelease = NULL; |
| } |
| else if( CF_ENHMETAFILE == fetc.cfFormat ) |
| { |
| stgmedium.tymed = TYMED_ENHMF; |
| stgmedium.hMetaFilePict = OOMFPictToWinENHMFPict( clipDataStream ); |
| stgmedium.pUnkForRelease = NULL; |
| } |
| else |
| renderDataAndSetupStgMedium( |
| clipDataStream.getArray( ), |
| fetc, |
| nRequiredMemSize, |
| clipDataStream.getLength( ), |
| stgmedium ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| HRESULT SAL_CALL CXTDataObject::renderSynthesizedFormatAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ) |
| { |
| HRESULT hr = S_OK; |
| |
| try |
| { |
| if ( CF_UNICODETEXT == fetc.cfFormat ) |
| // the transferable seems to have only text |
| renderSynthesizedUnicodeAndSetupStgMedium( fetc, stgmedium ); |
| else if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) ) |
| // the transferable seems to have only unicode text |
| renderSynthesizedTextAndSetupStgMedium( fetc, stgmedium ); |
| else |
| // the transferable seems to have only text/html |
| renderSynthesizedHtmlAndSetupStgMedium( fetc, stgmedium ); |
| } |
| catch(UnsupportedFlavorException&) |
| { |
| hr = DV_E_FORMATETC; |
| } |
| catch( CInvalidFormatEtcException& ) |
| { |
| OSL_ENSURE( sal_False, "Unexpected exception" ); |
| } |
| catch( CStgTransferHelper::CStgTransferException& ex ) |
| { |
| return translateStgExceptionCode( ex.m_hr ); |
| } |
| catch(...) |
| { |
| hr = E_UNEXPECTED; |
| } |
| |
| return hr; |
| } |
| |
| //------------------------------------------------------------------------ |
| // the transferable must have only text, so we will synthesize unicode text |
| //------------------------------------------------------------------------ |
| |
| void SAL_CALL CXTDataObject::renderSynthesizedUnicodeAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ) |
| { |
| OSL_ASSERT( CF_UNICODETEXT == fetc.cfFormat ); |
| |
| Any aAny = m_XTransferable->getTransferData( m_FormatRegistrar.getRegisteredTextFlavor( ) ); |
| |
| // unfortunately not all transferables fulfill the |
| // spec. an do throw an UnsupportedFlavorException |
| // so we must check the any |
| if ( !aAny.hasValue( ) ) |
| { |
| OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); |
| throw UnsupportedFlavorException( ); |
| } |
| |
| Sequence< sal_Int8 > aText; |
| aAny >>= aText; |
| |
| CStgTransferHelper stgTransfHelper; |
| |
| MultiByteToWideCharEx( |
| m_FormatRegistrar.getRegisteredTextCodePage( ), |
| reinterpret_cast< char* >( aText.getArray( ) ), |
| aText.getLength( ), |
| stgTransfHelper ); |
| |
| setupStgMedium( fetc, stgTransfHelper, stgmedium ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // the transferable must have only unicode text so we will sythesize text |
| //------------------------------------------------------------------------ |
| |
| void SAL_CALL CXTDataObject::renderSynthesizedTextAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ) |
| { |
| OSL_ASSERT( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) ); |
| |
| DataFlavor aFlavor = formatEtcToDataFlavor( |
| m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) ); |
| |
| Any aAny = m_XTransferable->getTransferData( aFlavor ); |
| |
| // unfortunately not all transferables fulfill the |
| // spec. an do throw an UnsupportedFlavorException |
| // so we must check the any |
| if ( !aAny.hasValue( ) ) |
| { |
| OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); |
| throw UnsupportedFlavorException( ); |
| } |
| |
| OUString aUnicodeText; |
| aAny >>= aUnicodeText; |
| |
| CStgTransferHelper stgTransfHelper; |
| |
| WideCharToMultiByteEx( |
| GetACP( ), |
| reinterpret_cast<LPCWSTR>( aUnicodeText.getStr( ) ), |
| aUnicodeText.getLength( ), |
| stgTransfHelper ); |
| |
| setupStgMedium( fetc, stgTransfHelper, stgmedium ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| void SAL_CALL CXTDataObject::renderSynthesizedHtmlAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium ) |
| { |
| OSL_ASSERT( m_DataFormatTranslator.isHTMLFormat( fetc.cfFormat ) ); |
| |
| DataFlavor aFlavor; |
| |
| // creating a DataFlavor on the fly |
| aFlavor.MimeType = OUString::createFromAscii( "text/html" ); |
| aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 ); |
| |
| Any aAny = m_XTransferable->getTransferData( aFlavor ); |
| |
| // unfortunately not all transferables fulfill the |
| // spec. an do throw an UnsupportedFlavorException |
| // so we must check the any |
| if ( !aAny.hasValue( ) ) |
| { |
| OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" ); |
| throw UnsupportedFlavorException( ); |
| } |
| |
| Sequence< sal_Int8 > aTextHtmlSequence; |
| aAny >>= aTextHtmlSequence; |
| |
| Sequence< sal_Int8 > aHTMLFormatSequence = TextHtmlToHTMLFormat( aTextHtmlSequence ); |
| |
| sal_uInt32 nBytesToTransfer = aHTMLFormatSequence.getLength( ); |
| |
| renderDataAndSetupStgMedium( |
| reinterpret_cast< const sal_Int8* >( aHTMLFormatSequence.getArray( ) ), |
| fetc, |
| 0, |
| nBytesToTransfer, |
| stgmedium ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // IDataObject->EnumFormatEtc |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::EnumFormatEtc( |
| DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ) |
| { |
| if ( NULL == ppenumFormatetc ) |
| return E_INVALIDARG; |
| |
| if ( DATADIR_SET == dwDirection ) |
| return E_NOTIMPL; |
| |
| *ppenumFormatetc = NULL; |
| |
| InitializeFormatEtcContainer( ); |
| |
| HRESULT hr; |
| if ( DATADIR_GET == dwDirection ) |
| { |
| *ppenumFormatetc = new CEnumFormatEtc( this, m_FormatEtcContainer ); |
| if ( NULL != *ppenumFormatetc ) |
| static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( ); |
| |
| hr = ( NULL != *ppenumFormatetc ) ? S_OK : E_OUTOFMEMORY; |
| } |
| else |
| hr = E_INVALIDARG; |
| |
| return hr; |
| } |
| |
| //------------------------------------------------------------------------ |
| // IDataObject->QueryGetData |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc ) |
| { |
| if ( (NULL == pFormatetc) || IsBadReadPtr( pFormatetc, sizeof( FORMATETC ) ) ) |
| return E_INVALIDARG; |
| |
| InitializeFormatEtcContainer( ); |
| |
| return m_FormatEtcContainer.hasFormatEtc( *pFormatetc ) ? S_OK : S_FALSE; |
| } |
| |
| //------------------------------------------------------------------------ |
| // IDataObject->GetDataHere |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM ) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //------------------------------------------------------------------------ |
| // IDataObject->GetCanonicalFormatEtc |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC ) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //------------------------------------------------------------------------ |
| // IDataObject->SetData |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL ) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //------------------------------------------------------------------------ |
| // IDataObject->DAdvise |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * ) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //------------------------------------------------------------------------ |
| // IDataObject->DUnadvise |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::DUnadvise( DWORD ) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //------------------------------------------------------------------------ |
| // IDataObject->EnumDAdvise |
| //------------------------------------------------------------------------ |
| |
| STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * ) |
| { |
| return E_NOTIMPL; |
| } |
| |
| //------------------------------------------------------------------------ |
| // for our convenience |
| //------------------------------------------------------------------------ |
| |
| CXTDataObject::operator IDataObject*( ) |
| { |
| return static_cast< IDataObject* >( this ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline |
| DataFlavor SAL_CALL CXTDataObject::formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) const |
| { |
| DataFlavor aFlavor; |
| |
| if ( m_FormatRegistrar.hasSynthesizedLocale( ) ) |
| aFlavor = |
| m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, m_FormatRegistrar.getSynthesizedLocale( ) ); |
| else |
| aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc ); |
| |
| if ( !aFlavor.MimeType.getLength( ) ) |
| throw UnsupportedFlavorException( ); |
| |
| return aFlavor; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline |
| void CXTDataObject::validateFormatEtc( LPFORMATETC lpFormatEtc ) const |
| { |
| OSL_ASSERT( lpFormatEtc ); |
| |
| if ( lpFormatEtc->lindex != -1 ) |
| throw CInvalidFormatEtcException( DV_E_LINDEX ); |
| |
| if ( !(lpFormatEtc->dwAspect & DVASPECT_CONTENT) && |
| !(lpFormatEtc->dwAspect & DVASPECT_SHORTNAME) ) |
| throw CInvalidFormatEtcException( DV_E_DVASPECT ); |
| |
| if ( !(lpFormatEtc->tymed & TYMED_HGLOBAL) && |
| !(lpFormatEtc->tymed & TYMED_ISTREAM) && |
| !(lpFormatEtc->tymed & TYMED_MFPICT) && |
| !(lpFormatEtc->tymed & TYMED_ENHMF) ) |
| throw CInvalidFormatEtcException( DV_E_TYMED ); |
| |
| if ( lpFormatEtc->cfFormat == CF_METAFILEPICT && |
| !(lpFormatEtc->tymed & TYMED_MFPICT) ) |
| throw CInvalidFormatEtcException( DV_E_TYMED ); |
| |
| if ( lpFormatEtc->cfFormat == CF_ENHMETAFILE && |
| !(lpFormatEtc->tymed & TYMED_ENHMF) ) |
| throw CInvalidFormatEtcException( DV_E_TYMED ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| //inline |
| void SAL_CALL CXTDataObject::setupStgMedium( const FORMATETC& fetc, |
| CStgTransferHelper& stgTransHlp, |
| STGMEDIUM& stgmedium ) |
| { |
| stgmedium.pUnkForRelease = NULL; |
| |
| if ( fetc.cfFormat == CF_METAFILEPICT ) |
| { |
| stgmedium.tymed = TYMED_MFPICT; |
| stgmedium.hMetaFilePict = static_cast< HMETAFILEPICT >( stgTransHlp.getHGlobal( ) ); |
| } |
| else if ( fetc.cfFormat == CF_ENHMETAFILE ) |
| { |
| stgmedium.tymed = TYMED_ENHMF; |
| stgmedium.hEnhMetaFile = static_cast< HENHMETAFILE >( stgTransHlp.getHGlobal( ) ); |
| } |
| else if ( fetc.tymed & TYMED_HGLOBAL ) |
| { |
| stgmedium.tymed = TYMED_HGLOBAL; |
| stgmedium.hGlobal = stgTransHlp.getHGlobal( ); |
| } |
| else if ( fetc.tymed & TYMED_ISTREAM ) |
| { |
| stgmedium.tymed = TYMED_ISTREAM; |
| stgTransHlp.getIStream( &stgmedium.pstm ); |
| } |
| else |
| OSL_ASSERT( sal_False ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline |
| void SAL_CALL CXTDataObject::invalidateStgMedium( STGMEDIUM& stgmedium ) const |
| { |
| stgmedium.tymed = TYMED_NULL; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline |
| HRESULT SAL_CALL CXTDataObject::translateStgExceptionCode( HRESULT hr ) const |
| { |
| HRESULT hrTransl; |
| |
| switch( hr ) |
| { |
| case STG_E_MEDIUMFULL: |
| hrTransl = hr; |
| break; |
| |
| default: |
| hrTransl = E_UNEXPECTED; |
| break; |
| } |
| |
| return hrTransl; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline void SAL_CALL CXTDataObject::InitializeFormatEtcContainer( ) |
| { |
| if ( !m_bFormatEtcContainerInitialized ) |
| { |
| m_FormatRegistrar.RegisterFormats( m_XTransferable, m_FormatEtcContainer ); |
| m_bFormatEtcContainerInitialized = sal_True; |
| } |
| } |
| |
| //============================================================================ |
| // CEnumFormatEtc |
| //============================================================================ |
| |
| //---------------------------------------------------------------------------- |
| // ctor |
| //---------------------------------------------------------------------------- |
| |
| CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN lpUnkOuter, const CFormatEtcContainer& aFormatEtcContainer ) : |
| m_nRefCnt( 0 ), |
| m_lpUnkOuter( lpUnkOuter ), |
| m_FormatEtcContainer( aFormatEtcContainer ) |
| { |
| Reset( ); |
| } |
| |
| //---------------------------------------------------------------------------- |
| // IUnknown->QueryInterface |
| //---------------------------------------------------------------------------- |
| |
| STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject ) |
| { |
| if ( NULL == ppvObject ) |
| return E_INVALIDARG; |
| |
| HRESULT hr = E_NOINTERFACE; |
| |
| *ppvObject = NULL; |
| |
| if ( ( __uuidof( IUnknown ) == iid ) || |
| ( __uuidof( IEnumFORMATETC ) == iid ) ) |
| { |
| *ppvObject = static_cast< IUnknown* >( this ); |
| static_cast< LPUNKNOWN >( *ppvObject )->AddRef( ); |
| hr = S_OK; |
| } |
| |
| return hr; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // IUnknown->AddRef |
| //---------------------------------------------------------------------------- |
| |
| STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( ) |
| { |
| // keep the dataobject alive |
| m_lpUnkOuter->AddRef( ); |
| return InterlockedIncrement( &m_nRefCnt ); |
| } |
| |
| //---------------------------------------------------------------------------- |
| // IUnknown->Release |
| //---------------------------------------------------------------------------- |
| |
| STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( ) |
| { |
| // release the outer dataobject |
| m_lpUnkOuter->Release( ); |
| |
| ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt ); |
| if ( 0 == nRefCnt ) |
| delete this; |
| |
| return nRefCnt; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // IEnumFORMATETC->Next |
| //---------------------------------------------------------------------------- |
| |
| STDMETHODIMP CEnumFormatEtc::Next( ULONG nRequested, LPFORMATETC lpDest, ULONG* lpFetched ) |
| { |
| if ( ( nRequested < 1 ) || |
| (( nRequested > 1 ) && ( NULL == lpFetched )) || |
| IsBadWritePtr( lpDest, sizeof( FORMATETC ) * nRequested ) ) |
| return E_INVALIDARG; |
| |
| sal_uInt32 nFetched = m_FormatEtcContainer.nextFormatEtc( lpDest, nRequested ); |
| |
| if ( NULL != lpFetched ) |
| *lpFetched = nFetched; |
| |
| return (nFetched == nRequested) ? S_OK : S_FALSE; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // IEnumFORMATETC->Skip |
| //---------------------------------------------------------------------------- |
| |
| STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt ) |
| { |
| return m_FormatEtcContainer.skipFormatEtc( celt ) ? S_OK : S_FALSE; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // IEnumFORMATETC->Reset |
| //---------------------------------------------------------------------------- |
| |
| STDMETHODIMP CEnumFormatEtc::Reset( ) |
| { |
| m_FormatEtcContainer.beginEnumFormatEtc( ); |
| return S_OK; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // IEnumFORMATETC->Clone |
| //---------------------------------------------------------------------------- |
| |
| STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum ) |
| { |
| if ( NULL == ppenum ) |
| return E_INVALIDARG; |
| |
| *ppenum = new CEnumFormatEtc( m_lpUnkOuter, m_FormatEtcContainer ); |
| if ( NULL != ppenum ) |
| static_cast< LPUNKNOWN >( *ppenum )->AddRef( ); |
| |
| return ( NULL != *ppenum ) ? S_OK : E_OUTOFMEMORY; |
| } |