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