bump product version to 4.1.6.2
[LibreOffice.git] / dtrans / source / win32 / dtobj / XTDataObject.cxx
blobc213517cdd190d2dd952afe3757ac97bfa62b7a7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/diagnose.h>
22 #include "XTDataObject.hxx"
23 #include <com/sun/star/datatransfer/DataFlavor.hpp>
24 #include "../misc/ImplHelper.hxx"
25 #include "DTransHelper.hxx"
26 #include "TxtCnvtHlp.hxx"
27 #include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp>
28 #include "FmtFilter.hxx"
29 #include <comphelper/processfactory.hxx>
31 #if defined _MSC_VER
32 #pragma warning(push,1)
33 #pragma warning(disable:4917)
34 #endif
35 #include <windows.h>
36 #include <shlobj.h>
37 #if defined _MSC_VER
38 #pragma warning(pop)
39 #endif
41 #ifdef __MINGW32__
42 #if defined __uuidof
43 #undef __uuidof
44 #endif
45 #define __uuidof(I) IID_##I
46 #endif
48 //------------------------------------------------------------------------
49 // namespace directives
50 //------------------------------------------------------------------------
52 using namespace com::sun::star::datatransfer;
53 using namespace com::sun::star::datatransfer::clipboard;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::lang;
58 //------------------------------------------------------------------------
59 // a helper class that will be thrown by the function validateFormatEtc
60 //------------------------------------------------------------------------
62 class CInvalidFormatEtcException
64 public:
65 HRESULT m_hr;
66 CInvalidFormatEtcException( HRESULT hr ) : m_hr( hr ) {};
69 //------------------------------------------------------------------------
70 // ctor
71 //------------------------------------------------------------------------
73 CXTDataObject::CXTDataObject( const Reference< XComponentContext >& rxContext,
74 const Reference< XTransferable >& aXTransferable )
75 : m_nRefCnt( 0 )
76 , m_XTransferable( aXTransferable )
77 , m_bFormatEtcContainerInitialized( sal_False )
78 , m_DataFormatTranslator( rxContext )
79 , m_FormatRegistrar( rxContext, m_DataFormatTranslator )
83 //------------------------------------------------------------------------
84 // IUnknown->QueryInterface
85 //------------------------------------------------------------------------
87 STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject )
89 if ( NULL == ppvObject )
90 return E_INVALIDARG;
92 HRESULT hr = E_NOINTERFACE;
94 *ppvObject = NULL;
95 if ( ( __uuidof( IUnknown ) == iid ) ||
96 ( __uuidof( IDataObject ) == iid ) )
98 *ppvObject = static_cast< IUnknown* >( this );
99 ( (LPUNKNOWN)*ppvObject )->AddRef( );
100 hr = S_OK;
103 return hr;
106 //------------------------------------------------------------------------
107 // IUnknown->AddRef
108 //------------------------------------------------------------------------
110 STDMETHODIMP_(ULONG) CXTDataObject::AddRef( )
112 return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
115 //------------------------------------------------------------------------
116 // IUnknown->Release
117 //------------------------------------------------------------------------
119 STDMETHODIMP_(ULONG) CXTDataObject::Release( )
121 ULONG nRefCnt =
122 static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) );
124 if ( 0 == nRefCnt )
125 delete this;
127 return nRefCnt;
130 //------------------------------------------------------------------------
132 //------------------------------------------------------------------------
134 STDMETHODIMP CXTDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
136 if ( !(pFormatetc && pmedium) )
137 return E_INVALIDARG;
141 // prepare data transfer
142 invalidateStgMedium( *pmedium );
143 validateFormatEtc( pFormatetc );
145 // handle locale request, because locale is a artificial format for us
146 if ( CF_LOCALE == pFormatetc->cfFormat )
147 renderLocaleAndSetupStgMedium( *pFormatetc, *pmedium );
148 else if ( CF_UNICODETEXT == pFormatetc->cfFormat )
149 renderUnicodeAndSetupStgMedium( *pFormatetc, *pmedium );
150 else
151 renderAnyDataAndSetupStgMedium( *pFormatetc, *pmedium );
153 catch(UnsupportedFlavorException&)
155 HRESULT hr = DV_E_FORMATETC;
157 if ( m_FormatRegistrar.isSynthesizeableFormat( *pFormatetc ) )
158 hr = renderSynthesizedFormatAndSetupStgMedium( *pFormatetc, *pmedium );
160 return hr;
162 catch( CInvalidFormatEtcException& ex )
164 return ex.m_hr;
166 catch( CStgTransferHelper::CStgTransferException& ex )
168 return translateStgExceptionCode( ex.m_hr );
170 catch(...)
172 return E_UNEXPECTED;
175 return S_OK;
178 //------------------------------------------------------------------------
180 //------------------------------------------------------------------------
182 // inline
183 void SAL_CALL CXTDataObject::renderDataAndSetupStgMedium(
184 const sal_Int8* lpStorage, const FORMATETC& fetc, sal_uInt32 nInitStgSize,
185 sal_uInt32 nBytesToTransfer, STGMEDIUM& stgmedium )
187 OSL_PRECOND( !nInitStgSize || nInitStgSize && (nInitStgSize >= nBytesToTransfer),
188 "Memory size less than number of bytes to transfer" );
190 CStgTransferHelper stgTransfHelper( AUTO_INIT );
192 // setup storage size
193 if ( nInitStgSize > 0 )
194 stgTransfHelper.init( nInitStgSize, GHND );
196 #if OSL_DEBUG_LEVEL > 0
197 sal_uInt32 nBytesWritten = 0;
198 stgTransfHelper.write( lpStorage, nBytesToTransfer, &nBytesWritten );
199 OSL_ASSERT( nBytesWritten == nBytesToTransfer );
200 #else
201 stgTransfHelper.write( lpStorage, nBytesToTransfer );
202 #endif
204 setupStgMedium( fetc, stgTransfHelper, stgmedium );
207 //------------------------------------------------------------------------
209 //------------------------------------------------------------------------
211 //inline
212 void SAL_CALL CXTDataObject::renderLocaleAndSetupStgMedium(
213 FORMATETC& fetc, STGMEDIUM& stgmedium )
215 if ( m_FormatRegistrar.hasSynthesizedLocale( ) )
217 LCID lcid = m_FormatRegistrar.getSynthesizedLocale( );
218 renderDataAndSetupStgMedium(
219 reinterpret_cast< sal_Int8* >( &lcid ),
220 fetc,
222 sizeof( LCID ),
223 stgmedium );
225 else
226 throw CInvalidFormatEtcException( DV_E_FORMATETC );
229 //------------------------------------------------------------------------
231 //------------------------------------------------------------------------
233 //inline
234 void SAL_CALL CXTDataObject::renderUnicodeAndSetupStgMedium(
235 FORMATETC& fetc, STGMEDIUM& stgmedium )
237 DataFlavor aFlavor = formatEtcToDataFlavor( fetc );
239 Any aAny = m_XTransferable->getTransferData( aFlavor );
241 // unfortunately not all transferables fulfill the
242 // spec. an do throw an UnsupportedFlavorException
243 // so we must check the any
244 if ( !aAny.hasValue( ) )
246 OSL_FAIL( "XTransferable should throw an exception if ask for an unsupported flavor" );
247 throw UnsupportedFlavorException( );
250 OUString aText;
251 aAny >>= aText;
253 sal_uInt32 nBytesToTransfer = aText.getLength( ) * sizeof( sal_Unicode );
255 // to be sure there is an ending 0
256 sal_uInt32 nRequiredMemSize = nBytesToTransfer + sizeof( sal_Unicode );
258 renderDataAndSetupStgMedium(
259 reinterpret_cast< const sal_Int8* >( aText.getStr( ) ),
260 fetc,
261 nRequiredMemSize,
262 nBytesToTransfer,
263 stgmedium );
266 //------------------------------------------------------------------------
268 //------------------------------------------------------------------------
270 //inline
271 void SAL_CALL CXTDataObject::renderAnyDataAndSetupStgMedium(
272 FORMATETC& fetc, STGMEDIUM& stgmedium )
274 DataFlavor aFlavor = formatEtcToDataFlavor( fetc );
276 Any aAny = m_XTransferable->getTransferData( aFlavor );
278 // unfortunately not all transferables fulfill the
279 // spec. an do throw an UnsupportedFlavorException
280 // so we must check the any
281 if ( !aAny.hasValue( ) )
283 OSL_FAIL( "XTransferable should throw an exception if ask for an unsupported flavor" );
284 throw UnsupportedFlavorException( );
287 // unfortunately not all transferables fulfill the
288 // spec. an do throw an UnsupportedFlavorException
289 // so we must check the any
290 if ( !aAny.hasValue( ) )
291 throw UnsupportedFlavorException( );
293 Sequence< sal_Int8 > clipDataStream;
294 aAny >>= clipDataStream;
296 sal_uInt32 nRequiredMemSize = 0;
297 if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) )
298 nRequiredMemSize = sizeof( sal_Int8 ) * clipDataStream.getLength( ) + 1;
300 // prepare data for transmision
301 if ( CF_DIB == fetc.cfFormat )
302 clipDataStream = OOBmpToWinDIB( clipDataStream );
304 if ( CF_METAFILEPICT == fetc.cfFormat )
306 stgmedium.tymed = TYMED_MFPICT;
307 stgmedium.hMetaFilePict = OOMFPictToWinMFPict( clipDataStream );
308 stgmedium.pUnkForRelease = NULL;
310 else if( CF_ENHMETAFILE == fetc.cfFormat )
312 stgmedium.tymed = TYMED_ENHMF;
313 stgmedium.hMetaFilePict = OOMFPictToWinENHMFPict( clipDataStream );
314 stgmedium.pUnkForRelease = NULL;
316 else
317 renderDataAndSetupStgMedium(
318 clipDataStream.getArray( ),
319 fetc,
320 nRequiredMemSize,
321 clipDataStream.getLength( ),
322 stgmedium );
325 //------------------------------------------------------------------------
327 //------------------------------------------------------------------------
329 HRESULT SAL_CALL CXTDataObject::renderSynthesizedFormatAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
331 HRESULT hr = S_OK;
335 if ( CF_UNICODETEXT == fetc.cfFormat )
336 // the transferable seems to have only text
337 renderSynthesizedUnicodeAndSetupStgMedium( fetc, stgmedium );
338 else if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) )
339 // the transferable seems to have only unicode text
340 renderSynthesizedTextAndSetupStgMedium( fetc, stgmedium );
341 else
342 // the transferable seems to have only text/html
343 renderSynthesizedHtmlAndSetupStgMedium( fetc, stgmedium );
345 catch(UnsupportedFlavorException&)
347 hr = DV_E_FORMATETC;
349 catch( CInvalidFormatEtcException& )
351 OSL_FAIL( "Unexpected exception" );
353 catch( CStgTransferHelper::CStgTransferException& ex )
355 return translateStgExceptionCode( ex.m_hr );
357 catch(...)
359 hr = E_UNEXPECTED;
362 return hr;
365 //------------------------------------------------------------------------
366 // the transferable must have only text, so we will synthesize unicode text
367 //------------------------------------------------------------------------
369 void SAL_CALL CXTDataObject::renderSynthesizedUnicodeAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
371 OSL_ASSERT( CF_UNICODETEXT == fetc.cfFormat );
373 Any aAny = m_XTransferable->getTransferData( m_FormatRegistrar.getRegisteredTextFlavor( ) );
375 // unfortunately not all transferables fulfill the
376 // spec. an do throw an UnsupportedFlavorException
377 // so we must check the any
378 if ( !aAny.hasValue( ) )
380 OSL_FAIL( "XTransferable should throw an exception if ask for an unsupported flavor" );
381 throw UnsupportedFlavorException( );
384 Sequence< sal_Int8 > aText;
385 aAny >>= aText;
387 CStgTransferHelper stgTransfHelper;
389 MultiByteToWideCharEx(
390 m_FormatRegistrar.getRegisteredTextCodePage( ),
391 reinterpret_cast< char* >( aText.getArray( ) ),
392 aText.getLength( ),
393 stgTransfHelper );
395 setupStgMedium( fetc, stgTransfHelper, stgmedium );
398 //------------------------------------------------------------------------
399 // the transferable must have only unicode text so we will sythesize text
400 //------------------------------------------------------------------------
402 void SAL_CALL CXTDataObject::renderSynthesizedTextAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
404 OSL_ASSERT( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) );
406 DataFlavor aFlavor = formatEtcToDataFlavor(
407 m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) );
409 Any aAny = m_XTransferable->getTransferData( aFlavor );
411 // unfortunately not all transferables fulfill the
412 // spec. an do throw an UnsupportedFlavorException
413 // so we must check the any
414 if ( !aAny.hasValue( ) )
416 OSL_FAIL( "XTransferable should throw an exception if ask for an unsupported flavor" );
417 throw UnsupportedFlavorException( );
420 OUString aUnicodeText;
421 aAny >>= aUnicodeText;
423 CStgTransferHelper stgTransfHelper;
425 WideCharToMultiByteEx(
426 GetACP( ),
427 reinterpret_cast<LPCWSTR>( aUnicodeText.getStr( ) ),
428 aUnicodeText.getLength( ),
429 stgTransfHelper );
431 setupStgMedium( fetc, stgTransfHelper, stgmedium );
434 //------------------------------------------------------------------------
436 //------------------------------------------------------------------------
438 void SAL_CALL CXTDataObject::renderSynthesizedHtmlAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
440 OSL_ASSERT( m_DataFormatTranslator.isHTMLFormat( fetc.cfFormat ) );
442 DataFlavor aFlavor;
444 // creating a DataFlavor on the fly
445 aFlavor.MimeType = OUString("text/html");
446 aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
448 Any aAny = m_XTransferable->getTransferData( aFlavor );
450 // unfortunately not all transferables fulfill the
451 // spec. an do throw an UnsupportedFlavorException
452 // so we must check the any
453 if ( !aAny.hasValue( ) )
455 OSL_FAIL( "XTransferable should throw an exception if ask for an unsupported flavor" );
456 throw UnsupportedFlavorException( );
459 Sequence< sal_Int8 > aTextHtmlSequence;
460 aAny >>= aTextHtmlSequence;
462 Sequence< sal_Int8 > aHTMLFormatSequence = TextHtmlToHTMLFormat( aTextHtmlSequence );
464 sal_uInt32 nBytesToTransfer = aHTMLFormatSequence.getLength( );
466 renderDataAndSetupStgMedium(
467 reinterpret_cast< const sal_Int8* >( aHTMLFormatSequence.getArray( ) ),
468 fetc,
470 nBytesToTransfer,
471 stgmedium );
474 //------------------------------------------------------------------------
475 // IDataObject->EnumFormatEtc
476 //------------------------------------------------------------------------
478 STDMETHODIMP CXTDataObject::EnumFormatEtc(
479 DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
481 if ( NULL == ppenumFormatetc )
482 return E_INVALIDARG;
484 if ( DATADIR_SET == dwDirection )
485 return E_NOTIMPL;
487 *ppenumFormatetc = NULL;
489 InitializeFormatEtcContainer( );
491 HRESULT hr;
492 if ( DATADIR_GET == dwDirection )
494 *ppenumFormatetc = new CEnumFormatEtc( this, m_FormatEtcContainer );
495 static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( );
497 hr = S_OK;
499 else
500 hr = E_INVALIDARG;
502 return hr;
505 //------------------------------------------------------------------------
506 // IDataObject->QueryGetData
507 //------------------------------------------------------------------------
509 STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc )
511 if ( (NULL == pFormatetc) || IsBadReadPtr( pFormatetc, sizeof( FORMATETC ) ) )
512 return E_INVALIDARG;
514 InitializeFormatEtcContainer( );
516 return m_FormatEtcContainer.hasFormatEtc( *pFormatetc ) ? S_OK : S_FALSE;
519 //------------------------------------------------------------------------
520 // IDataObject->GetDataHere
521 //------------------------------------------------------------------------
523 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM )
525 return E_NOTIMPL;
528 //------------------------------------------------------------------------
529 // IDataObject->GetCanonicalFormatEtc
530 //------------------------------------------------------------------------
532 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC )
534 return E_NOTIMPL;
537 //------------------------------------------------------------------------
538 // IDataObject->SetData
539 //------------------------------------------------------------------------
541 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL )
543 return E_NOTIMPL;
546 //------------------------------------------------------------------------
547 // IDataObject->DAdvise
548 //------------------------------------------------------------------------
550 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * )
552 return E_NOTIMPL;
555 //------------------------------------------------------------------------
556 // IDataObject->DUnadvise
557 //------------------------------------------------------------------------
559 STDMETHODIMP CXTDataObject::DUnadvise( DWORD )
561 return E_NOTIMPL;
564 //------------------------------------------------------------------------
565 // IDataObject->EnumDAdvise
566 //------------------------------------------------------------------------
568 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * )
570 return E_NOTIMPL;
573 //------------------------------------------------------------------------
574 // for our convenience
575 //------------------------------------------------------------------------
577 CXTDataObject::operator IDataObject*( )
579 return static_cast< IDataObject* >( this );
582 //------------------------------------------------------------------------
584 //------------------------------------------------------------------------
586 inline
587 DataFlavor SAL_CALL CXTDataObject::formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) const
589 DataFlavor aFlavor;
591 if ( m_FormatRegistrar.hasSynthesizedLocale( ) )
592 aFlavor =
593 m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, m_FormatRegistrar.getSynthesizedLocale( ) );
594 else
595 aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc );
597 if ( !aFlavor.MimeType.getLength( ) )
598 throw UnsupportedFlavorException( );
600 return aFlavor;
603 //------------------------------------------------------------------------
605 //------------------------------------------------------------------------
607 inline
608 void CXTDataObject::validateFormatEtc( LPFORMATETC lpFormatEtc ) const
610 OSL_ASSERT( lpFormatEtc );
612 if ( lpFormatEtc->lindex != -1 )
613 throw CInvalidFormatEtcException( DV_E_LINDEX );
615 if ( !(lpFormatEtc->dwAspect & DVASPECT_CONTENT) &&
616 !(lpFormatEtc->dwAspect & DVASPECT_SHORTNAME) )
617 throw CInvalidFormatEtcException( DV_E_DVASPECT );
619 if ( !(lpFormatEtc->tymed & TYMED_HGLOBAL) &&
620 !(lpFormatEtc->tymed & TYMED_ISTREAM) &&
621 !(lpFormatEtc->tymed & TYMED_MFPICT) &&
622 !(lpFormatEtc->tymed & TYMED_ENHMF) )
623 throw CInvalidFormatEtcException( DV_E_TYMED );
625 if ( lpFormatEtc->cfFormat == CF_METAFILEPICT &&
626 !(lpFormatEtc->tymed & TYMED_MFPICT) )
627 throw CInvalidFormatEtcException( DV_E_TYMED );
629 if ( lpFormatEtc->cfFormat == CF_ENHMETAFILE &&
630 !(lpFormatEtc->tymed & TYMED_ENHMF) )
631 throw CInvalidFormatEtcException( DV_E_TYMED );
634 //------------------------------------------------------------------------
636 //------------------------------------------------------------------------
638 //inline
639 void SAL_CALL CXTDataObject::setupStgMedium( const FORMATETC& fetc,
640 CStgTransferHelper& stgTransHlp,
641 STGMEDIUM& stgmedium )
643 stgmedium.pUnkForRelease = NULL;
645 if ( fetc.cfFormat == CF_METAFILEPICT )
647 stgmedium.tymed = TYMED_MFPICT;
648 stgmedium.hMetaFilePict = static_cast< HMETAFILEPICT >( stgTransHlp.getHGlobal( ) );
650 else if ( fetc.cfFormat == CF_ENHMETAFILE )
652 stgmedium.tymed = TYMED_ENHMF;
653 stgmedium.hEnhMetaFile = static_cast< HENHMETAFILE >( stgTransHlp.getHGlobal( ) );
655 else if ( fetc.tymed & TYMED_HGLOBAL )
657 stgmedium.tymed = TYMED_HGLOBAL;
658 stgmedium.hGlobal = stgTransHlp.getHGlobal( );
660 else if ( fetc.tymed & TYMED_ISTREAM )
662 stgmedium.tymed = TYMED_ISTREAM;
663 stgTransHlp.getIStream( &stgmedium.pstm );
665 else
666 OSL_ASSERT( sal_False );
669 //------------------------------------------------------------------------
671 //------------------------------------------------------------------------
673 inline
674 void SAL_CALL CXTDataObject::invalidateStgMedium( STGMEDIUM& stgmedium ) const
676 stgmedium.tymed = TYMED_NULL;
679 //------------------------------------------------------------------------
681 //------------------------------------------------------------------------
683 inline
684 HRESULT SAL_CALL CXTDataObject::translateStgExceptionCode( HRESULT hr ) const
686 HRESULT hrTransl;
688 switch( hr )
690 case STG_E_MEDIUMFULL:
691 hrTransl = hr;
692 break;
694 default:
695 hrTransl = E_UNEXPECTED;
696 break;
699 return hrTransl;
702 //------------------------------------------------------------------------
704 //------------------------------------------------------------------------
706 inline void SAL_CALL CXTDataObject::InitializeFormatEtcContainer( )
708 if ( !m_bFormatEtcContainerInitialized )
710 m_FormatRegistrar.RegisterFormats( m_XTransferable, m_FormatEtcContainer );
711 m_bFormatEtcContainerInitialized = sal_True;
715 //============================================================================
716 // CEnumFormatEtc
717 //============================================================================
719 //----------------------------------------------------------------------------
720 // ctor
721 //----------------------------------------------------------------------------
723 CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN lpUnkOuter, const CFormatEtcContainer& aFormatEtcContainer ) :
724 m_nRefCnt( 0 ),
725 m_lpUnkOuter( lpUnkOuter ),
726 m_FormatEtcContainer( aFormatEtcContainer )
728 Reset( );
731 //----------------------------------------------------------------------------
732 // IUnknown->QueryInterface
733 //----------------------------------------------------------------------------
735 STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject )
737 if ( NULL == ppvObject )
738 return E_INVALIDARG;
740 HRESULT hr = E_NOINTERFACE;
742 *ppvObject = NULL;
744 if ( ( __uuidof( IUnknown ) == iid ) ||
745 ( __uuidof( IEnumFORMATETC ) == iid ) )
747 *ppvObject = static_cast< IUnknown* >( this );
748 static_cast< LPUNKNOWN >( *ppvObject )->AddRef( );
749 hr = S_OK;
752 return hr;
755 //----------------------------------------------------------------------------
756 // IUnknown->AddRef
757 //----------------------------------------------------------------------------
759 STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( )
761 // keep the dataobject alive
762 m_lpUnkOuter->AddRef( );
763 return InterlockedIncrement( &m_nRefCnt );
766 //----------------------------------------------------------------------------
767 // IUnknown->Release
768 //----------------------------------------------------------------------------
770 STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( )
772 // release the outer dataobject
773 m_lpUnkOuter->Release( );
775 ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt );
776 if ( 0 == nRefCnt )
777 delete this;
779 return nRefCnt;
782 //----------------------------------------------------------------------------
783 // IEnumFORMATETC->Next
784 //----------------------------------------------------------------------------
786 STDMETHODIMP CEnumFormatEtc::Next( ULONG nRequested, LPFORMATETC lpDest, ULONG* lpFetched )
788 if ( ( nRequested < 1 ) ||
789 (( nRequested > 1 ) && ( NULL == lpFetched )) ||
790 IsBadWritePtr( lpDest, sizeof( FORMATETC ) * nRequested ) )
791 return E_INVALIDARG;
793 sal_uInt32 nFetched = m_FormatEtcContainer.nextFormatEtc( lpDest, nRequested );
795 if ( NULL != lpFetched )
796 *lpFetched = nFetched;
798 return (nFetched == nRequested) ? S_OK : S_FALSE;
801 //----------------------------------------------------------------------------
802 // IEnumFORMATETC->Skip
803 //----------------------------------------------------------------------------
805 STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt )
807 return m_FormatEtcContainer.skipFormatEtc( celt ) ? S_OK : S_FALSE;
810 //----------------------------------------------------------------------------
811 // IEnumFORMATETC->Reset
812 //----------------------------------------------------------------------------
814 STDMETHODIMP CEnumFormatEtc::Reset( )
816 m_FormatEtcContainer.beginEnumFormatEtc( );
817 return S_OK;
820 //----------------------------------------------------------------------------
821 // IEnumFORMATETC->Clone
822 //----------------------------------------------------------------------------
824 STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum )
826 if ( NULL == ppenum )
827 return E_INVALIDARG;
829 *ppenum = new CEnumFormatEtc( m_lpUnkOuter, m_FormatEtcContainer );
830 static_cast< LPUNKNOWN >( *ppenum )->AddRef( );
832 return S_OK;
835 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */