Update ooo320-m1
[ooovba.git] / dtrans / source / win32 / dtobj / XTDataObject.cxx
blob70a08fd92fdacb7702fd8ac332fbd8b834db739e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: XTDataObject.cxx,v $
10 * $Revision: 1.25 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dtrans.hxx"
34 //------------------------------------------------------------------------
35 // includes
36 //------------------------------------------------------------------------
37 #include <osl/diagnose.h>
39 #ifndef _TXDATAOBJECT_HXX_
40 #include "XTDataObject.hxx"
41 #endif
42 #include <com/sun/star/datatransfer/dataflavor.hpp>
43 #include "..\misc\ImplHelper.hxx"
44 #include "DTransHelper.hxx"
45 #include "TxtCnvtHlp.hxx"
46 #include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp>
47 #include "FmtFilter.hxx"
49 #if defined _MSC_VER
50 #pragma warning(push,1)
51 #pragma warning(disable:4917)
52 #endif
53 #include <windows.h>
54 #include <shlobj.h>
55 #if defined _MSC_VER
56 #pragma warning(pop)
57 #endif
59 #ifdef __MINGW32__
60 #define __uuidof(I) IID_##I
61 #endif
63 //------------------------------------------------------------------------
64 // namespace directives
65 //------------------------------------------------------------------------
67 using namespace com::sun::star::datatransfer;
68 using namespace com::sun::star::datatransfer::clipboard;
69 using namespace com::sun::star::uno;
70 using namespace com::sun::star::lang;
71 using namespace rtl;
73 //------------------------------------------------------------------------
74 // a helper class that will be thrown by the function validateFormatEtc
75 //------------------------------------------------------------------------
77 class CInvalidFormatEtcException
79 public:
80 HRESULT m_hr;
81 CInvalidFormatEtcException( HRESULT hr ) : m_hr( hr ) {};
84 //------------------------------------------------------------------------
85 // ctor
86 //------------------------------------------------------------------------
88 CXTDataObject::CXTDataObject( const Reference< XMultiServiceFactory >& aServiceManager,
89 const Reference< XTransferable >& aXTransferable ) :
90 m_nRefCnt( 0 ),
91 m_SrvMgr( aServiceManager ),
92 m_XTransferable( aXTransferable ),
93 m_DataFormatTranslator( aServiceManager ),
94 m_bFormatEtcContainerInitialized( sal_False ),
95 m_FormatRegistrar( m_SrvMgr, m_DataFormatTranslator )
99 //------------------------------------------------------------------------
100 // IUnknown->QueryInterface
101 //------------------------------------------------------------------------
103 STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject )
105 if ( NULL == ppvObject )
106 return E_INVALIDARG;
108 HRESULT hr = E_NOINTERFACE;
110 *ppvObject = NULL;
111 if ( ( __uuidof( IUnknown ) == iid ) ||
112 ( __uuidof( IDataObject ) == iid ) )
114 *ppvObject = static_cast< IUnknown* >( this );
115 ( (LPUNKNOWN)*ppvObject )->AddRef( );
116 hr = S_OK;
119 return hr;
122 //------------------------------------------------------------------------
123 // IUnknown->AddRef
124 //------------------------------------------------------------------------
126 STDMETHODIMP_(ULONG) CXTDataObject::AddRef( )
128 return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
131 //------------------------------------------------------------------------
132 // IUnknown->Release
133 //------------------------------------------------------------------------
135 STDMETHODIMP_(ULONG) CXTDataObject::Release( )
137 ULONG nRefCnt =
138 static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) );
140 if ( 0 == nRefCnt )
141 delete this;
143 return nRefCnt;
146 //------------------------------------------------------------------------
148 //------------------------------------------------------------------------
150 STDMETHODIMP CXTDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
152 if ( !(pFormatetc && pmedium) )
153 return E_INVALIDARG;
157 // prepare data transfer
158 invalidateStgMedium( *pmedium );
159 validateFormatEtc( pFormatetc );
161 // handle locale request, because locale is a artificial format for us
162 if ( CF_LOCALE == pFormatetc->cfFormat )
163 renderLocaleAndSetupStgMedium( *pFormatetc, *pmedium );
164 else if ( CF_UNICODETEXT == pFormatetc->cfFormat )
165 renderUnicodeAndSetupStgMedium( *pFormatetc, *pmedium );
166 else
167 renderAnyDataAndSetupStgMedium( *pFormatetc, *pmedium );
169 catch(UnsupportedFlavorException&)
171 HRESULT hr = DV_E_FORMATETC;
173 if ( m_FormatRegistrar.isSynthesizeableFormat( *pFormatetc ) )
174 hr = renderSynthesizedFormatAndSetupStgMedium( *pFormatetc, *pmedium );
176 return hr;
178 catch( CInvalidFormatEtcException& ex )
180 return ex.m_hr;
182 catch( CStgTransferHelper::CStgTransferException& ex )
184 return translateStgExceptionCode( ex.m_hr );
186 catch(...)
188 return E_UNEXPECTED;
191 return S_OK;
194 //------------------------------------------------------------------------
196 //------------------------------------------------------------------------
198 // inline
199 void SAL_CALL CXTDataObject::renderDataAndSetupStgMedium(
200 const sal_Int8* lpStorage, const FORMATETC& fetc, sal_uInt32 nInitStgSize,
201 sal_uInt32 nBytesToTransfer, STGMEDIUM& stgmedium )
203 OSL_PRECOND( !nInitStgSize || nInitStgSize && (nInitStgSize >= nBytesToTransfer),
204 "Memory size less than number of bytes to transfer" );
206 CStgTransferHelper stgTransfHelper( AUTO_INIT );
208 // setup storage size
209 if ( nInitStgSize > 0 )
210 stgTransfHelper.init( nInitStgSize, GHND );
212 #if OSL_DEBUG_LEVEL > 0
213 sal_uInt32 nBytesWritten = 0;
214 stgTransfHelper.write( lpStorage, nBytesToTransfer, &nBytesWritten );
215 OSL_ASSERT( nBytesWritten == nBytesToTransfer );
216 #else
217 stgTransfHelper.write( lpStorage, nBytesToTransfer );
218 #endif
220 setupStgMedium( fetc, stgTransfHelper, stgmedium );
223 //------------------------------------------------------------------------
225 //------------------------------------------------------------------------
227 //inline
228 void SAL_CALL CXTDataObject::renderLocaleAndSetupStgMedium(
229 FORMATETC& fetc, STGMEDIUM& stgmedium )
231 if ( m_FormatRegistrar.hasSynthesizedLocale( ) )
233 LCID lcid = m_FormatRegistrar.getSynthesizedLocale( );
234 renderDataAndSetupStgMedium(
235 reinterpret_cast< sal_Int8* >( &lcid ),
236 fetc,
238 sizeof( LCID ),
239 stgmedium );
241 else
242 throw CInvalidFormatEtcException( DV_E_FORMATETC );
245 //------------------------------------------------------------------------
247 //------------------------------------------------------------------------
249 //inline
250 void SAL_CALL CXTDataObject::renderUnicodeAndSetupStgMedium(
251 FORMATETC& fetc, STGMEDIUM& stgmedium )
253 DataFlavor aFlavor = formatEtcToDataFlavor( fetc );
255 Any aAny = m_XTransferable->getTransferData( aFlavor );
257 // unfortunately not all transferables fulfill the
258 // spec. an do throw an UnsupportedFlavorException
259 // so we must check the any
260 if ( !aAny.hasValue( ) )
262 OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
263 throw UnsupportedFlavorException( );
266 OUString aText;
267 aAny >>= aText;
269 sal_uInt32 nBytesToTransfer = aText.getLength( ) * sizeof( sal_Unicode );
271 // to be sure there is an ending 0
272 sal_uInt32 nRequiredMemSize = nBytesToTransfer + sizeof( sal_Unicode );
274 renderDataAndSetupStgMedium(
275 reinterpret_cast< const sal_Int8* >( aText.getStr( ) ),
276 fetc,
277 nRequiredMemSize,
278 nBytesToTransfer,
279 stgmedium );
282 //------------------------------------------------------------------------
284 //------------------------------------------------------------------------
286 //inline
287 void SAL_CALL CXTDataObject::renderAnyDataAndSetupStgMedium(
288 FORMATETC& fetc, STGMEDIUM& stgmedium )
290 DataFlavor aFlavor = formatEtcToDataFlavor( fetc );
292 Any aAny = m_XTransferable->getTransferData( aFlavor );
294 // unfortunately not all transferables fulfill the
295 // spec. an do throw an UnsupportedFlavorException
296 // so we must check the any
297 if ( !aAny.hasValue( ) )
299 OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
300 throw UnsupportedFlavorException( );
303 // unfortunately not all transferables fulfill the
304 // spec. an do throw an UnsupportedFlavorException
305 // so we must check the any
306 if ( !aAny.hasValue( ) )
307 throw UnsupportedFlavorException( );
309 Sequence< sal_Int8 > clipDataStream;
310 aAny >>= clipDataStream;
312 sal_uInt32 nRequiredMemSize = 0;
313 if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) )
314 nRequiredMemSize = sizeof( sal_Int8 ) * clipDataStream.getLength( ) + 1;
316 // prepare data for transmision
317 if ( CF_DIB == fetc.cfFormat )
318 clipDataStream = OOBmpToWinDIB( clipDataStream );
320 if ( CF_METAFILEPICT == fetc.cfFormat )
322 stgmedium.tymed = TYMED_MFPICT;
323 stgmedium.hMetaFilePict = OOMFPictToWinMFPict( clipDataStream );
324 stgmedium.pUnkForRelease = NULL;
326 else if( CF_ENHMETAFILE == fetc.cfFormat )
328 stgmedium.tymed = TYMED_ENHMF;
329 stgmedium.hMetaFilePict = OOMFPictToWinENHMFPict( clipDataStream );
330 stgmedium.pUnkForRelease = NULL;
332 else
333 renderDataAndSetupStgMedium(
334 clipDataStream.getArray( ),
335 fetc,
336 nRequiredMemSize,
337 clipDataStream.getLength( ),
338 stgmedium );
341 //------------------------------------------------------------------------
343 //------------------------------------------------------------------------
345 HRESULT SAL_CALL CXTDataObject::renderSynthesizedFormatAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
347 HRESULT hr = S_OK;
351 if ( CF_UNICODETEXT == fetc.cfFormat )
352 // the transferable seems to have only text
353 renderSynthesizedUnicodeAndSetupStgMedium( fetc, stgmedium );
354 else if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) )
355 // the transferable seems to have only unicode text
356 renderSynthesizedTextAndSetupStgMedium( fetc, stgmedium );
357 else
358 // the transferable seems to have only text/html
359 renderSynthesizedHtmlAndSetupStgMedium( fetc, stgmedium );
361 catch(UnsupportedFlavorException&)
363 hr = DV_E_FORMATETC;
365 catch( CInvalidFormatEtcException& )
367 OSL_ENSURE( sal_False, "Unexpected exception" );
369 catch( CStgTransferHelper::CStgTransferException& ex )
371 return translateStgExceptionCode( ex.m_hr );
373 catch(...)
375 hr = E_UNEXPECTED;
378 return hr;
381 //------------------------------------------------------------------------
382 // the transferable must have only text, so we will synthesize unicode text
383 //------------------------------------------------------------------------
385 void SAL_CALL CXTDataObject::renderSynthesizedUnicodeAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
387 OSL_ASSERT( CF_UNICODETEXT == fetc.cfFormat );
389 Any aAny = m_XTransferable->getTransferData( m_FormatRegistrar.getRegisteredTextFlavor( ) );
391 // unfortunately not all transferables fulfill the
392 // spec. an do throw an UnsupportedFlavorException
393 // so we must check the any
394 if ( !aAny.hasValue( ) )
396 OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
397 throw UnsupportedFlavorException( );
400 Sequence< sal_Int8 > aText;
401 aAny >>= aText;
403 CStgTransferHelper stgTransfHelper;
405 MultiByteToWideCharEx(
406 m_FormatRegistrar.getRegisteredTextCodePage( ),
407 reinterpret_cast< char* >( aText.getArray( ) ),
408 aText.getLength( ),
409 stgTransfHelper );
411 setupStgMedium( fetc, stgTransfHelper, stgmedium );
414 //------------------------------------------------------------------------
415 // the transferable must have only unicode text so we will sythesize text
416 //------------------------------------------------------------------------
418 void SAL_CALL CXTDataObject::renderSynthesizedTextAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
420 OSL_ASSERT( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) );
422 DataFlavor aFlavor = formatEtcToDataFlavor(
423 m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) );
425 Any aAny = m_XTransferable->getTransferData( aFlavor );
427 // unfortunately not all transferables fulfill the
428 // spec. an do throw an UnsupportedFlavorException
429 // so we must check the any
430 if ( !aAny.hasValue( ) )
432 OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
433 throw UnsupportedFlavorException( );
436 OUString aUnicodeText;
437 aAny >>= aUnicodeText;
439 CStgTransferHelper stgTransfHelper;
441 WideCharToMultiByteEx(
442 GetACP( ),
443 reinterpret_cast<LPCWSTR>( aUnicodeText.getStr( ) ),
444 aUnicodeText.getLength( ),
445 stgTransfHelper );
447 setupStgMedium( fetc, stgTransfHelper, stgmedium );
450 //------------------------------------------------------------------------
452 //------------------------------------------------------------------------
454 void SAL_CALL CXTDataObject::renderSynthesizedHtmlAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
456 OSL_ASSERT( m_DataFormatTranslator.isHTMLFormat( fetc.cfFormat ) );
458 DataFlavor aFlavor;
460 // creating a DataFlavor on the fly
461 aFlavor.MimeType = OUString::createFromAscii( "text/html" );
462 aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
464 Any aAny = m_XTransferable->getTransferData( aFlavor );
466 // unfortunately not all transferables fulfill the
467 // spec. an do throw an UnsupportedFlavorException
468 // so we must check the any
469 if ( !aAny.hasValue( ) )
471 OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
472 throw UnsupportedFlavorException( );
475 Sequence< sal_Int8 > aTextHtmlSequence;
476 aAny >>= aTextHtmlSequence;
478 Sequence< sal_Int8 > aHTMLFormatSequence = TextHtmlToHTMLFormat( aTextHtmlSequence );
480 sal_uInt32 nBytesToTransfer = aHTMLFormatSequence.getLength( );
482 renderDataAndSetupStgMedium(
483 reinterpret_cast< const sal_Int8* >( aHTMLFormatSequence.getArray( ) ),
484 fetc,
486 nBytesToTransfer,
487 stgmedium );
490 //------------------------------------------------------------------------
491 // IDataObject->EnumFormatEtc
492 //------------------------------------------------------------------------
494 STDMETHODIMP CXTDataObject::EnumFormatEtc(
495 DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
497 if ( NULL == ppenumFormatetc )
498 return E_INVALIDARG;
500 if ( DATADIR_SET == dwDirection )
501 return E_NOTIMPL;
503 *ppenumFormatetc = NULL;
505 InitializeFormatEtcContainer( );
507 HRESULT hr;
508 if ( DATADIR_GET == dwDirection )
510 *ppenumFormatetc = new CEnumFormatEtc( this, m_FormatEtcContainer );
511 if ( NULL != *ppenumFormatetc )
512 static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( );
514 hr = ( NULL != *ppenumFormatetc ) ? S_OK : E_OUTOFMEMORY;
516 else
517 hr = E_INVALIDARG;
519 return hr;
522 //------------------------------------------------------------------------
523 // IDataObject->QueryGetData
524 //------------------------------------------------------------------------
526 STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc )
528 if ( (NULL == pFormatetc) || IsBadReadPtr( pFormatetc, sizeof( FORMATETC ) ) )
529 return E_INVALIDARG;
531 InitializeFormatEtcContainer( );
533 return m_FormatEtcContainer.hasFormatEtc( *pFormatetc ) ? S_OK : S_FALSE;
536 //------------------------------------------------------------------------
537 // IDataObject->GetDataHere
538 //------------------------------------------------------------------------
540 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM )
542 return E_NOTIMPL;
545 //------------------------------------------------------------------------
546 // IDataObject->GetCanonicalFormatEtc
547 //------------------------------------------------------------------------
549 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC )
551 return E_NOTIMPL;
554 //------------------------------------------------------------------------
555 // IDataObject->SetData
556 //------------------------------------------------------------------------
558 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL )
560 return E_NOTIMPL;
563 //------------------------------------------------------------------------
564 // IDataObject->DAdvise
565 //------------------------------------------------------------------------
567 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * )
569 return E_NOTIMPL;
572 //------------------------------------------------------------------------
573 // IDataObject->DUnadvise
574 //------------------------------------------------------------------------
576 STDMETHODIMP CXTDataObject::DUnadvise( DWORD )
578 return E_NOTIMPL;
581 //------------------------------------------------------------------------
582 // IDataObject->EnumDAdvise
583 //------------------------------------------------------------------------
585 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * )
587 return E_NOTIMPL;
590 //------------------------------------------------------------------------
591 // for our convenience
592 //------------------------------------------------------------------------
594 CXTDataObject::operator IDataObject*( )
596 return static_cast< IDataObject* >( this );
599 //------------------------------------------------------------------------
601 //------------------------------------------------------------------------
603 inline
604 DataFlavor SAL_CALL CXTDataObject::formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) const
606 DataFlavor aFlavor;
608 if ( m_FormatRegistrar.hasSynthesizedLocale( ) )
609 aFlavor =
610 m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, m_FormatRegistrar.getSynthesizedLocale( ) );
611 else
612 aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc );
614 if ( !aFlavor.MimeType.getLength( ) )
615 throw UnsupportedFlavorException( );
617 return aFlavor;
620 //------------------------------------------------------------------------
622 //------------------------------------------------------------------------
624 inline
625 void CXTDataObject::validateFormatEtc( LPFORMATETC lpFormatEtc ) const
627 OSL_ASSERT( lpFormatEtc );
629 if ( lpFormatEtc->lindex != -1 )
630 throw CInvalidFormatEtcException( DV_E_LINDEX );
632 if ( !(lpFormatEtc->dwAspect & DVASPECT_CONTENT) &&
633 !(lpFormatEtc->dwAspect & DVASPECT_SHORTNAME) )
634 throw CInvalidFormatEtcException( DV_E_DVASPECT );
636 if ( !(lpFormatEtc->tymed & TYMED_HGLOBAL) &&
637 !(lpFormatEtc->tymed & TYMED_ISTREAM) &&
638 !(lpFormatEtc->tymed & TYMED_MFPICT) &&
639 !(lpFormatEtc->tymed & TYMED_ENHMF) )
640 throw CInvalidFormatEtcException( DV_E_TYMED );
642 if ( lpFormatEtc->cfFormat == CF_METAFILEPICT &&
643 !(lpFormatEtc->tymed & TYMED_MFPICT) )
644 throw CInvalidFormatEtcException( DV_E_TYMED );
646 if ( lpFormatEtc->cfFormat == CF_ENHMETAFILE &&
647 !(lpFormatEtc->tymed & TYMED_ENHMF) )
648 throw CInvalidFormatEtcException( DV_E_TYMED );
651 //------------------------------------------------------------------------
653 //------------------------------------------------------------------------
655 //inline
656 void SAL_CALL CXTDataObject::setupStgMedium( const FORMATETC& fetc,
657 CStgTransferHelper& stgTransHlp,
658 STGMEDIUM& stgmedium )
660 stgmedium.pUnkForRelease = NULL;
662 if ( fetc.cfFormat == CF_METAFILEPICT )
664 stgmedium.tymed = TYMED_MFPICT;
665 stgmedium.hMetaFilePict = static_cast< HMETAFILEPICT >( stgTransHlp.getHGlobal( ) );
667 else if ( fetc.cfFormat == CF_ENHMETAFILE )
669 stgmedium.tymed = TYMED_ENHMF;
670 stgmedium.hEnhMetaFile = static_cast< HENHMETAFILE >( stgTransHlp.getHGlobal( ) );
672 else if ( fetc.tymed & TYMED_HGLOBAL )
674 stgmedium.tymed = TYMED_HGLOBAL;
675 stgmedium.hGlobal = stgTransHlp.getHGlobal( );
677 else if ( fetc.tymed & TYMED_ISTREAM )
679 stgmedium.tymed = TYMED_ISTREAM;
680 stgTransHlp.getIStream( &stgmedium.pstm );
682 else
683 OSL_ASSERT( sal_False );
686 //------------------------------------------------------------------------
688 //------------------------------------------------------------------------
690 inline
691 void SAL_CALL CXTDataObject::invalidateStgMedium( STGMEDIUM& stgmedium ) const
693 stgmedium.tymed = TYMED_NULL;
696 //------------------------------------------------------------------------
698 //------------------------------------------------------------------------
700 inline
701 HRESULT SAL_CALL CXTDataObject::translateStgExceptionCode( HRESULT hr ) const
703 HRESULT hrTransl;
705 switch( hr )
707 case STG_E_MEDIUMFULL:
708 hrTransl = hr;
709 break;
711 default:
712 hrTransl = E_UNEXPECTED;
713 break;
716 return hrTransl;
719 //------------------------------------------------------------------------
721 //------------------------------------------------------------------------
723 inline void SAL_CALL CXTDataObject::InitializeFormatEtcContainer( )
725 if ( !m_bFormatEtcContainerInitialized )
727 m_FormatRegistrar.RegisterFormats( m_XTransferable, m_FormatEtcContainer );
728 m_bFormatEtcContainerInitialized = sal_True;
732 //============================================================================
733 // CEnumFormatEtc
734 //============================================================================
736 //----------------------------------------------------------------------------
737 // ctor
738 //----------------------------------------------------------------------------
740 CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN lpUnkOuter, const CFormatEtcContainer& aFormatEtcContainer ) :
741 m_nRefCnt( 0 ),
742 m_lpUnkOuter( lpUnkOuter ),
743 m_FormatEtcContainer( aFormatEtcContainer )
745 Reset( );
748 //----------------------------------------------------------------------------
749 // IUnknown->QueryInterface
750 //----------------------------------------------------------------------------
752 STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject )
754 if ( NULL == ppvObject )
755 return E_INVALIDARG;
757 HRESULT hr = E_NOINTERFACE;
759 *ppvObject = NULL;
761 if ( ( __uuidof( IUnknown ) == iid ) ||
762 ( __uuidof( IEnumFORMATETC ) == iid ) )
764 *ppvObject = static_cast< IUnknown* >( this );
765 static_cast< LPUNKNOWN >( *ppvObject )->AddRef( );
766 hr = S_OK;
769 return hr;
772 //----------------------------------------------------------------------------
773 // IUnknown->AddRef
774 //----------------------------------------------------------------------------
776 STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( )
778 // keep the dataobject alive
779 m_lpUnkOuter->AddRef( );
780 return InterlockedIncrement( &m_nRefCnt );
783 //----------------------------------------------------------------------------
784 // IUnknown->Release
785 //----------------------------------------------------------------------------
787 STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( )
789 // release the outer dataobject
790 m_lpUnkOuter->Release( );
792 ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt );
793 if ( 0 == nRefCnt )
794 delete this;
796 return nRefCnt;
799 //----------------------------------------------------------------------------
800 // IEnumFORMATETC->Next
801 //----------------------------------------------------------------------------
803 STDMETHODIMP CEnumFormatEtc::Next( ULONG nRequested, LPFORMATETC lpDest, ULONG* lpFetched )
805 if ( ( nRequested < 1 ) ||
806 (( nRequested > 1 ) && ( NULL == lpFetched )) ||
807 IsBadWritePtr( lpDest, sizeof( FORMATETC ) * nRequested ) )
808 return E_INVALIDARG;
810 sal_uInt32 nFetched = m_FormatEtcContainer.nextFormatEtc( lpDest, nRequested );
812 if ( NULL != lpFetched )
813 *lpFetched = nFetched;
815 return (nFetched == nRequested) ? S_OK : S_FALSE;
818 //----------------------------------------------------------------------------
819 // IEnumFORMATETC->Skip
820 //----------------------------------------------------------------------------
822 STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt )
824 return m_FormatEtcContainer.skipFormatEtc( celt ) ? S_OK : S_FALSE;
827 //----------------------------------------------------------------------------
828 // IEnumFORMATETC->Reset
829 //----------------------------------------------------------------------------
831 STDMETHODIMP CEnumFormatEtc::Reset( )
833 m_FormatEtcContainer.beginEnumFormatEtc( );
834 return S_OK;
837 //----------------------------------------------------------------------------
838 // IEnumFORMATETC->Clone
839 //----------------------------------------------------------------------------
841 STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum )
843 if ( NULL == ppenum )
844 return E_INVALIDARG;
846 *ppenum = new CEnumFormatEtc( m_lpUnkOuter, m_FormatEtcContainer );
847 if ( NULL != ppenum )
848 static_cast< LPUNKNOWN >( *ppenum )->AddRef( );
850 return ( NULL != *ppenum ) ? S_OK : E_OUTOFMEMORY;