xref: /AOO41X/main/dtrans/source/win32/dtobj/XTDataObject.cxx (revision 5443dcac4da55ae8863c5c80e8907938642a7f1b)
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_DIBV5 == fetc.cfFormat || CF_DIB == fetc.cfFormat )
311     {
312 #ifdef DBG_UTIL
313         if(CF_DIBV5 == fetc.cfFormat)
314         {
315             OSL_ENSURE(clipDataStream.getLength( ) > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPV5HEADER)), "Wrong size on CF_DIBV5 data (!)");
316         }
317         else // CF_DIB == fetc.cfFormat
318         {
319             OSL_ENSURE(clipDataStream.getLength( ) > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)), "Wrong size on CF_DIB data (!)");
320         }
321 #endif
322 
323         // remove BITMAPFILEHEADER
324         clipDataStream = OOBmpToWinDIB( clipDataStream );
325     }
326 
327     if ( CF_METAFILEPICT == fetc.cfFormat )
328     {
329         stgmedium.tymed          = TYMED_MFPICT;
330         stgmedium.hMetaFilePict  = OOMFPictToWinMFPict( clipDataStream );
331         stgmedium.pUnkForRelease = NULL;
332     }
333     else if( CF_ENHMETAFILE == fetc.cfFormat )
334     {
335         stgmedium.tymed          = TYMED_ENHMF;
336         stgmedium.hMetaFilePict  = OOMFPictToWinENHMFPict( clipDataStream );
337         stgmedium.pUnkForRelease = NULL;
338     }
339     else
340         renderDataAndSetupStgMedium(
341             clipDataStream.getArray( ),
342             fetc,
343             nRequiredMemSize,
344             clipDataStream.getLength( ),
345             stgmedium );
346 }
347 
348 //------------------------------------------------------------------------
349 //
350 //------------------------------------------------------------------------
351 
352 HRESULT SAL_CALL CXTDataObject::renderSynthesizedFormatAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
353 {
354     HRESULT hr = S_OK;
355 
356     try
357     {
358         if ( CF_UNICODETEXT == fetc.cfFormat )
359             // the transferable seems to have only text
360             renderSynthesizedUnicodeAndSetupStgMedium( fetc, stgmedium );
361         else if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) )
362             // the transferable seems to have only unicode text
363             renderSynthesizedTextAndSetupStgMedium( fetc, stgmedium );
364         else
365             // the transferable seems to have only text/html
366             renderSynthesizedHtmlAndSetupStgMedium( fetc, stgmedium );
367     }
368     catch(UnsupportedFlavorException&)
369     {
370         hr = DV_E_FORMATETC;
371     }
372     catch( CInvalidFormatEtcException& )
373     {
374         OSL_ENSURE( sal_False, "Unexpected exception" );
375     }
376     catch( CStgTransferHelper::CStgTransferException& ex )
377     {
378         return translateStgExceptionCode( ex.m_hr );
379     }
380     catch(...)
381     {
382         hr = E_UNEXPECTED;
383     }
384 
385     return hr;
386 }
387 
388 //------------------------------------------------------------------------
389 // the transferable must have only text, so we will synthesize unicode text
390 //------------------------------------------------------------------------
391 
392 void SAL_CALL CXTDataObject::renderSynthesizedUnicodeAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
393 {
394     OSL_ASSERT( CF_UNICODETEXT == fetc.cfFormat );
395 
396     Any aAny = m_XTransferable->getTransferData( m_FormatRegistrar.getRegisteredTextFlavor( ) );
397 
398     // unfortunately not all transferables fulfill the
399     // spec. an do throw an UnsupportedFlavorException
400     // so we must check the any
401     if ( !aAny.hasValue( ) )
402     {
403         OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
404         throw UnsupportedFlavorException( );
405     }
406 
407     Sequence< sal_Int8 > aText;
408     aAny >>= aText;
409 
410     CStgTransferHelper stgTransfHelper;
411 
412     MultiByteToWideCharEx(
413         m_FormatRegistrar.getRegisteredTextCodePage( ),
414         reinterpret_cast< char* >( aText.getArray( ) ),
415         aText.getLength( ),
416         stgTransfHelper );
417 
418     setupStgMedium( fetc, stgTransfHelper, stgmedium );
419 }
420 
421 //------------------------------------------------------------------------
422 // the transferable must have only unicode text so we will sythesize text
423 //------------------------------------------------------------------------
424 
425 void SAL_CALL CXTDataObject::renderSynthesizedTextAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
426 {
427     OSL_ASSERT( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) );
428 
429     DataFlavor aFlavor = formatEtcToDataFlavor(
430         m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) );
431 
432     Any aAny = m_XTransferable->getTransferData( aFlavor );
433 
434     // unfortunately not all transferables fulfill the
435     // spec. an do throw an UnsupportedFlavorException
436     // so we must check the any
437     if ( !aAny.hasValue( ) )
438     {
439         OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
440         throw UnsupportedFlavorException( );
441     }
442 
443     OUString aUnicodeText;
444     aAny >>= aUnicodeText;
445 
446     CStgTransferHelper stgTransfHelper;
447 
448     WideCharToMultiByteEx(
449         GetACP( ),
450         reinterpret_cast<LPCWSTR>( aUnicodeText.getStr( ) ),
451         aUnicodeText.getLength( ),
452         stgTransfHelper );
453 
454     setupStgMedium( fetc, stgTransfHelper, stgmedium );
455 }
456 
457 //------------------------------------------------------------------------
458 //
459 //------------------------------------------------------------------------
460 
461 void SAL_CALL CXTDataObject::renderSynthesizedHtmlAndSetupStgMedium( FORMATETC& fetc, STGMEDIUM& stgmedium )
462 {
463     OSL_ASSERT( m_DataFormatTranslator.isHTMLFormat( fetc.cfFormat ) );
464 
465     DataFlavor aFlavor;
466 
467     // creating a DataFlavor on the fly
468     aFlavor.MimeType = OUString::createFromAscii( "text/html" );
469     aFlavor.DataType = getCppuType( (Sequence< sal_Int8 >*)0 );
470 
471     Any aAny = m_XTransferable->getTransferData( aFlavor );
472 
473     // unfortunately not all transferables fulfill the
474     // spec. an do throw an UnsupportedFlavorException
475     // so we must check the any
476     if ( !aAny.hasValue( ) )
477     {
478         OSL_ENSURE( sal_False, "XTransferable should throw an exception if ask for an unsupported flavor" );
479         throw UnsupportedFlavorException( );
480     }
481 
482     Sequence< sal_Int8 > aTextHtmlSequence;
483     aAny >>= aTextHtmlSequence;
484 
485     Sequence< sal_Int8 > aHTMLFormatSequence = TextHtmlToHTMLFormat( aTextHtmlSequence );
486 
487     sal_uInt32 nBytesToTransfer = aHTMLFormatSequence.getLength( );
488 
489     renderDataAndSetupStgMedium(
490         reinterpret_cast< const sal_Int8* >( aHTMLFormatSequence.getArray( ) ),
491         fetc,
492         0,
493         nBytesToTransfer,
494         stgmedium );
495 }
496 
497 //------------------------------------------------------------------------
498 // IDataObject->EnumFormatEtc
499 //------------------------------------------------------------------------
500 
501 STDMETHODIMP CXTDataObject::EnumFormatEtc(
502     DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
503 {
504     if ( NULL == ppenumFormatetc )
505         return E_INVALIDARG;
506 
507     if ( DATADIR_SET == dwDirection )
508         return E_NOTIMPL;
509 
510     *ppenumFormatetc = NULL;
511 
512     InitializeFormatEtcContainer( );
513 
514     HRESULT hr;
515     if ( DATADIR_GET == dwDirection )
516     {
517         *ppenumFormatetc = new CEnumFormatEtc( this, m_FormatEtcContainer );
518         if ( NULL != *ppenumFormatetc )
519             static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( );
520 
521         hr = ( NULL != *ppenumFormatetc ) ? S_OK : E_OUTOFMEMORY;
522     }
523     else
524         hr = E_INVALIDARG;
525 
526     return hr;
527 }
528 
529 //------------------------------------------------------------------------
530 // IDataObject->QueryGetData
531 //------------------------------------------------------------------------
532 
533 STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc )
534 {
535     if ( (NULL == pFormatetc) || IsBadReadPtr( pFormatetc, sizeof( FORMATETC ) ) )
536         return E_INVALIDARG;
537 
538     InitializeFormatEtcContainer( );
539 
540     return m_FormatEtcContainer.hasFormatEtc( *pFormatetc ) ? S_OK : S_FALSE;
541 }
542 
543 //------------------------------------------------------------------------
544 // IDataObject->GetDataHere
545 //------------------------------------------------------------------------
546 
547 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM )
548 {
549     return E_NOTIMPL;
550 }
551 
552 //------------------------------------------------------------------------
553 // IDataObject->GetCanonicalFormatEtc
554 //------------------------------------------------------------------------
555 
556 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC )
557 {
558     return E_NOTIMPL;
559 }
560 
561 //------------------------------------------------------------------------
562 // IDataObject->SetData
563 //------------------------------------------------------------------------
564 
565 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL )
566 {
567     return E_NOTIMPL;
568 }
569 
570 //------------------------------------------------------------------------
571 // IDataObject->DAdvise
572 //------------------------------------------------------------------------
573 
574 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * )
575 {
576     return E_NOTIMPL;
577 }
578 
579 //------------------------------------------------------------------------
580 // IDataObject->DUnadvise
581 //------------------------------------------------------------------------
582 
583 STDMETHODIMP CXTDataObject::DUnadvise( DWORD )
584 {
585     return E_NOTIMPL;
586 }
587 
588 //------------------------------------------------------------------------
589 // IDataObject->EnumDAdvise
590 //------------------------------------------------------------------------
591 
592 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * )
593 {
594     return E_NOTIMPL;
595 }
596 
597 //------------------------------------------------------------------------
598 // for our convenience
599 //------------------------------------------------------------------------
600 
601 CXTDataObject::operator IDataObject*( )
602 {
603     return static_cast< IDataObject* >( this );
604 }
605 
606 //------------------------------------------------------------------------
607 //
608 //------------------------------------------------------------------------
609 
610 inline
611 DataFlavor SAL_CALL CXTDataObject::formatEtcToDataFlavor( const FORMATETC& aFormatEtc ) const
612 {
613     DataFlavor aFlavor;
614 
615     if ( m_FormatRegistrar.hasSynthesizedLocale( ) )
616         aFlavor =
617             m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, m_FormatRegistrar.getSynthesizedLocale( ) );
618     else
619         aFlavor = m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc );
620 
621     if ( !aFlavor.MimeType.getLength( ) )
622         throw UnsupportedFlavorException( );
623 
624     return aFlavor;
625 }
626 
627 //------------------------------------------------------------------------
628 //
629 //------------------------------------------------------------------------
630 
631 inline
632 void CXTDataObject::validateFormatEtc( LPFORMATETC lpFormatEtc ) const
633 {
634     OSL_ASSERT( lpFormatEtc );
635 
636     if ( lpFormatEtc->lindex != -1 )
637         throw CInvalidFormatEtcException( DV_E_LINDEX );
638 
639     if ( !(lpFormatEtc->dwAspect & DVASPECT_CONTENT) &&
640          !(lpFormatEtc->dwAspect & DVASPECT_SHORTNAME) )
641         throw CInvalidFormatEtcException( DV_E_DVASPECT );
642 
643     if ( !(lpFormatEtc->tymed & TYMED_HGLOBAL) &&
644          !(lpFormatEtc->tymed & TYMED_ISTREAM) &&
645          !(lpFormatEtc->tymed & TYMED_MFPICT) &&
646          !(lpFormatEtc->tymed & TYMED_ENHMF) )
647         throw CInvalidFormatEtcException( DV_E_TYMED );
648 
649     if ( lpFormatEtc->cfFormat == CF_METAFILEPICT &&
650          !(lpFormatEtc->tymed & TYMED_MFPICT) )
651         throw CInvalidFormatEtcException( DV_E_TYMED );
652 
653     if ( lpFormatEtc->cfFormat == CF_ENHMETAFILE &&
654          !(lpFormatEtc->tymed & TYMED_ENHMF) )
655         throw CInvalidFormatEtcException( DV_E_TYMED );
656 }
657 
658 //------------------------------------------------------------------------
659 //
660 //------------------------------------------------------------------------
661 
662 //inline
663 void SAL_CALL CXTDataObject::setupStgMedium( const FORMATETC& fetc,
664                                              CStgTransferHelper& stgTransHlp,
665                                              STGMEDIUM& stgmedium )
666 {
667     stgmedium.pUnkForRelease = NULL;
668 
669     if ( fetc.cfFormat == CF_METAFILEPICT )
670     {
671         stgmedium.tymed         = TYMED_MFPICT;
672         stgmedium.hMetaFilePict = static_cast< HMETAFILEPICT >( stgTransHlp.getHGlobal( ) );
673     }
674     else if ( fetc.cfFormat == CF_ENHMETAFILE )
675     {
676         stgmedium.tymed        = TYMED_ENHMF;
677         stgmedium.hEnhMetaFile = static_cast< HENHMETAFILE >( stgTransHlp.getHGlobal( ) );
678     }
679     else if ( fetc.tymed & TYMED_HGLOBAL )
680     {
681         stgmedium.tymed   = TYMED_HGLOBAL;
682         stgmedium.hGlobal = stgTransHlp.getHGlobal( );
683     }
684     else if ( fetc.tymed & TYMED_ISTREAM )
685     {
686         stgmedium.tymed = TYMED_ISTREAM;
687         stgTransHlp.getIStream( &stgmedium.pstm );
688     }
689     else
690         OSL_ASSERT( sal_False );
691 }
692 
693 //------------------------------------------------------------------------
694 //
695 //------------------------------------------------------------------------
696 
697 inline
698 void SAL_CALL CXTDataObject::invalidateStgMedium( STGMEDIUM& stgmedium ) const
699 {
700     stgmedium.tymed = TYMED_NULL;
701 }
702 
703 //------------------------------------------------------------------------
704 //
705 //------------------------------------------------------------------------
706 
707 inline
708 HRESULT SAL_CALL CXTDataObject::translateStgExceptionCode( HRESULT hr ) const
709 {
710     HRESULT hrTransl;
711 
712     switch( hr )
713     {
714     case STG_E_MEDIUMFULL:
715         hrTransl = hr;
716         break;
717 
718     default:
719         hrTransl = E_UNEXPECTED;
720         break;
721     }
722 
723     return hrTransl;
724 }
725 
726 //------------------------------------------------------------------------
727 //
728 //------------------------------------------------------------------------
729 
730 inline void SAL_CALL CXTDataObject::InitializeFormatEtcContainer( )
731 {
732     if ( !m_bFormatEtcContainerInitialized )
733     {
734         m_FormatRegistrar.RegisterFormats( m_XTransferable, m_FormatEtcContainer );
735         m_bFormatEtcContainerInitialized = sal_True;
736     }
737 }
738 
739 //============================================================================
740 // CEnumFormatEtc
741 //============================================================================
742 
743 //----------------------------------------------------------------------------
744 // ctor
745 //----------------------------------------------------------------------------
746 
747 CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN lpUnkOuter, const CFormatEtcContainer& aFormatEtcContainer ) :
748     m_nRefCnt( 0 ),
749     m_lpUnkOuter( lpUnkOuter ),
750     m_FormatEtcContainer( aFormatEtcContainer )
751 {
752     Reset( );
753 }
754 
755 //----------------------------------------------------------------------------
756 // IUnknown->QueryInterface
757 //----------------------------------------------------------------------------
758 
759 STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject )
760 {
761     if ( NULL == ppvObject )
762         return E_INVALIDARG;
763 
764     HRESULT hr = E_NOINTERFACE;
765 
766     *ppvObject = NULL;
767 
768     if ( ( __uuidof( IUnknown ) == iid ) ||
769          ( __uuidof( IEnumFORMATETC ) == iid ) )
770     {
771         *ppvObject = static_cast< IUnknown* >( this );
772         static_cast< LPUNKNOWN >( *ppvObject )->AddRef( );
773         hr = S_OK;
774     }
775 
776     return hr;
777 }
778 
779 //----------------------------------------------------------------------------
780 // IUnknown->AddRef
781 //----------------------------------------------------------------------------
782 
783 STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( )
784 {
785     // keep the dataobject alive
786     m_lpUnkOuter->AddRef( );
787     return InterlockedIncrement( &m_nRefCnt );
788 }
789 
790 //----------------------------------------------------------------------------
791 // IUnknown->Release
792 //----------------------------------------------------------------------------
793 
794 STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( )
795 {
796     // release the outer dataobject
797     m_lpUnkOuter->Release( );
798 
799     ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt );
800     if ( 0 == nRefCnt )
801         delete this;
802 
803     return nRefCnt;
804 }
805 
806 //----------------------------------------------------------------------------
807 // IEnumFORMATETC->Next
808 //----------------------------------------------------------------------------
809 
810 STDMETHODIMP CEnumFormatEtc::Next( ULONG nRequested, LPFORMATETC lpDest, ULONG* lpFetched )
811 {
812     if ( ( nRequested < 1 ) ||
813          (( nRequested > 1 ) && ( NULL == lpFetched )) ||
814          IsBadWritePtr( lpDest, sizeof( FORMATETC ) * nRequested ) )
815         return E_INVALIDARG;
816 
817     sal_uInt32 nFetched = m_FormatEtcContainer.nextFormatEtc( lpDest, nRequested );
818 
819     if ( NULL != lpFetched )
820         *lpFetched = nFetched;
821 
822     return (nFetched == nRequested) ? S_OK : S_FALSE;
823 }
824 
825 //----------------------------------------------------------------------------
826 // IEnumFORMATETC->Skip
827 //----------------------------------------------------------------------------
828 
829 STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt )
830 {
831     return m_FormatEtcContainer.skipFormatEtc( celt ) ? S_OK : S_FALSE;
832 }
833 
834 //----------------------------------------------------------------------------
835 // IEnumFORMATETC->Reset
836 //----------------------------------------------------------------------------
837 
838 STDMETHODIMP CEnumFormatEtc::Reset( )
839 {
840     m_FormatEtcContainer.beginEnumFormatEtc( );
841     return S_OK;
842 }
843 
844 //----------------------------------------------------------------------------
845 // IEnumFORMATETC->Clone
846 //----------------------------------------------------------------------------
847 
848 STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum )
849 {
850     if ( NULL == ppenum )
851         return E_INVALIDARG;
852 
853     *ppenum = new CEnumFormatEtc( m_lpUnkOuter, m_FormatEtcContainer );
854     if ( NULL != ppenum )
855         static_cast< LPUNKNOWN >( *ppenum )->AddRef( );
856 
857     return ( NULL != *ppenum ) ? S_OK : E_OUTOFMEMORY;
858 }
859