blob: cb23ef0b661507ec083f8948627be789b8380ab5 [file] [log] [blame]
/**************************************************************
*
* 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;
}