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