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