1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dtrans.hxx"
30 
31 //------------------------------------------------------------------------
32 // includes
33 //------------------------------------------------------------------------
34 #include <osl/diagnose.h>
35 
36 #ifndef _TXDATAOBJECT_HXX_
37 #include "XTDataObject.hxx"
38 #endif
39 #include <com/sun/star/datatransfer/DataFlavor.hpp>
40 #include "..\misc\ImplHelper.hxx"
41 #include "DTransHelper.hxx"
42 #include "TxtCnvtHlp.hxx"
43 #include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp>
44 #include "FmtFilter.hxx"
45 
46 #if defined _MSC_VER
47 #pragma warning(push,1)
48 #pragma warning(disable:4917)
49 #endif
50 #include <windows.h>
51 #include <shlobj.h>
52 #if defined _MSC_VER
53 #pragma warning(pop)
54 #endif
55 
56 #ifdef __MINGW32__
57 #define __uuidof(I) IID_##I
58 #endif
59 
60 //------------------------------------------------------------------------
61 // namespace directives
62 //------------------------------------------------------------------------
63 
64 using namespace com::sun::star::datatransfer;
65 using namespace com::sun::star::datatransfer::clipboard;
66 using namespace com::sun::star::uno;
67 using namespace com::sun::star::lang;
68 using namespace rtl;
69 
70 //------------------------------------------------------------------------
71 // a helper class that will be thrown by the function validateFormatEtc
72 //------------------------------------------------------------------------
73 
74 class CInvalidFormatEtcException
75 {
76 public:
77 	HRESULT m_hr;
78 	CInvalidFormatEtcException( HRESULT hr ) : m_hr( hr ) {};
79 };
80 
81 //------------------------------------------------------------------------
82 // ctor
83 //------------------------------------------------------------------------
84 
85 CXTDataObject::CXTDataObject( const Reference< XMultiServiceFactory >& aServiceManager,
86 							  const Reference< XTransferable >& aXTransferable ) :
87 	m_nRefCnt( 0 ),
88 	m_SrvMgr( aServiceManager ),
89 	m_XTransferable( aXTransferable ),
90 	m_DataFormatTranslator( aServiceManager ),
91     m_bFormatEtcContainerInitialized( sal_False ),
92 	m_FormatRegistrar( m_SrvMgr, m_DataFormatTranslator )
93 {
94 }
95 
96 //------------------------------------------------------------------------
97 // IUnknown->QueryInterface
98 //------------------------------------------------------------------------
99 
100 STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject )
101 {
102 	if ( NULL == ppvObject )
103 		return E_INVALIDARG;
104 
105 	HRESULT hr = E_NOINTERFACE;
106 
107 	*ppvObject = NULL;
108 	if ( ( __uuidof( IUnknown ) == iid ) ||
109 		 ( __uuidof( IDataObject ) == iid ) )
110 	{
111 		*ppvObject = static_cast< IUnknown* >( this );
112 		( (LPUNKNOWN)*ppvObject )->AddRef( );
113 		hr = S_OK;
114 	}
115 
116 	return hr;
117 }
118 
119 //------------------------------------------------------------------------
120 // IUnknown->AddRef
121 //------------------------------------------------------------------------
122 
123 STDMETHODIMP_(ULONG) CXTDataObject::AddRef( )
124 {
125 	return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
126 }
127 
128 //------------------------------------------------------------------------
129 // IUnknown->Release
130 //------------------------------------------------------------------------
131 
132 STDMETHODIMP_(ULONG) CXTDataObject::Release( )
133 {
134 	ULONG nRefCnt =
135 		static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) );
136 
137 	if ( 0 == nRefCnt )
138 		delete this;
139 
140 	return nRefCnt;
141 }
142 
143 //------------------------------------------------------------------------
144 //
145 //------------------------------------------------------------------------
146 
147 STDMETHODIMP CXTDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
148 {
149 	if ( !(pFormatetc && pmedium) )
150 		return E_INVALIDARG;
151 
152 	try
153 	{
154 		// prepare data transfer
155 		invalidateStgMedium( *pmedium );
156 		validateFormatEtc( pFormatetc );
157 
158 		// handle locale request, because locale is a artificial format for us
159 		if ( CF_LOCALE == pFormatetc->cfFormat )
160 			renderLocaleAndSetupStgMedium( *pFormatetc, *pmedium );
161 		else if ( CF_UNICODETEXT == pFormatetc->cfFormat )
162 			renderUnicodeAndSetupStgMedium( *pFormatetc, *pmedium );
163 		else
164 			renderAnyDataAndSetupStgMedium( *pFormatetc, *pmedium );
165 	}
166 	catch(UnsupportedFlavorException&)
167 	{
168 		HRESULT hr = DV_E_FORMATETC;
169 
170 		if ( m_FormatRegistrar.isSynthesizeableFormat( *pFormatetc ) )
171 			hr = renderSynthesizedFormatAndSetupStgMedium( *pFormatetc, *pmedium );
172 
173 		return hr;
174 	}
175 	catch( CInvalidFormatEtcException& ex )
176 	{
177 		return ex.m_hr;
178 	}
179 	catch( CStgTransferHelper::CStgTransferException& ex )
180 	{
181 		return translateStgExceptionCode( ex.m_hr );
182 	}
183 	catch(...)
184 	{
185 		return E_UNEXPECTED;
186 	}
187 
188 	return S_OK;
189 }
190 
191 //------------------------------------------------------------------------
192 //
193 //------------------------------------------------------------------------
194 
195 // inline
196 void SAL_CALL CXTDataObject::renderDataAndSetupStgMedium(
197 	const sal_Int8* lpStorage, const FORMATETC& fetc, sal_uInt32 nInitStgSize,
198 	sal_uInt32 nBytesToTransfer, STGMEDIUM& stgmedium )
199 {
200 	OSL_PRECOND( !nInitStgSize || nInitStgSize && (nInitStgSize >= nBytesToTransfer),
201 		         "Memory size less than number of bytes to transfer" );
202 
203 	CStgTransferHelper stgTransfHelper( AUTO_INIT );
204 
205 	// setup storage size
206 	if ( nInitStgSize > 0 )
207 		stgTransfHelper.init( nInitStgSize, GHND );
208 
209 #if OSL_DEBUG_LEVEL > 0
210     sal_uInt32 nBytesWritten = 0;
211     stgTransfHelper.write( lpStorage, nBytesToTransfer, &nBytesWritten );
212     OSL_ASSERT( nBytesWritten == nBytesToTransfer );
213 #else
214     stgTransfHelper.write( lpStorage, nBytesToTransfer );
215 #endif
216 
217 	setupStgMedium( fetc, stgTransfHelper, stgmedium );
218 }
219 
220 //------------------------------------------------------------------------
221 //
222 //------------------------------------------------------------------------
223 
224 //inline
225 void SAL_CALL CXTDataObject::renderLocaleAndSetupStgMedium(
226 	FORMATETC& fetc, STGMEDIUM& stgmedium )
227 {
228 	if ( m_FormatRegistrar.hasSynthesizedLocale( ) )
229 	{
230 		LCID lcid = m_FormatRegistrar.getSynthesizedLocale( );
231 		renderDataAndSetupStgMedium(
232 			reinterpret_cast< sal_Int8* >( &lcid ),
233 			fetc,
234 			0,
235 			sizeof( LCID ),
236 			stgmedium );
237 	}
238 	else
239 		throw CInvalidFormatEtcException( DV_E_FORMATETC );
240 }
241 
242 //------------------------------------------------------------------------
243 //
244 //------------------------------------------------------------------------
245 
246 //inline
247 void SAL_CALL CXTDataObject::renderUnicodeAndSetupStgMedium(
248 	FORMATETC& fetc, STGMEDIUM& stgmedium )
249 {
250 	DataFlavor aFlavor = formatEtcToDataFlavor( fetc );
251 
252 	Any aAny = m_XTransferable->getTransferData( aFlavor );
253 
254 	// unfortunately not all transferables fulfill the
255 	// spec. an do throw an UnsupportedFlavorException
256 	// so we must check the any
257 	if ( !aAny.hasValue( ) )
258 	{
259 		OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
260 		throw UnsupportedFlavorException( );
261 	}
262 
263 	OUString aText;
264 	aAny >>= aText;
265 
266 	sal_uInt32 nBytesToTransfer = aText.getLength( ) * sizeof( sal_Unicode );
267 
268 	// to be sure there is an ending 0
269 	sal_uInt32 nRequiredMemSize = nBytesToTransfer + sizeof( sal_Unicode );
270 
271 	renderDataAndSetupStgMedium(
272 		reinterpret_cast< const sal_Int8* >( aText.getStr( ) ),
273 		fetc,
274 		nRequiredMemSize,
275 		nBytesToTransfer,
276 		stgmedium );
277 }
278 
279 //------------------------------------------------------------------------
280 //
281 //------------------------------------------------------------------------
282 
283 //inline
284 void SAL_CALL CXTDataObject::renderAnyDataAndSetupStgMedium(
285 	FORMATETC& fetc, STGMEDIUM& stgmedium )
286 {
287 	DataFlavor aFlavor = formatEtcToDataFlavor( fetc );
288 
289 	Any aAny = m_XTransferable->getTransferData( aFlavor );
290 
291 	// unfortunately not all transferables fulfill the
292 	// spec. an do throw an UnsupportedFlavorException
293 	// so we must check the any
294 	if ( !aAny.hasValue( ) )
295 	{
296 		OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
297 		throw UnsupportedFlavorException( );
298 	}
299 
300 	// unfortunately not all transferables fulfill the
301 	// spec. an do throw an UnsupportedFlavorException
302 	// so we must check the any
303 	if ( !aAny.hasValue( ) )
304 		throw UnsupportedFlavorException( );
305 
306 	Sequence< sal_Int8 > clipDataStream;
307 	aAny >>= clipDataStream;
308 
309 	sal_uInt32 nRequiredMemSize = 0;
310 	if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) )
311 		nRequiredMemSize = sizeof( sal_Int8 ) * clipDataStream.getLength( ) + 1;
312 
313 	// prepare data for transmision
314 	if ( CF_DIB == fetc.cfFormat )
315 		clipDataStream = OOBmpToWinDIB( clipDataStream );
316 
317 	if ( CF_METAFILEPICT == fetc.cfFormat )
318 	{
319 		stgmedium.tymed          = TYMED_MFPICT;
320 		stgmedium.hMetaFilePict  = OOMFPictToWinMFPict( clipDataStream );
321 		stgmedium.pUnkForRelease = NULL;
322 	}
323 	else if( CF_ENHMETAFILE	== fetc.cfFormat )
324 	{
325 		stgmedium.tymed          = TYMED_ENHMF;
326 		stgmedium.hMetaFilePict  = OOMFPictToWinENHMFPict( clipDataStream );
327 		stgmedium.pUnkForRelease = NULL;
328 	}
329 	else
330 		renderDataAndSetupStgMedium(
331 			clipDataStream.getArray( ),
332 			fetc,
333 			nRequiredMemSize,
334 			clipDataStream.getLength( ),
335 			stgmedium );
336 }
337 
338 //------------------------------------------------------------------------
339 //
340 //------------------------------------------------------------------------
341 
342 HRESULT SAL_CALL CXTDataObject::renderSynthesizedFormatAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
343 {
344 	HRESULT hr = S_OK;
345 
346 	try
347 	{
348 		if ( CF_UNICODETEXT == fetc.cfFormat )
349 			// the transferable seems to have only text
350 			renderSynthesizedUnicodeAndSetupStgMedium( fetc, stgmedium );
351 		else if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) )
352 			// the transferable seems to have only unicode text
353 			renderSynthesizedTextAndSetupStgMedium( fetc, stgmedium );
354 		else
355 			// the transferable seems to have only text/html
356 			renderSynthesizedHtmlAndSetupStgMedium( fetc, stgmedium );
357 	}
358 	catch(UnsupportedFlavorException&)
359 	{
360 		hr = DV_E_FORMATETC;
361 	}
362 	catch( CInvalidFormatEtcException& )
363 	{
364 		OSL_ENSURE( sal_False, "Unexpected exception" );
365 	}
366 	catch( CStgTransferHelper::CStgTransferException& ex )
367 	{
368 		return translateStgExceptionCode( ex.m_hr );
369 	}
370 	catch(...)
371 	{
372 		hr = E_UNEXPECTED;
373 	}
374 
375 	return hr;
376 }
377 
378 //------------------------------------------------------------------------
379 // the transferable must have only text, so we will synthesize unicode text
380 //------------------------------------------------------------------------
381 
382 void SAL_CALL CXTDataObject::renderSynthesizedUnicodeAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
383 {
384 	OSL_ASSERT( CF_UNICODETEXT == fetc.cfFormat );
385 
386 	Any aAny = m_XTransferable->getTransferData( m_FormatRegistrar.getRegisteredTextFlavor( ) );
387 
388 	// unfortunately not all transferables fulfill the
389 	// spec. an do throw an UnsupportedFlavorException
390 	// so we must check the any
391 	if ( !aAny.hasValue( ) )
392 	{
393 		OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
394 		throw UnsupportedFlavorException( );
395 	}
396 
397 	Sequence< sal_Int8 > aText;
398 	aAny >>= aText;
399 
400 	CStgTransferHelper stgTransfHelper;
401 
402 	MultiByteToWideCharEx(
403 		m_FormatRegistrar.getRegisteredTextCodePage( ),
404 		reinterpret_cast< char* >( aText.getArray( ) ),
405 		aText.getLength( ),
406 		stgTransfHelper );
407 
408 	setupStgMedium( fetc, stgTransfHelper, stgmedium );
409 }
410 
411 //------------------------------------------------------------------------
412 // the transferable must have only unicode text so we will sythesize text
413 //------------------------------------------------------------------------
414 
415 void SAL_CALL CXTDataObject::renderSynthesizedTextAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
416 {
417 	OSL_ASSERT( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) );
418 
419 	DataFlavor aFlavor = formatEtcToDataFlavor(
420 		m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) );
421 
422 	Any aAny = m_XTransferable->getTransferData( aFlavor );
423 
424 	// unfortunately not all transferables fulfill the
425 	// spec. an do throw an UnsupportedFlavorException
426 	// so we must check the any
427 	if ( !aAny.hasValue( ) )
428 	{
429 		OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
430 		throw UnsupportedFlavorException( );
431 	}
432 
433 	OUString aUnicodeText;
434 	aAny >>= aUnicodeText;
435 
436 	CStgTransferHelper stgTransfHelper;
437 
438 	WideCharToMultiByteEx(
439 		GetACP( ),
440 		reinterpret_cast<LPCWSTR>( aUnicodeText.getStr( ) ),
441 		aUnicodeText.getLength( ),
442 		stgTransfHelper );
443 
444 	setupStgMedium( fetc, stgTransfHelper, stgmedium );
445 }
446 
447 //------------------------------------------------------------------------
448 //
449 //------------------------------------------------------------------------
450 
451 void SAL_CALL CXTDataObject::renderSynthesizedHtmlAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
452 {
453 	OSL_ASSERT( m_DataFormatTranslator.isHTMLFormat( fetc.cfFormat ) );
454 
455 	DataFlavor aFlavor;
456 
457 	// creating a DataFlavor on the fly
458 	aFlavor.MimeType = OUString::createFromAscii( "text/html" );
459 	aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
460 
461 	Any aAny = m_XTransferable->getTransferData( aFlavor );
462 
463 	// unfortunately not all transferables fulfill the
464 	// spec. an do throw an UnsupportedFlavorException
465 	// so we must check the any
466 	if ( !aAny.hasValue( ) )
467 	{
468 		OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
469 		throw UnsupportedFlavorException( );
470 	}
471 
472 	Sequence< sal_Int8 > aTextHtmlSequence;
473 	aAny >>= aTextHtmlSequence;
474 
475 	Sequence< sal_Int8 > aHTMLFormatSequence = TextHtmlToHTMLFormat( aTextHtmlSequence );
476 
477 	sal_uInt32 nBytesToTransfer = aHTMLFormatSequence.getLength( );
478 
479 	renderDataAndSetupStgMedium(
480 		reinterpret_cast< const sal_Int8* >( aHTMLFormatSequence.getArray( ) ),
481 		fetc,
482 		0,
483 		nBytesToTransfer,
484 		stgmedium );
485 }
486 
487 //------------------------------------------------------------------------
488 // IDataObject->EnumFormatEtc
489 //------------------------------------------------------------------------
490 
491 STDMETHODIMP CXTDataObject::EnumFormatEtc(
492 	DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
493 {
494 	if ( NULL == ppenumFormatetc )
495 		return E_INVALIDARG;
496 
497 	if ( DATADIR_SET == dwDirection )
498 		return E_NOTIMPL;
499 
500 	*ppenumFormatetc = NULL;
501 
502     InitializeFormatEtcContainer( );
503 
504 	HRESULT hr;
505 	if ( DATADIR_GET == dwDirection )
506 	{
507 		*ppenumFormatetc = new CEnumFormatEtc( this, m_FormatEtcContainer );
508 		if ( NULL != *ppenumFormatetc )
509 			static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( );
510 
511 		hr = ( NULL != *ppenumFormatetc ) ? S_OK : E_OUTOFMEMORY;
512 	}
513 	else
514 		hr = E_INVALIDARG;
515 
516 	return hr;
517 }
518 
519 //------------------------------------------------------------------------
520 // IDataObject->QueryGetData
521 //------------------------------------------------------------------------
522 
523 STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc )
524 {
525 	if ( (NULL == pFormatetc) || IsBadReadPtr( pFormatetc, sizeof( FORMATETC ) ) )
526 		return E_INVALIDARG;
527 
528     InitializeFormatEtcContainer( );
529 
530 	return m_FormatEtcContainer.hasFormatEtc( *pFormatetc ) ? S_OK : S_FALSE;
531 }
532 
533 //------------------------------------------------------------------------
534 // IDataObject->GetDataHere
535 //------------------------------------------------------------------------
536 
537 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM )
538 {
539 	return E_NOTIMPL;
540 }
541 
542 //------------------------------------------------------------------------
543 // IDataObject->GetCanonicalFormatEtc
544 //------------------------------------------------------------------------
545 
546 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC )
547 {
548 	return E_NOTIMPL;
549 }
550 
551 //------------------------------------------------------------------------
552 // IDataObject->SetData
553 //------------------------------------------------------------------------
554 
555 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL )
556 {
557 	return E_NOTIMPL;
558 }
559 
560 //------------------------------------------------------------------------
561 // IDataObject->DAdvise
562 //------------------------------------------------------------------------
563 
564 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * )
565 {
566 	return E_NOTIMPL;
567 }
568 
569 //------------------------------------------------------------------------
570 // IDataObject->DUnadvise
571 //------------------------------------------------------------------------
572 
573 STDMETHODIMP CXTDataObject::DUnadvise( DWORD )
574 {
575 	return E_NOTIMPL;
576 }
577 
578 //------------------------------------------------------------------------
579 // IDataObject->EnumDAdvise
580 //------------------------------------------------------------------------
581 
582 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * )
583 {
584 	return E_NOTIMPL;
585 }
586 
587 //------------------------------------------------------------------------
588 // for our convenience
589 //------------------------------------------------------------------------
590 
591 CXTDataObject::operator IDataObject*( )
592 {
593 	return static_cast< IDataObject* >( this );
594 }
595 
596 //------------------------------------------------------------------------
597 //
598 //------------------------------------------------------------------------
599 
600 inline
601 DataFlavor SAL_CALL CXTDataObject::formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) const
602 {
603 	DataFlavor aFlavor;
604 
605 	if ( m_FormatRegistrar.hasSynthesizedLocale( ) )
606 		aFlavor =
607 			m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, m_FormatRegistrar.getSynthesizedLocale( ) );
608 	else
609 		aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc );
610 
611 	if ( !aFlavor.MimeType.getLength( ) )
612 		throw UnsupportedFlavorException( );
613 
614 	return aFlavor;
615 }
616 
617 //------------------------------------------------------------------------
618 //
619 //------------------------------------------------------------------------
620 
621 inline
622 void CXTDataObject::validateFormatEtc( LPFORMATETC lpFormatEtc ) const
623 {
624 	OSL_ASSERT( lpFormatEtc );
625 
626 	if ( lpFormatEtc->lindex != -1 )
627 		throw CInvalidFormatEtcException( DV_E_LINDEX );
628 
629 	if ( !(lpFormatEtc->dwAspect & DVASPECT_CONTENT) &&
630 		 !(lpFormatEtc->dwAspect & DVASPECT_SHORTNAME) )
631 		throw CInvalidFormatEtcException( DV_E_DVASPECT );
632 
633 	if ( !(lpFormatEtc->tymed & TYMED_HGLOBAL) &&
634 		 !(lpFormatEtc->tymed & TYMED_ISTREAM) &&
635 		 !(lpFormatEtc->tymed & TYMED_MFPICT) &&
636 		 !(lpFormatEtc->tymed & TYMED_ENHMF) )
637 		throw CInvalidFormatEtcException( DV_E_TYMED );
638 
639 	if ( lpFormatEtc->cfFormat == CF_METAFILEPICT &&
640 		 !(lpFormatEtc->tymed & TYMED_MFPICT) )
641 		throw CInvalidFormatEtcException( DV_E_TYMED );
642 
643 	if ( lpFormatEtc->cfFormat == CF_ENHMETAFILE &&
644 		 !(lpFormatEtc->tymed & TYMED_ENHMF) )
645 		throw CInvalidFormatEtcException( DV_E_TYMED );
646 }
647 
648 //------------------------------------------------------------------------
649 //
650 //------------------------------------------------------------------------
651 
652 //inline
653 void SAL_CALL CXTDataObject::setupStgMedium( const FORMATETC& fetc,
654 											 CStgTransferHelper& stgTransHlp,
655 											 STGMEDIUM& stgmedium )
656 {
657 	stgmedium.pUnkForRelease = NULL;
658 
659 	if ( fetc.cfFormat == CF_METAFILEPICT )
660 	{
661 		stgmedium.tymed         = TYMED_MFPICT;
662 		stgmedium.hMetaFilePict = static_cast< HMETAFILEPICT >( stgTransHlp.getHGlobal( ) );
663 	}
664 	else if ( fetc.cfFormat == CF_ENHMETAFILE )
665 	{
666 		stgmedium.tymed        = TYMED_ENHMF;
667 		stgmedium.hEnhMetaFile = static_cast< HENHMETAFILE >( stgTransHlp.getHGlobal( ) );
668 	}
669 	else if ( fetc.tymed & TYMED_HGLOBAL )
670 	{
671 		stgmedium.tymed   = TYMED_HGLOBAL;
672 		stgmedium.hGlobal = stgTransHlp.getHGlobal( );
673 	}
674 	else if ( fetc.tymed & TYMED_ISTREAM )
675 	{
676 		stgmedium.tymed = TYMED_ISTREAM;
677 		stgTransHlp.getIStream( &stgmedium.pstm );
678 	}
679 	else
680 		OSL_ASSERT( sal_False );
681 }
682 
683 //------------------------------------------------------------------------
684 //
685 //------------------------------------------------------------------------
686 
687 inline
688 void SAL_CALL CXTDataObject::invalidateStgMedium( STGMEDIUM& stgmedium ) const
689 {
690 	stgmedium.tymed = TYMED_NULL;
691 }
692 
693 //------------------------------------------------------------------------
694 //
695 //------------------------------------------------------------------------
696 
697 inline
698 HRESULT SAL_CALL CXTDataObject::translateStgExceptionCode( HRESULT hr ) const
699 {
700 	HRESULT hrTransl;
701 
702 	switch( hr )
703 	{
704 	case STG_E_MEDIUMFULL:
705 		hrTransl = hr;
706 		break;
707 
708 	default:
709 		hrTransl = E_UNEXPECTED;
710 		break;
711 	}
712 
713 	return hrTransl;
714 }
715 
716 //------------------------------------------------------------------------
717 //
718 //------------------------------------------------------------------------
719 
720 inline void SAL_CALL CXTDataObject::InitializeFormatEtcContainer( )
721 {
722     if ( !m_bFormatEtcContainerInitialized )
723     {
724         m_FormatRegistrar.RegisterFormats( m_XTransferable, m_FormatEtcContainer );
725         m_bFormatEtcContainerInitialized = sal_True;
726     }
727 }
728 
729 //============================================================================
730 // CEnumFormatEtc
731 //============================================================================
732 
733 //----------------------------------------------------------------------------
734 // ctor
735 //----------------------------------------------------------------------------
736 
737 CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN lpUnkOuter, const CFormatEtcContainer& aFormatEtcContainer ) :
738 	m_nRefCnt( 0 ),
739 	m_lpUnkOuter( lpUnkOuter ),
740 	m_FormatEtcContainer( aFormatEtcContainer )
741 {
742 	Reset( );
743 }
744 
745 //----------------------------------------------------------------------------
746 // IUnknown->QueryInterface
747 //----------------------------------------------------------------------------
748 
749 STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject )
750 {
751 	if ( NULL == ppvObject )
752 		return E_INVALIDARG;
753 
754 	HRESULT hr = E_NOINTERFACE;
755 
756 	*ppvObject = NULL;
757 
758 	if ( ( __uuidof( IUnknown ) == iid ) ||
759 		 ( __uuidof( IEnumFORMATETC ) == iid ) )
760 	{
761 		*ppvObject = static_cast< IUnknown* >( this );
762 		static_cast< LPUNKNOWN >( *ppvObject )->AddRef( );
763 		hr = S_OK;
764 	}
765 
766 	return hr;
767 }
768 
769 //----------------------------------------------------------------------------
770 // IUnknown->AddRef
771 //----------------------------------------------------------------------------
772 
773 STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( )
774 {
775 	// keep the dataobject alive
776 	m_lpUnkOuter->AddRef( );
777 	return InterlockedIncrement( &m_nRefCnt );
778 }
779 
780 //----------------------------------------------------------------------------
781 // IUnknown->Release
782 //----------------------------------------------------------------------------
783 
784 STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( )
785 {
786 	// release the outer dataobject
787 	m_lpUnkOuter->Release( );
788 
789 	ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt );
790 	if ( 0 == nRefCnt )
791 		delete this;
792 
793 	return nRefCnt;
794 }
795 
796 //----------------------------------------------------------------------------
797 // IEnumFORMATETC->Next
798 //----------------------------------------------------------------------------
799 
800 STDMETHODIMP CEnumFormatEtc::Next( ULONG nRequested, LPFORMATETC lpDest, ULONG* lpFetched )
801 {
802 	if ( ( nRequested < 1 ) ||
803 		 (( nRequested > 1 ) && ( NULL == lpFetched )) ||
804 		 IsBadWritePtr( lpDest, sizeof( FORMATETC ) * nRequested ) )
805 		return E_INVALIDARG;
806 
807 	sal_uInt32 nFetched = m_FormatEtcContainer.nextFormatEtc( lpDest, nRequested );
808 
809 	if ( NULL != lpFetched )
810 		*lpFetched = nFetched;
811 
812 	return (nFetched == nRequested) ? S_OK : S_FALSE;
813 }
814 
815 //----------------------------------------------------------------------------
816 // IEnumFORMATETC->Skip
817 //----------------------------------------------------------------------------
818 
819 STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt )
820 {
821 	return m_FormatEtcContainer.skipFormatEtc( celt ) ? S_OK : S_FALSE;
822 }
823 
824 //----------------------------------------------------------------------------
825 // IEnumFORMATETC->Reset
826 //----------------------------------------------------------------------------
827 
828 STDMETHODIMP CEnumFormatEtc::Reset( )
829 {
830 	m_FormatEtcContainer.beginEnumFormatEtc( );
831 	return S_OK;
832 }
833 
834 //----------------------------------------------------------------------------
835 // IEnumFORMATETC->Clone
836 //----------------------------------------------------------------------------
837 
838 STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum )
839 {
840 	if ( NULL == ppenum )
841 		return E_INVALIDARG;
842 
843 	*ppenum = new CEnumFormatEtc( m_lpUnkOuter, m_FormatEtcContainer );
844 	if ( NULL != ppenum )
845 		static_cast< LPUNKNOWN >( *ppenum )->AddRef( );
846 
847 	return ( NULL != *ppenum ) ? S_OK : E_OUTOFMEMORY;
848 }
849