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 // #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 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 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 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 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 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 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 548 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM ) 549 { 550 return E_NOTIMPL; 551 } 552 553 //------------------------------------------------------------------------ 554 // IDataObject->GetCanonicalFormatEtc 555 //------------------------------------------------------------------------ 556 557 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC ) 558 { 559 return E_NOTIMPL; 560 } 561 562 //------------------------------------------------------------------------ 563 // IDataObject->SetData 564 //------------------------------------------------------------------------ 565 566 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL ) 567 { 568 return E_NOTIMPL; 569 } 570 571 //------------------------------------------------------------------------ 572 // IDataObject->DAdvise 573 //------------------------------------------------------------------------ 574 575 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * ) 576 { 577 return E_NOTIMPL; 578 } 579 580 //------------------------------------------------------------------------ 581 // IDataObject->DUnadvise 582 //------------------------------------------------------------------------ 583 584 STDMETHODIMP CXTDataObject::DUnadvise( DWORD ) 585 { 586 return E_NOTIMPL; 587 } 588 589 //------------------------------------------------------------------------ 590 // IDataObject->EnumDAdvise 591 //------------------------------------------------------------------------ 592 593 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * ) 594 { 595 return E_NOTIMPL; 596 } 597 598 //------------------------------------------------------------------------ 599 // for our convenience 600 //------------------------------------------------------------------------ 601 602 CXTDataObject::operator IDataObject*( ) 603 { 604 return static_cast< IDataObject* >( this ); 605 } 606 607 //------------------------------------------------------------------------ 608 // 609 //------------------------------------------------------------------------ 610 611 inline 612 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 633 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 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 699 void SAL_CALL CXTDataObject::invalidateStgMedium( STGMEDIUM& stgmedium ) const 700 { 701 stgmedium.tymed = TYMED_NULL; 702 } 703 704 //------------------------------------------------------------------------ 705 // 706 //------------------------------------------------------------------------ 707 708 inline 709 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 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 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 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 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 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 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 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 839 STDMETHODIMP CEnumFormatEtc::Reset( ) 840 { 841 m_FormatEtcContainer.beginEnumFormatEtc( ); 842 return S_OK; 843 } 844 845 //---------------------------------------------------------------------------- 846 // IEnumFORMATETC->Clone 847 //---------------------------------------------------------------------------- 848 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