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 transmission
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 synthesize 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