1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_embeddedobj.hxx" 30 #include <com/sun/star/lang/IllegalArgumentException.hpp> 31 #include <com/sun/star/lang/DisposedException.hpp> 32 #include <com/sun/star/embed/WrongStateException.hpp> 33 #include <com/sun/star/embed/UnreachableStateException.hpp> 34 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 35 #include <com/sun/star/beans/XPropertySet.hpp> 36 #include <com/sun/star/io/XTruncate.hpp> 37 #include <com/sun/star/awt/XRequestCallback.hpp> 38 39 #include <platform.h> 40 #include <cppuhelper/interfacecontainer.h> 41 #include <comphelper/mimeconfighelper.hxx> 42 #include <comphelper/storagehelper.hxx> 43 #include <osl/file.hxx> 44 #include <rtl/ref.hxx> 45 46 #include <olecomponent.hxx> 47 #include <olewrapclient.hxx> 48 #include <advisesink.hxx> 49 #include <oleembobj.hxx> 50 #include <mtnotification.hxx> 51 52 using namespace ::com::sun::star; 53 using namespace ::comphelper; 54 #define MAX_ENUM_ELE 20 55 #define FORMATS_NUM 3 56 57 // ============ class ComSmart ===================== 58 namespace { 59 60 template< class T > class ComSmart 61 { 62 T* m_pInterface; 63 64 void OwnRelease() 65 { 66 if ( m_pInterface ) 67 { 68 T* pInterface = m_pInterface; 69 m_pInterface = NULL; 70 pInterface->Release(); 71 } 72 } 73 74 public: 75 ComSmart() 76 : m_pInterface( NULL ) 77 {} 78 79 ComSmart( const ComSmart<T>& rObj ) 80 : m_pInterface( rObj.m_pInterface ) 81 { 82 if ( m_pInterface != NULL ) 83 m_pInterface->AddRef(); 84 } 85 86 ComSmart( T* pInterface ) 87 : m_pInterface( pInterface ) 88 { 89 if ( m_pInterface != NULL ) 90 m_pInterface->AddRef(); 91 } 92 93 ~ComSmart() 94 { 95 OwnRelease(); 96 } 97 98 ComSmart& operator=( const ComSmart<T>& rObj ) 99 { 100 OwnRelease(); 101 102 m_pInterface = rObj.m_pInterface; 103 104 if ( m_pInterface != NULL ) 105 m_pInterface->AddRef(); 106 107 return *this; 108 } 109 110 ComSmart<T>& operator=( T* pInterface ) 111 { 112 OwnRelease(); 113 114 m_pInterface = pInterface; 115 116 if ( m_pInterface != NULL ) 117 m_pInterface->AddRef(); 118 119 return *this; 120 } 121 122 operator T*() const 123 { 124 return m_pInterface; 125 } 126 127 T& operator*() const 128 { 129 return *m_pInterface; 130 } 131 132 T** operator&() 133 { 134 OwnRelease(); 135 136 m_pInterface = NULL; 137 138 return &m_pInterface; 139 } 140 141 T* operator->() const 142 { 143 return m_pInterface; 144 } 145 146 BOOL operator==( const ComSmart<T>& rObj ) const 147 { 148 return ( m_pInterface == rObj.m_pInterface ); 149 } 150 151 BOOL operator!=( const ComSmart<T>& rObj ) const 152 { 153 return ( m_pInterface != rObj.m_pInterface ); 154 } 155 156 BOOL operator==( const T* pInterface ) const 157 { 158 return ( m_pInterface == pInterface ); 159 } 160 161 BOOL operator!=( const T* pInterface ) const 162 { 163 return ( m_pInterface != pInterface ); 164 } 165 }; 166 167 } 168 169 // ============ class ComSmart ===================== 170 171 sal_Bool ConvertBufferToFormat( void* pBuf, 172 sal_uInt32 nBufSize, 173 const ::rtl::OUString& aFormatShortName, 174 uno::Any& aResult ); 175 176 ::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException ); 177 178 typedef ::std::vector< FORMATETC* > FormatEtcList; 179 180 FORMATETC pFormatTemplates[FORMATS_NUM] = { 181 { CF_ENHMETAFILE, NULL, 0, -1, TYMED_ENHMF }, 182 { CF_METAFILEPICT, NULL, 0, -1, TYMED_MFPICT }, 183 { CF_BITMAP, NULL, 0, -1, TYMED_GDI } }; 184 185 186 struct OleComponentNative_Impl { 187 ComSmart< IUnknown > m_pObj; 188 ComSmart< IOleObject > m_pOleObject; 189 ComSmart< IViewObject2 > m_pViewObject2; 190 ComSmart< IStorage > m_pIStorage; 191 FormatEtcList m_aFormatsList; 192 uno::Sequence< datatransfer::DataFlavor > m_aSupportedGraphFormats; 193 194 OleComponentNative_Impl() 195 { 196 // TODO: Extend format list 197 m_aSupportedGraphFormats.realloc( 5 ); 198 199 m_aSupportedGraphFormats[0] = datatransfer::DataFlavor( 200 ::rtl::OUString::createFromAscii( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ), 201 ::rtl::OUString::createFromAscii( "Windows Enhanced Metafile" ), 202 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); 203 204 m_aSupportedGraphFormats[1] = datatransfer::DataFlavor( 205 ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), 206 ::rtl::OUString::createFromAscii( "Windows Metafile" ), 207 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); 208 209 m_aSupportedGraphFormats[2] = datatransfer::DataFlavor( 210 ::rtl::OUString::createFromAscii( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ), 211 ::rtl::OUString::createFromAscii( "Bitmap" ), 212 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); 213 214 m_aSupportedGraphFormats[3] = datatransfer::DataFlavor( 215 ::rtl::OUString::createFromAscii( "image/png" ), 216 ::rtl::OUString::createFromAscii( "PNG" ), 217 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); 218 219 m_aSupportedGraphFormats[0] = datatransfer::DataFlavor( 220 ::rtl::OUString::createFromAscii( "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" ), 221 ::rtl::OUString::createFromAscii( "GDIMetafile" ), 222 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); 223 } 224 225 void AddSupportedFormat( const FORMATETC& aFormatEtc ); 226 227 FORMATETC* GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect ); 228 229 sal_Bool ConvertDataForFlavor( const STGMEDIUM& aMedium, 230 const datatransfer::DataFlavor& aFlavor, 231 uno::Any& aResult ); 232 233 sal_Bool GraphicalFlavor( const datatransfer::DataFlavor& aFlavor ); 234 235 uno::Sequence< datatransfer::DataFlavor > GetFlavorsForAspects( sal_uInt32 nSupportedAspects ); 236 }; 237 238 //---------------------------------------------- 239 DWORD GetAspectFromFlavor( const datatransfer::DataFlavor& aFlavor ) 240 { 241 if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=THUMBNAIL" ) ) != -1 ) 242 return DVASPECT_THUMBNAIL; 243 else if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=ICON" ) ) != -1 ) 244 return DVASPECT_ICON; 245 else if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=DOCPRINT" ) ) != -1 ) 246 return DVASPECT_DOCPRINT; 247 else 248 return DVASPECT_CONTENT; 249 } 250 251 //---------------------------------------------- 252 ::rtl::OUString GetFlavorSuffixFromAspect( DWORD nAsp ) 253 { 254 ::rtl::OUString aResult; 255 256 if ( nAsp == DVASPECT_THUMBNAIL ) 257 aResult = ::rtl::OUString::createFromAscii( ";Aspect=THUMBNAIL" ); 258 else if ( nAsp == DVASPECT_ICON ) 259 aResult = ::rtl::OUString::createFromAscii( ";Aspect=ICON" ); 260 else if ( nAsp == DVASPECT_DOCPRINT ) 261 aResult = ::rtl::OUString::createFromAscii( ";Aspect=DOCPRINT" ); 262 263 // no suffix for DVASPECT_CONTENT 264 265 return aResult; 266 } 267 268 //---------------------------------------------- 269 HRESULT OpenIStorageFromURL_Impl( const ::rtl::OUString& aURL, IStorage** ppIStorage ) 270 { 271 OSL_ENSURE( ppIStorage, "The pointer must not be empty!" ); 272 273 ::rtl::OUString aFilePath; 274 if ( !ppIStorage || ::osl::FileBase::getSystemPathFromFileURL( aURL, aFilePath ) != ::osl::FileBase::E_None ) 275 throw uno::RuntimeException(); // TODO: something dangerous happend 276 277 return StgOpenStorage( reinterpret_cast<LPCWSTR>(aFilePath.getStr()), 278 NULL, 279 STGM_READWRITE | STGM_TRANSACTED, // | STGM_DELETEONRELEASE, 280 NULL, 281 0, 282 ppIStorage ); 283 } 284 285 //---------------------------------------------- 286 sal_Bool OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM& aMedium, 287 const datatransfer::DataFlavor& aFlavor, 288 uno::Any& aResult ) 289 { 290 sal_Bool bAnyIsReady = sal_False; 291 292 // try to convert data from Medium format to specified Flavor format 293 if ( aFlavor.DataType == getCppuType( ( const uno::Sequence< sal_Int8 >* ) 0 ) ) 294 { 295 // first the GDI-metafile must be generated 296 297 unsigned char* pBuf = NULL; 298 sal_uInt32 nBufSize = 0; 299 ::rtl::OUString aFormat; 300 301 if ( aMedium.tymed == TYMED_MFPICT ) // Win Metafile 302 { 303 aFormat = ::rtl::OUString::createFromAscii("image/x-wmf"); 304 METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict ); 305 if ( pMF ) 306 { 307 nBufSize = GetMetaFileBitsEx( pMF->hMF, 0, NULL ) + 22; 308 pBuf = new unsigned char[nBufSize]; 309 310 311 // TODO/LATER: the unit size must be calculated correctly 312 *( (long* )pBuf ) = 0x9ac6cdd7L; 313 *( (short* )( pBuf+6 )) = ( SHORT ) 0; 314 *( (short* )( pBuf+8 )) = ( SHORT ) 0; 315 *( (short* )( pBuf+10 )) = ( SHORT ) pMF->xExt; 316 *( (short* )( pBuf+12 )) = ( SHORT ) pMF->yExt; 317 *( (short* )( pBuf+14 )) = ( USHORT ) 2540; 318 319 320 if ( nBufSize && nBufSize == GetMetaFileBitsEx( pMF->hMF, nBufSize - 22, pBuf + 22 ) ) 321 { 322 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"", 57 ) ) 323 { 324 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize ); 325 bAnyIsReady = sal_True; 326 } 327 } 328 329 GlobalUnlock( aMedium.hMetaFilePict ); 330 } 331 } 332 else if ( aMedium.tymed == TYMED_ENHMF ) // Enh Metafile 333 { 334 aFormat = ::rtl::OUString::createFromAscii("image/x-emf"); 335 nBufSize = GetEnhMetaFileBits( aMedium.hEnhMetaFile, 0, NULL ); 336 pBuf = new unsigned char[nBufSize]; 337 if ( nBufSize && nBufSize == GetEnhMetaFileBits( aMedium.hEnhMetaFile, nBufSize, pBuf ) ) 338 { 339 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"", 57 ) ) 340 { 341 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize ); 342 bAnyIsReady = sal_True; 343 } 344 } 345 } 346 else if ( aMedium.tymed == TYMED_GDI ) // Bitmap 347 { 348 aFormat = ::rtl::OUString::createFromAscii("image/x-MS-bmp"); 349 nBufSize = GetBitmapBits( aMedium.hBitmap, 0, NULL ); 350 pBuf = new unsigned char[nBufSize]; 351 if ( nBufSize && nBufSize == sal::static_int_cast< ULONG >( GetBitmapBits( aMedium.hBitmap, nBufSize, pBuf ) ) ) 352 { 353 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"", 54 ) ) 354 { 355 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize ); 356 bAnyIsReady = sal_True; 357 } 358 } 359 } 360 361 if ( pBuf && !bAnyIsReady ) 362 { 363 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ ) 364 if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType ) 365 && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType 366 && aFlavor.DataType == getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) 367 { 368 bAnyIsReady = ConvertBufferToFormat( ( void* )pBuf, nBufSize, aFormat, aResult ); 369 break; 370 } 371 } 372 373 delete[] pBuf; 374 } 375 376 return bAnyIsReady; 377 } 378 379 //---------------------------------------------- 380 sal_Bool OleComponentNative_Impl::GraphicalFlavor( const datatransfer::DataFlavor& aFlavor ) 381 { 382 // Actually all the required graphical formats must be supported 383 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ ) 384 if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType ) 385 && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType ) 386 return sal_True; 387 388 return sal_False; 389 } 390 391 //---------------------------------------------- 392 sal_Bool GetClassIDFromSequence_Impl( uno::Sequence< sal_Int8 > aSeq, CLSID& aResult ) 393 { 394 if ( aSeq.getLength() == 16 ) 395 { 396 aResult.Data1 = ( ( ( ( ( ( sal_uInt8 )aSeq[0] << 8 ) + ( sal_uInt8 )aSeq[1] ) << 8 ) + ( sal_uInt8 )aSeq[2] ) << 8 ) + ( sal_uInt8 )aSeq[3]; 397 aResult.Data2 = ( ( sal_uInt8 )aSeq[4] << 8 ) + ( sal_uInt8 )aSeq[5]; 398 aResult.Data3 = ( ( sal_uInt8 )aSeq[6] << 8 ) + ( sal_uInt8 )aSeq[7]; 399 for( int nInd = 0; nInd < 8; nInd++ ) 400 aResult.Data4[nInd] = ( sal_uInt8 )aSeq[nInd+8]; 401 402 return sal_True; 403 } 404 405 return sal_False; 406 } 407 408 //---------------------------------------------- 409 ::rtl::OUString WinAccToVcl_Impl( const sal_Unicode* pStr ) 410 { 411 ::rtl::OUString aResult; 412 413 if( pStr ) 414 { 415 while ( *pStr ) 416 { 417 if ( *pStr == '&' ) 418 { 419 aResult += ::rtl::OUString::createFromAscii( "~" ); 420 while( *( ++pStr ) == '&' ); 421 } 422 else 423 { 424 aResult += ::rtl::OUString( pStr, 1 ); 425 pStr++; 426 } 427 } 428 } 429 430 return aResult; 431 } 432 433 //---------------------------------------------- 434 OleComponent::OleComponent( const uno::Reference< lang::XMultiServiceFactory >& xFactory, OleEmbeddedObject* pUnoOleObject ) 435 : m_pInterfaceContainer( NULL ) 436 , m_bDisposed( sal_False ) 437 , m_bModified( sal_False ) 438 , m_pNativeImpl( new OleComponentNative_Impl() ) 439 , m_xFactory( xFactory ) 440 , m_pOleWrapClientSite( NULL ) 441 , m_pImplAdviseSink( NULL ) 442 , m_pUnoOleObject( pUnoOleObject ) 443 , m_nOLEMiscFlags( 0 ) 444 , m_nAdvConn( 0 ) 445 , m_bOleInitialized( sal_False ) 446 , m_bWorkaroundActive( sal_False ) 447 { 448 OSL_ENSURE( m_pUnoOleObject, "No owner object is provided!" ); 449 450 HRESULT hr = OleInitialize( NULL ); 451 OSL_ENSURE( hr == S_OK || hr == S_FALSE, "The ole can not be successfuly initialized\n" ); 452 if ( hr == S_OK || hr == S_FALSE ) 453 m_bOleInitialized = sal_True; 454 455 m_pOleWrapClientSite = new OleWrapperClientSite( ( OleComponent* )this ); 456 m_pOleWrapClientSite->AddRef(); 457 458 m_pImplAdviseSink = new OleWrapperAdviseSink( ( OleComponent* )this ); 459 m_pImplAdviseSink->AddRef(); 460 461 } 462 463 //---------------------------------------------- 464 OleComponent::~OleComponent() 465 { 466 OSL_ENSURE( !m_pOleWrapClientSite && !m_pImplAdviseSink && !m_pInterfaceContainer && !m_bOleInitialized, 467 "The object was not closed successfully! DISASTER is possible!" ); 468 469 if ( m_pOleWrapClientSite || m_pImplAdviseSink || m_pInterfaceContainer || m_bOleInitialized ) 470 { 471 ::osl::MutexGuard aGuard( m_aMutex ); 472 m_refCount++; 473 try { 474 Dispose(); 475 } catch( uno::Exception& ) {} 476 } 477 478 for ( FormatEtcList::iterator aIter = m_pNativeImpl->m_aFormatsList.begin(); 479 aIter != m_pNativeImpl->m_aFormatsList.end(); 480 aIter++ ) 481 { 482 delete (*aIter); 483 (*aIter) = NULL; 484 } 485 m_pNativeImpl->m_aFormatsList.clear(); 486 487 delete m_pNativeImpl; 488 } 489 490 //---------------------------------------------- 491 void OleComponentNative_Impl::AddSupportedFormat( const FORMATETC& aFormatEtc ) 492 { 493 FORMATETC* pFormatToInsert = new FORMATETC( aFormatEtc ); 494 m_aFormatsList.push_back( pFormatToInsert ); 495 } 496 497 //---------------------------------------------- 498 FORMATETC* OleComponentNative_Impl::GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect ) 499 { 500 for ( FormatEtcList::iterator aIter = m_aFormatsList.begin(); 501 aIter != m_aFormatsList.end(); 502 aIter++ ) 503 if ( (*aIter) && (*aIter)->dwAspect == nRequestedAspect ) 504 return (*aIter); 505 506 return NULL; 507 } 508 509 //---------------------------------------------- 510 void OleComponent::Dispose() 511 { 512 // the mutex must be locked before this method is called 513 if ( m_bDisposed ) 514 return; 515 516 CloseObject(); 517 518 if ( m_pOleWrapClientSite ) 519 { 520 m_pOleWrapClientSite->disconnectOleComponent(); 521 m_pOleWrapClientSite->Release(); 522 m_pOleWrapClientSite = NULL; 523 } 524 525 if ( m_pImplAdviseSink ) 526 { 527 m_pImplAdviseSink->disconnectOleComponent(); 528 m_pImplAdviseSink->Release(); 529 m_pImplAdviseSink = NULL; 530 } 531 532 if ( m_pInterfaceContainer ) 533 { 534 lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >( this ) ); 535 m_pInterfaceContainer->disposeAndClear( aEvent ); 536 537 delete m_pInterfaceContainer; 538 m_pInterfaceContainer = NULL; 539 } 540 541 if ( m_bOleInitialized ) 542 { 543 // since the disposing can happen not only from main thread but also from a clipboard 544 // the deinitialization might lead to a disaster, SO7 does not deinitialize OLE at all 545 // so currently the same approach is selected as workaround 546 // OleUninitialize(); 547 m_bOleInitialized = sal_False; 548 } 549 550 m_bDisposed = sal_True; 551 } 552 553 //---------------------------------------------- 554 void OleComponent::disconnectEmbeddedObject() 555 { 556 // must not be called from destructor of UNO OLE object!!! 557 osl::MutexGuard aGuard( m_aMutex ); 558 m_pUnoOleObject = NULL; 559 } 560 561 //---------------------------------------------- 562 void OleComponent::CreateNewIStorage_Impl() 563 { 564 // TODO: in future a global memory could be used instead of file. 565 566 // write the stream to the temporary file 567 ::rtl::OUString aTempURL; 568 569 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" ); 570 if ( m_pUnoOleObject ) 571 aTempURL = m_pUnoOleObject->CreateTempURLEmpty_Impl(); 572 else 573 aTempURL = GetNewTempFileURL_Impl( m_xFactory ); 574 575 if ( !aTempURL.getLength() ) 576 throw uno::RuntimeException(); // TODO 577 578 // open an IStorage based on the temporary file 579 ::rtl::OUString aTempFilePath; 580 if ( ::osl::FileBase::getSystemPathFromFileURL( aTempURL, aTempFilePath ) != ::osl::FileBase::E_None ) 581 throw uno::RuntimeException(); // TODO: something dangerous happend 582 583 HRESULT hr = StgCreateDocfile( reinterpret_cast<LPCWSTR>(aTempFilePath.getStr()), STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED | STGM_DELETEONRELEASE, 0, &m_pNativeImpl->m_pIStorage ); 584 if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage ) 585 throw io::IOException(); // TODO: transport error code? 586 } 587 588 //---------------------------------------------- 589 uno::Sequence< datatransfer::DataFlavor > OleComponentNative_Impl::GetFlavorsForAspects( sal_uInt32 nSupportedAspects ) 590 { 591 uno::Sequence< datatransfer::DataFlavor > aResult; 592 for ( sal_uInt32 nAsp = 1; nAsp <= 8; nAsp *= 2 ) 593 if ( ( nSupportedAspects & nAsp ) == nAsp ) 594 { 595 ::rtl::OUString aAspectSuffix = GetFlavorSuffixFromAspect( nAsp ); 596 597 sal_Int32 nLength = aResult.getLength(); 598 aResult.realloc( nLength + m_aSupportedGraphFormats.getLength() ); 599 600 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ ) 601 { 602 aResult[nLength + nInd].MimeType = m_aSupportedGraphFormats[nInd].MimeType + aAspectSuffix; 603 aResult[nLength + nInd].HumanPresentableName = m_aSupportedGraphFormats[nInd].HumanPresentableName; 604 aResult[nLength + nInd].DataType = m_aSupportedGraphFormats[nInd].DataType; 605 } 606 } 607 608 return aResult; 609 } 610 611 //---------------------------------------------- 612 void OleComponent::RetrieveObjectDataFlavors_Impl() 613 { 614 if ( !m_pNativeImpl->m_pOleObject ) 615 throw embed::WrongStateException(); // TODO: the object is in wrong state 616 617 if ( !m_aDataFlavors.getLength() ) 618 { 619 ComSmart< IDataObject > pDataObject; 620 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject ); 621 if ( SUCCEEDED( hr ) && pDataObject ) 622 { 623 ComSmart< IEnumFORMATETC > pFormatEnum; 624 hr = pDataObject->EnumFormatEtc( DATADIR_GET, &pFormatEnum ); 625 if ( SUCCEEDED( hr ) && pFormatEnum ) 626 { 627 FORMATETC pElem[ MAX_ENUM_ELE ]; 628 ULONG nNum = 0; 629 630 // if it is possible to retrieve at least one supported graphical format for an aspect 631 // this format can be converted to other supported formats 632 sal_uInt32 nSupportedAspects = 0; 633 do 634 { 635 HRESULT hr = pFormatEnum->Next( MAX_ENUM_ELE, pElem, &nNum ); 636 if( hr == S_OK || hr == S_FALSE ) 637 { 638 for( sal_uInt32 nInd = 0; nInd < FORMATS_NUM; nInd++ ) 639 { 640 if ( pElem[nInd].cfFormat == pFormatTemplates[nInd].cfFormat 641 && pElem[nInd].tymed == pFormatTemplates[nInd].tymed ) 642 nSupportedAspects |= pElem[nInd].dwAspect; 643 } 644 } 645 else 646 break; 647 } 648 while( nNum == MAX_ENUM_ELE ); 649 650 m_aDataFlavors = m_pNativeImpl->GetFlavorsForAspects( nSupportedAspects ); 651 } 652 } 653 654 if ( !m_aDataFlavors.getLength() ) 655 { 656 // TODO: 657 // for any reason the object could not provide this information 658 // try to get access to the cached representation 659 } 660 } 661 } 662 663 //---------------------------------------------- 664 sal_Bool OleComponent::InitializeObject_Impl() 665 // There will be no static objects! 666 { 667 if ( !m_pNativeImpl->m_pObj ) 668 return sal_False; 669 670 // the linked object will be detected here 671 ComSmart< IOleLink > pOleLink; 672 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink ); 673 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" ); 674 if ( m_pUnoOleObject ) 675 m_pUnoOleObject->SetObjectIsLink_Impl( sal_Bool( pOleLink != NULL ) ); 676 677 678 hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IViewObject2, (void**)&m_pNativeImpl->m_pViewObject2 ); 679 if ( FAILED( hr ) || !m_pNativeImpl->m_pViewObject2 ) 680 return sal_False; 681 682 // not realy needed for now, since object is updated on saving 683 // m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink ); 684 685 // remove all the caches 686 IOleCache* pIOleCache = NULL; 687 if ( SUCCEEDED( m_pNativeImpl->m_pObj->QueryInterface( IID_IOleCache, (void**)&pIOleCache ) ) && pIOleCache ) 688 { 689 IEnumSTATDATA* pEnumSD = NULL; 690 HRESULT hr = pIOleCache->EnumCache( &pEnumSD ); 691 692 if ( SUCCEEDED( hr ) && pEnumSD ) 693 { 694 pEnumSD->Reset(); 695 STATDATA aSD; 696 DWORD nNum; 697 while( SUCCEEDED( pEnumSD->Next( 1, &aSD, &nNum ) ) && nNum == 1 ) 698 hr = pIOleCache->Uncache( aSD.dwConnection ); 699 } 700 701 // No IDataObject implementation, caching must be used instead 702 DWORD nConn; 703 FORMATETC aFormat = { 0, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }; 704 hr = pIOleCache->Cache( &aFormat, ADVFCACHE_ONSAVE, &nConn ); 705 706 pIOleCache->Release(); 707 pIOleCache = NULL; 708 } 709 710 hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleObject, (void**)&m_pNativeImpl->m_pOleObject ); 711 if ( FAILED( hr ) || !m_pNativeImpl->m_pOleObject ) 712 return sal_False; // Static objects are not supported, they should be inserted as graphics 713 714 m_pNativeImpl->m_pOleObject->GetMiscStatus( DVASPECT_CONTENT, ( DWORD* )&m_nOLEMiscFlags ); 715 // TODO: use other misc flags also 716 // the object should have drawable aspect even in case it supports only iconic representation 717 // if ( m_nOLEMiscFlags & OLEMISC_ONLYICONIC ) 718 719 m_pNativeImpl->m_pOleObject->SetClientSite( m_pOleWrapClientSite ); 720 721 // the only need in this registration is workaround for close notification 722 m_pNativeImpl->m_pOleObject->Advise( m_pImplAdviseSink, ( DWORD* )&m_nAdvConn ); 723 m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink ); 724 725 OleSetContainedObject( m_pNativeImpl->m_pOleObject, TRUE ); 726 727 return sal_True; 728 } 729 730 //---------------------------------------------- 731 void OleComponent::LoadEmbeddedObject( const ::rtl::OUString& aTempURL ) 732 { 733 if ( !aTempURL.getLength() ) 734 throw lang::IllegalArgumentException(); // TODO 735 736 if ( m_pNativeImpl->m_pIStorage ) 737 throw io::IOException(); // TODO the object is already initialized or wrong initialization is done 738 739 // open an IStorage based on the temporary file 740 HRESULT hr = OpenIStorageFromURL_Impl( aTempURL, &m_pNativeImpl->m_pIStorage ); 741 742 if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage ) 743 throw io::IOException(); // TODO: transport error code? 744 745 hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj ); 746 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) 747 { 748 // STATSTG aStat; 749 // m_pNativeImpl->m_pIStorage->Stat( &aStat, STATFLAG_NONAME ); 750 throw uno::RuntimeException(); 751 } 752 753 if ( !InitializeObject_Impl() ) 754 throw uno::RuntimeException(); // TODO 755 } 756 757 //---------------------------------------------- 758 void OleComponent::CreateObjectFromClipboard() 759 { 760 if ( m_pNativeImpl->m_pIStorage ) 761 throw io::IOException(); // TODO:the object is already initialized 762 763 CreateNewIStorage_Impl(); 764 if ( !m_pNativeImpl->m_pIStorage ) 765 throw uno::RuntimeException(); // TODO 766 767 IDataObject * pDO = NULL; 768 HRESULT hr = OleGetClipboard( &pDO ); 769 if( SUCCEEDED( hr ) && pDO ) 770 { 771 hr = OleQueryCreateFromData( pDO ); 772 if( S_OK == GetScode( hr ) ) 773 { 774 hr = OleCreateFromData( pDO, 775 IID_IUnknown, 776 OLERENDER_DRAW, // OLERENDER_FORMAT 777 NULL, // &aFormat, 778 NULL, 779 m_pNativeImpl->m_pIStorage, 780 (void**)&m_pNativeImpl->m_pObj ); 781 } 782 else 783 { 784 // Static objects are not supported 785 pDO->Release(); 786 } 787 } 788 789 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) 790 throw uno::RuntimeException(); 791 792 if ( !InitializeObject_Impl() ) 793 throw uno::RuntimeException(); // TODO 794 } 795 796 //---------------------------------------------- 797 void OleComponent::CreateNewEmbeddedObject( const uno::Sequence< sal_Int8 >& aSeqCLSID ) 798 { 799 CLSID aClsID; 800 801 if ( !GetClassIDFromSequence_Impl( aSeqCLSID, aClsID ) ) 802 throw lang::IllegalArgumentException(); // TODO 803 804 if ( m_pNativeImpl->m_pIStorage ) 805 throw io::IOException(); // TODO:the object is already initialized 806 807 CreateNewIStorage_Impl(); 808 if ( !m_pNativeImpl->m_pIStorage ) 809 throw uno::RuntimeException(); // TODO 810 811 // FORMATETC aFormat = { CF_METAFILEPICT, NULL, nAspect, -1, TYMED_MFPICT }; // for OLE..._DRAW should be NULL 812 813 HRESULT hr = OleCreate( aClsID, 814 IID_IUnknown, 815 OLERENDER_DRAW, // OLERENDER_FORMAT 816 NULL, // &aFormat, 817 NULL, 818 m_pNativeImpl->m_pIStorage, 819 (void**)&m_pNativeImpl->m_pObj ); 820 821 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) 822 throw uno::RuntimeException(); // TODO 823 824 if ( !InitializeObject_Impl() ) 825 throw uno::RuntimeException(); // TODO 826 827 // TODO: getExtent??? 828 } 829 830 //---------------------------------------------- 831 void OleComponent::CreateObjectFromData( const uno::Reference< datatransfer::XTransferable >& ) 832 // Static objects are not supported, they should be inserted as graphics 833 { 834 // TODO: May be this call is useless since there are no static objects 835 // and nonstatic objects will be created based on OLEstorage ( stream ). 836 // ??? 837 838 // OleQueryCreateFromData... 839 } 840 841 //---------------------------------------------- 842 void OleComponent::CreateObjectFromFile( const ::rtl::OUString& aFileURL ) 843 { 844 if ( m_pNativeImpl->m_pIStorage ) 845 throw io::IOException(); // TODO:the object is already initialized 846 847 CreateNewIStorage_Impl(); 848 if ( !m_pNativeImpl->m_pIStorage ) 849 throw uno::RuntimeException(); // TODO: 850 851 ::rtl::OUString aFilePath; 852 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None ) 853 throw uno::RuntimeException(); // TODO: something dangerous happend 854 855 HRESULT hr = OleCreateFromFile( CLSID_NULL, 856 reinterpret_cast<LPCWSTR>(aFilePath.getStr()), 857 IID_IUnknown, 858 OLERENDER_DRAW, // OLERENDER_FORMAT 859 NULL, 860 NULL, 861 m_pNativeImpl->m_pIStorage, 862 (void**)&m_pNativeImpl->m_pObj ); 863 864 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) 865 throw uno::RuntimeException(); // TODO 866 867 if ( !InitializeObject_Impl() ) 868 throw uno::RuntimeException(); // TODO 869 } 870 871 //---------------------------------------------- 872 void OleComponent::CreateLinkFromFile( const ::rtl::OUString& aFileURL ) 873 { 874 if ( m_pNativeImpl->m_pIStorage ) 875 throw io::IOException(); // TODO:the object is already initialized 876 877 CreateNewIStorage_Impl(); 878 if ( !m_pNativeImpl->m_pIStorage ) 879 throw uno::RuntimeException(); // TODO: 880 881 ::rtl::OUString aFilePath; 882 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None ) 883 throw uno::RuntimeException(); // TODO: something dangerous happend 884 885 HRESULT hr = OleCreateLinkToFile( reinterpret_cast<LPCWSTR>(aFilePath.getStr()), 886 IID_IUnknown, 887 OLERENDER_DRAW, // OLERENDER_FORMAT 888 NULL, 889 NULL, 890 m_pNativeImpl->m_pIStorage, 891 (void**)&m_pNativeImpl->m_pObj ); 892 893 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) 894 throw uno::RuntimeException(); // TODO 895 896 if ( !InitializeObject_Impl() ) 897 throw uno::RuntimeException(); // TODO 898 } 899 900 //---------------------------------------------- 901 void OleComponent::InitEmbeddedCopyOfLink( OleComponent* pOleLinkComponent ) 902 { 903 if ( !pOleLinkComponent || !pOleLinkComponent->m_pNativeImpl->m_pObj ) 904 throw lang::IllegalArgumentException(); // TODO 905 906 if ( m_pNativeImpl->m_pIStorage ) 907 throw io::IOException(); // TODO:the object is already initialized 908 909 ComSmart< IDataObject > pDataObject; 910 HRESULT hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject ); 911 if ( SUCCEEDED( hr ) && pDataObject && SUCCEEDED( OleQueryCreateFromData( pDataObject ) ) ) 912 { 913 // the object must be already disconnected from the temporary URL 914 CreateNewIStorage_Impl(); 915 if ( !m_pNativeImpl->m_pIStorage ) 916 throw uno::RuntimeException(); // TODO: 917 918 hr = OleCreateFromData( pDataObject, 919 IID_IUnknown, 920 OLERENDER_DRAW, 921 NULL, 922 NULL, 923 m_pNativeImpl->m_pIStorage, 924 (void**)&m_pNativeImpl->m_pObj ); 925 } 926 927 if ( !m_pNativeImpl->m_pObj ) 928 { 929 ComSmart< IOleLink > pOleLink; 930 hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink ); 931 if ( FAILED( hr ) || !pOleLink ) 932 throw io::IOException(); // TODO: the object doesn't support IOleLink 933 934 ComSmart< IMoniker > pMoniker; 935 hr = pOleLink->GetSourceMoniker( &pMoniker ); 936 if ( FAILED( hr ) || !pMoniker ) 937 throw io::IOException(); // TODO: can not retrieve moniker 938 939 // In case of file moniker life is easy : ) 940 DWORD aMonType = 0; 941 hr = pMoniker->IsSystemMoniker( &aMonType ); 942 if ( SUCCEEDED( hr ) && aMonType == MKSYS_FILEMONIKER ) 943 { 944 ComSmart< IMalloc > pMalloc; 945 CoGetMalloc( 1, &pMalloc ); // if fails there will be a memory leak 946 OSL_ENSURE( pMalloc, "CoGetMalloc() failed!" ); 947 948 LPOLESTR pOleStr = NULL; 949 hr = pOleLink->GetSourceDisplayName( &pOleStr ); 950 if ( SUCCEEDED( hr ) && pOleStr ) 951 { 952 ::rtl::OUString aFilePath( ( sal_Unicode* )pOleStr ); 953 if ( pMalloc ) 954 pMalloc->Free( ( void* )pOleStr ); 955 956 hr = OleCreateFromFile( CLSID_NULL, 957 reinterpret_cast<LPCWSTR>(aFilePath.getStr()), 958 IID_IUnknown, 959 OLERENDER_DRAW, // OLERENDER_FORMAT 960 NULL, 961 NULL, 962 m_pNativeImpl->m_pIStorage, 963 (void**)&m_pNativeImpl->m_pObj ); 964 } 965 } 966 967 // in case of other moniker types the only way is to get storage 968 if ( !m_pNativeImpl->m_pObj ) 969 { 970 ComSmart< IBindCtx > pBindCtx; 971 hr = CreateBindCtx( 0, ( LPBC FAR* )&pBindCtx ); 972 if ( SUCCEEDED( hr ) && pBindCtx ) 973 { 974 ComSmart< IStorage > pObjectStorage; 975 hr = pMoniker->BindToStorage( pBindCtx, NULL, IID_IStorage, (void**)&pObjectStorage ); 976 if ( SUCCEEDED( hr ) && pObjectStorage ) 977 { 978 hr = pObjectStorage->CopyTo( 0, NULL, NULL, m_pNativeImpl->m_pIStorage ); 979 if ( SUCCEEDED( hr ) ) 980 hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj ); 981 } 982 } 983 } 984 } 985 986 // If object could not be created the only way is to use graphical representation 987 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) 988 throw uno::RuntimeException(); // TODO 989 990 if ( !InitializeObject_Impl() ) 991 throw uno::RuntimeException(); // TODO 992 } 993 994 //---------------------------------------------- 995 void OleComponent::RunObject() 996 { 997 OSL_ENSURE( m_pNativeImpl->m_pOleObject, "The pointer can not be set to NULL here!\n" ); 998 if ( !m_pNativeImpl->m_pOleObject ) 999 throw embed::WrongStateException(); // TODO: the object is in wrong state 1000 1001 if ( !OleIsRunning( m_pNativeImpl->m_pOleObject ) ) 1002 { 1003 HRESULT hr = S_OK; 1004 try 1005 { 1006 hr = OleRun( m_pNativeImpl->m_pObj ); 1007 } 1008 catch( ... ) 1009 { 1010 int i = 0; 1011 i++; 1012 } 1013 1014 if ( FAILED( hr ) ) 1015 { 1016 if ( hr == REGDB_E_CLASSNOTREG ) 1017 throw embed::UnreachableStateException(); // the object server is not installed 1018 else 1019 throw io::IOException(); 1020 } 1021 } 1022 } 1023 1024 //---------------------------------------------- 1025 awt::Size OleComponent::CalculateWithFactor( const awt::Size& aSize, 1026 const awt::Size& aMultiplier, 1027 const awt::Size& aDivisor ) 1028 { 1029 awt::Size aResult; 1030 1031 sal_Int64 nWidth = (sal_Int64)aSize.Width * (sal_Int64)aMultiplier.Width / (sal_Int64)aDivisor.Width; 1032 sal_Int64 nHeight = (sal_Int64)aSize.Height * (sal_Int64)aMultiplier.Height / (sal_Int64)aDivisor.Height; 1033 OSL_ENSURE( nWidth < SAL_MAX_INT32 && nWidth > SAL_MIN_INT32 1034 && nHeight < SAL_MAX_INT32 && nHeight > SAL_MIN_INT32, 1035 "Unacceptable result size!" ); 1036 1037 aResult.Width = (sal_Int32)nWidth; 1038 aResult.Height = (sal_Int32)nHeight; 1039 1040 return aResult; 1041 } 1042 1043 //---------------------------------------------- 1044 void OleComponent::CloseObject() 1045 { 1046 if ( m_pNativeImpl->m_pOleObject && OleIsRunning( m_pNativeImpl->m_pOleObject ) ) 1047 m_pNativeImpl->m_pOleObject->Close( OLECLOSE_NOSAVE ); // must be saved before 1048 } 1049 1050 //---------------------------------------------- 1051 uno::Sequence< embed::VerbDescriptor > OleComponent::GetVerbList() 1052 { 1053 if ( !m_pNativeImpl->m_pOleObject ) 1054 throw embed::WrongStateException(); // TODO: the object is in wrong state 1055 1056 if( !m_aVerbList.getLength() ) 1057 { 1058 ComSmart< IEnumOLEVERB > pEnum; 1059 if( SUCCEEDED( m_pNativeImpl->m_pOleObject->EnumVerbs( &pEnum ) ) ) 1060 { 1061 OLEVERB szEle[ MAX_ENUM_ELE ]; 1062 ULONG nNum = 0; 1063 sal_Int32 nSeqSize = 0; 1064 1065 do 1066 { 1067 HRESULT hr = pEnum->Next( MAX_ENUM_ELE, szEle, &nNum ); 1068 if( hr == S_OK || hr == S_FALSE ) 1069 { 1070 m_aVerbList.realloc( nSeqSize += nNum ); 1071 for( sal_uInt32 nInd = 0; nInd < nNum; nInd++ ) 1072 { 1073 m_aVerbList[nSeqSize-nNum+nInd].VerbID = szEle[ nInd ].lVerb; 1074 m_aVerbList[nSeqSize-nNum+nInd].VerbName = WinAccToVcl_Impl( reinterpret_cast<const sal_Unicode*>(szEle[ nInd ].lpszVerbName) ); 1075 m_aVerbList[nSeqSize-nNum+nInd].VerbFlags = szEle[ nInd ].fuFlags; 1076 m_aVerbList[nSeqSize-nNum+nInd].VerbAttributes = szEle[ nInd ].grfAttribs; 1077 } 1078 } 1079 else 1080 break; 1081 } 1082 while( nNum == MAX_ENUM_ELE ); 1083 } 1084 } 1085 1086 return m_aVerbList; 1087 } 1088 1089 //---------------------------------------------- 1090 void OleComponent::ExecuteVerb( sal_Int32 nVerbID ) 1091 { 1092 if ( !m_pNativeImpl->m_pOleObject ) 1093 throw embed::WrongStateException(); // TODO 1094 1095 HRESULT hr = OleRun( m_pNativeImpl->m_pOleObject ); 1096 if ( FAILED( hr ) ) 1097 throw io::IOException(); // TODO: a specific exception that transport error code can be thrown here 1098 1099 // TODO: probably extents should be set here and stored in aRect 1100 // TODO: probably the parent window also should be set 1101 hr = m_pNativeImpl->m_pOleObject->DoVerb( nVerbID, NULL, m_pOleWrapClientSite, 0, NULL, NULL ); 1102 1103 if ( FAILED( hr ) ) 1104 throw io::IOException(); // TODO 1105 1106 // TODO/LATER: the real names should be used here 1107 m_pNativeImpl->m_pOleObject->SetHostNames( L"app name", L"untitled" ); 1108 } 1109 1110 //---------------------------------------------- 1111 void OleComponent::SetHostName( const ::rtl::OUString&, 1112 const ::rtl::OUString& ) 1113 { 1114 if ( !m_pNativeImpl->m_pOleObject ) 1115 throw embed::WrongStateException(); // TODO: the object is in wrong state 1116 1117 // TODO: use aContName and aEmbDocName in m_pNativeImpl->m_pOleObject->SetHostNames() 1118 } 1119 1120 //---------------------------------------------- 1121 void OleComponent::SetExtent( const awt::Size& aVisAreaSize, sal_Int64 nAspect ) 1122 { 1123 if ( !m_pNativeImpl->m_pOleObject ) 1124 throw embed::WrongStateException(); // TODO: the object is in wrong state 1125 1126 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects 1127 1128 SIZEL aSize = { aVisAreaSize.Width, aVisAreaSize.Height }; 1129 HRESULT hr = m_pNativeImpl->m_pOleObject->SetExtent( nMSAspect, &aSize ); 1130 1131 if ( FAILED( hr ) ) 1132 { 1133 // TODO/LATER: is it correct? In future user code probably should be ready for the exception. 1134 // if the object is running but not activated, RPC_E_SERVER_DIED error code is returned by OLE package 1135 // in this case just do nothing 1136 // Also Visio returns E_FAIL on resize if it is in running state 1137 // if ( hr != RPC_E_SERVER_DIED ) 1138 throw io::IOException(); // TODO 1139 } 1140 } 1141 1142 //---------------------------------------------- 1143 awt::Size OleComponent::GetExtent( sal_Int64 nAspect ) 1144 { 1145 if ( !m_pNativeImpl->m_pOleObject ) 1146 throw embed::WrongStateException(); // TODO: the object is in wrong state 1147 1148 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects 1149 awt::Size aSize; 1150 sal_Bool bGotSize = sal_False; 1151 1152 if ( nMSAspect == DVASPECT_CONTENT ) 1153 { 1154 // Try to get the size from the replacement image first 1155 ComSmart< IDataObject > pDataObject; 1156 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject ); 1157 if ( SUCCEEDED( hr ) || pDataObject ) 1158 { 1159 STGMEDIUM aMedium; 1160 FORMATETC aFormat = pFormatTemplates[1]; // use windows metafile format 1161 aFormat.dwAspect = nMSAspect; 1162 1163 hr = pDataObject->GetData( &aFormat, &aMedium ); 1164 if ( SUCCEEDED( hr ) && aMedium.tymed == TYMED_MFPICT ) // Win Metafile 1165 { 1166 METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict ); 1167 if ( pMF ) 1168 { 1169 // the object uses 0.01 mm as unit, so the metafile size should be converted to object unit 1170 sal_Int64 nMult = 1; 1171 sal_Int64 nDiv = 1; 1172 switch( pMF->mm ) 1173 { 1174 case MM_HIENGLISH: 1175 nMult = 254; 1176 nDiv = 100; 1177 break; 1178 1179 case MM_LOENGLISH: 1180 nMult = 254; 1181 nDiv = 10; 1182 break; 1183 1184 case MM_LOMETRIC: 1185 nMult = 10; 1186 break; 1187 1188 case MM_TWIPS: 1189 nMult = 254; 1190 nDiv = 144; 1191 break; 1192 1193 case MM_ISOTROPIC: 1194 case MM_ANISOTROPIC: 1195 case MM_HIMETRIC: 1196 // do nothing 1197 break; 1198 } 1199 1200 sal_Int64 nX = ( (sal_Int64)abs( pMF->xExt ) ) * nMult / nDiv; 1201 sal_Int64 nY = ( (sal_Int64)abs( pMF->yExt ) ) * nMult / nDiv; 1202 if ( nX < SAL_MAX_INT32 && nY < SAL_MAX_INT32 ) 1203 { 1204 aSize.Width = ( sal_Int32 )nX; 1205 aSize.Height = ( sal_Int32 )nY; 1206 bGotSize = sal_True; 1207 } 1208 else 1209 OSL_ENSURE( sal_False, "Unexpected size is provided!" ); 1210 } 1211 } 1212 } 1213 } 1214 1215 if ( !bGotSize ) 1216 throw lang::IllegalArgumentException(); 1217 1218 return aSize; 1219 } 1220 1221 //---------------------------------------------- 1222 awt::Size OleComponent::GetCachedExtent( sal_Int64 nAspect ) 1223 { 1224 if ( !m_pNativeImpl->m_pOleObject ) 1225 throw embed::WrongStateException(); // TODO: the object is in wrong state 1226 1227 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects 1228 SIZEL aSize; 1229 1230 HRESULT hr = m_pNativeImpl->m_pViewObject2->GetExtent( nMSAspect, -1, NULL, &aSize ); 1231 1232 if ( FAILED( hr ) ) 1233 { 1234 // TODO/LATER: is it correct? 1235 // if there is no appropriate cache for the aspect, OLE_E_BLANK error code is returned 1236 // if ( hr == OLE_E_BLANK ) 1237 // throw lang::IllegalArgumentException(); 1238 //else 1239 // throw io::IOException(); // TODO 1240 1241 throw lang::IllegalArgumentException(); 1242 } 1243 1244 return awt::Size( aSize.cx, aSize.cy ); 1245 } 1246 1247 //---------------------------------------------- 1248 awt::Size OleComponent::GetReccomendedExtent( sal_Int64 nAspect ) 1249 { 1250 if ( !m_pNativeImpl->m_pOleObject ) 1251 throw embed::WrongStateException(); // TODO: the object is in wrong state 1252 1253 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects 1254 SIZEL aSize; 1255 HRESULT hr = m_pNativeImpl->m_pOleObject->GetExtent( nMSAspect, &aSize ); 1256 if ( FAILED( hr ) ) 1257 throw lang::IllegalArgumentException(); 1258 1259 return awt::Size( aSize.cx, aSize.cy ); 1260 } 1261 1262 //---------------------------------------------- 1263 sal_Int64 OleComponent::GetMiscStatus( sal_Int64 nAspect ) 1264 { 1265 if ( !m_pNativeImpl->m_pOleObject ) 1266 throw embed::WrongStateException(); // TODO: the object is in wrong state 1267 1268 sal_uInt32 nResult; 1269 m_pNativeImpl->m_pOleObject->GetMiscStatus( ( DWORD )nAspect, ( DWORD* )&nResult ); 1270 return ( sal_Int64 )nResult; // first 32 bits are for MS flags 1271 } 1272 1273 //---------------------------------------------- 1274 uno::Sequence< sal_Int8 > OleComponent::GetCLSID() 1275 { 1276 if ( !m_pNativeImpl->m_pOleObject ) 1277 throw embed::WrongStateException(); // TODO: the object is in wrong state 1278 1279 GUID aCLSID; 1280 HRESULT hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID ); 1281 if ( FAILED( hr ) ) 1282 throw io::IOException(); // TODO: 1283 1284 return MimeConfigurationHelper::GetSequenceClassID( aCLSID.Data1, aCLSID.Data2, aCLSID.Data3, 1285 aCLSID.Data4[0], aCLSID.Data4[1], 1286 aCLSID.Data4[2], aCLSID.Data4[3], 1287 aCLSID.Data4[4], aCLSID.Data4[5], 1288 aCLSID.Data4[6], aCLSID.Data4[7] ); 1289 } 1290 1291 //---------------------------------------------- 1292 sal_Bool OleComponent::IsDirty() 1293 { 1294 if ( !m_pNativeImpl->m_pOleObject ) 1295 throw embed::WrongStateException(); // TODO: the object is in wrong state 1296 1297 if ( IsWorkaroundActive() ) 1298 return sal_True; 1299 1300 ComSmart< IPersistStorage > pPersistStorage; 1301 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage ); 1302 if ( FAILED( hr ) || !pPersistStorage ) 1303 throw io::IOException(); // TODO 1304 1305 hr = pPersistStorage->IsDirty(); 1306 return ( hr != S_FALSE ); 1307 } 1308 1309 //---------------------------------------------- 1310 void OleComponent::StoreOwnTmpIfNecessary() 1311 { 1312 if ( !m_pNativeImpl->m_pOleObject ) 1313 throw embed::WrongStateException(); // TODO: the object is in wrong state 1314 1315 ComSmart< IPersistStorage > pPersistStorage; 1316 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage ); 1317 if ( FAILED( hr ) || !pPersistStorage ) 1318 throw io::IOException(); // TODO 1319 1320 if ( m_bWorkaroundActive || pPersistStorage->IsDirty() != S_FALSE ) 1321 { 1322 hr = OleSave( pPersistStorage, m_pNativeImpl->m_pIStorage, TRUE ); 1323 if ( FAILED( hr ) ) 1324 { 1325 // Till now was required only for AcrobatReader7.0.8 1326 GUID aCLSID; 1327 hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID ); 1328 if ( FAILED( hr ) ) 1329 throw io::IOException(); // TODO 1330 1331 hr = WriteClassStg( m_pNativeImpl->m_pIStorage, aCLSID ); 1332 if ( FAILED( hr ) ) 1333 throw io::IOException(); // TODO 1334 1335 // the result of the following call is not checked because some objects, for example AcrobatReader7.0.8 1336 // return error even in case the saving was done correctly 1337 hr = pPersistStorage->Save( m_pNativeImpl->m_pIStorage, TRUE ); 1338 1339 // another workaround for AcrobatReader7.0.8 object, this object might think that it is not changed 1340 // when it has been created from file, although it must be saved 1341 m_bWorkaroundActive = sal_True; 1342 } 1343 1344 hr = m_pNativeImpl->m_pIStorage->Commit( STGC_DEFAULT ); 1345 if ( FAILED( hr ) ) 1346 throw io::IOException(); // TODO 1347 1348 hr = pPersistStorage->SaveCompleted( NULL ); 1349 if ( FAILED( hr ) && hr != E_UNEXPECTED ) 1350 throw io::IOException(); // TODO 1351 1352 // STATSTG aStat; 1353 // m_pNativeImpl->m_pIStorage->Stat( &aStat, STATFLAG_NONAME ); 1354 } 1355 } 1356 1357 //---------------------------------------------- 1358 sal_Bool OleComponent::SaveObject_Impl() 1359 { 1360 sal_Bool bResult = sal_False; 1361 OleEmbeddedObject* pLockObject = NULL; 1362 1363 { 1364 osl::MutexGuard aGuard( m_aMutex ); 1365 if ( m_pUnoOleObject ) 1366 { 1367 pLockObject = m_pUnoOleObject; 1368 pLockObject->acquire(); 1369 } 1370 } 1371 1372 if ( pLockObject ) 1373 { 1374 bResult = pLockObject->SaveObject_Impl(); 1375 pLockObject->release(); 1376 } 1377 1378 return bResult; 1379 } 1380 1381 //---------------------------------------------- 1382 sal_Bool OleComponent::OnShowWindow_Impl( bool bShow ) 1383 { 1384 sal_Bool bResult = sal_False; 1385 OleEmbeddedObject* pLockObject = NULL; 1386 1387 { 1388 osl::MutexGuard aGuard( m_aMutex ); 1389 1390 if ( m_pUnoOleObject ) 1391 { 1392 pLockObject = m_pUnoOleObject; 1393 pLockObject->acquire(); 1394 } 1395 } 1396 1397 if ( pLockObject ) 1398 { 1399 bResult = pLockObject->OnShowWindow_Impl( bShow ); 1400 pLockObject->release(); 1401 } 1402 1403 return bResult; 1404 } 1405 1406 //---------------------------------------------- 1407 void OleComponent::OnViewChange_Impl( sal_uInt32 dwAspect ) 1408 { 1409 // TODO: check if it is enough or may be saving notifications are required for Visio2000 1410 ::rtl::Reference< OleEmbeddedObject > xLockObject; 1411 1412 { 1413 osl::MutexGuard aGuard( m_aMutex ); 1414 if ( m_pUnoOleObject ) 1415 xLockObject = m_pUnoOleObject; 1416 } 1417 1418 if ( xLockObject.is() ) 1419 { 1420 uno::Reference < awt::XRequestCallback > xRequestCallback( 1421 m_xFactory->createInstance( 1422 ::rtl::OUString::createFromAscii("com.sun.star.awt.AsyncCallback") ), 1423 uno::UNO_QUERY ); 1424 xRequestCallback->addCallback( new MainThreadNotificationRequest( xLockObject, OLECOMP_ONVIEWCHANGE, dwAspect ), uno::Any() ); 1425 } 1426 } 1427 1428 //---------------------------------------------- 1429 void OleComponent::OnClose_Impl() 1430 { 1431 ::rtl::Reference< OleEmbeddedObject > xLockObject; 1432 1433 { 1434 osl::MutexGuard aGuard( m_aMutex ); 1435 if ( m_pUnoOleObject ) 1436 xLockObject = m_pUnoOleObject; 1437 } 1438 1439 if ( xLockObject.is() ) 1440 { 1441 uno::Reference < awt::XRequestCallback > xRequestCallback( 1442 m_xFactory->createInstance( 1443 ::rtl::OUString::createFromAscii("com.sun.star.awt.AsyncCallback") ), 1444 uno::UNO_QUERY ); 1445 xRequestCallback->addCallback( new MainThreadNotificationRequest( xLockObject, OLECOMP_ONCLOSE ), uno::Any() ); 1446 } 1447 } 1448 1449 // XCloseable 1450 //---------------------------------------------- 1451 void SAL_CALL OleComponent::close( sal_Bool bDeliverOwnership ) 1452 throw ( util::CloseVetoException, 1453 uno::RuntimeException ) 1454 { 1455 ::osl::MutexGuard aGuard( m_aMutex ); 1456 if ( m_bDisposed ) 1457 throw lang::DisposedException(); // TODO 1458 1459 uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) ); 1460 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) ); 1461 1462 if ( m_pInterfaceContainer ) 1463 { 1464 ::cppu::OInterfaceContainerHelper* pContainer = 1465 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) ); 1466 if ( pContainer != NULL ) 1467 { 1468 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer ); 1469 while ( pIterator.hasMoreElements() ) 1470 { 1471 try 1472 { 1473 ( (util::XCloseListener* )pIterator.next() )->queryClosing( aSource, bDeliverOwnership ); 1474 } 1475 catch( uno::RuntimeException& ) 1476 { 1477 pIterator.remove(); 1478 } 1479 } 1480 } 1481 1482 pContainer = m_pInterfaceContainer->getContainer( 1483 ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) ); 1484 if ( pContainer != NULL ) 1485 { 1486 ::cppu::OInterfaceIteratorHelper pCloseIterator( *pContainer ); 1487 while ( pCloseIterator.hasMoreElements() ) 1488 { 1489 try 1490 { 1491 ( (util::XCloseListener* )pCloseIterator.next() )->notifyClosing( aSource ); 1492 } 1493 catch( uno::RuntimeException& ) 1494 { 1495 pCloseIterator.remove(); 1496 } 1497 } 1498 } 1499 } 1500 1501 Dispose(); 1502 } 1503 1504 //---------------------------------------------- 1505 void SAL_CALL OleComponent::addCloseListener( const uno::Reference< util::XCloseListener >& xListener ) 1506 throw ( uno::RuntimeException ) 1507 { 1508 ::osl::MutexGuard aGuard( m_aMutex ); 1509 if ( m_bDisposed ) 1510 throw lang::DisposedException(); // TODO 1511 1512 if ( !m_pInterfaceContainer ) 1513 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); 1514 1515 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ), xListener ); 1516 } 1517 1518 //---------------------------------------------- 1519 void SAL_CALL OleComponent::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener ) 1520 throw ( uno::RuntimeException ) 1521 { 1522 ::osl::MutexGuard aGuard( m_aMutex ); 1523 if ( m_bDisposed ) 1524 throw lang::DisposedException(); // TODO 1525 1526 if ( m_pInterfaceContainer ) 1527 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ), 1528 xListener ); 1529 } 1530 1531 // XTransferable 1532 //---------------------------------------------- 1533 uno::Any SAL_CALL OleComponent::getTransferData( const datatransfer::DataFlavor& aFlavor ) 1534 throw ( datatransfer::UnsupportedFlavorException, 1535 io::IOException, 1536 uno::RuntimeException ) 1537 { 1538 ::osl::MutexGuard aGuard( m_aMutex ); 1539 if ( m_bDisposed ) 1540 throw lang::DisposedException(); // TODO 1541 1542 if ( !m_pNativeImpl->m_pOleObject ) 1543 throw embed::WrongStateException(); // TODO: the object is in wrong state 1544 1545 uno::Any aResult; 1546 sal_Bool bSupportedFlavor = sal_False; 1547 1548 if ( m_pNativeImpl->GraphicalFlavor( aFlavor ) ) 1549 { 1550 DWORD nRequestedAspect = GetAspectFromFlavor( aFlavor ); 1551 // if own icon is set and icon aspect is requested the own icon can be returned directly 1552 1553 ComSmart< IDataObject > pDataObject; 1554 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject ); 1555 if ( FAILED( hr ) || !pDataObject ) 1556 throw io::IOException(); // TODO: transport error code 1557 1558 // The following optimization does not make much sence currently just because 1559 // only one aspect is supported, and only three formats for the aspect are supported 1560 // and moreover it is not guarantied that the once returned format will be supported further 1561 // example - i52106 1562 // TODO/LATER: bring the optimization back when other aspects are supported 1563 1564 // FORMATETC* pFormatEtc = m_pNativeImpl->GetSupportedFormatForAspect( nRequestedAspect ); 1565 // if ( pFormatEtc ) 1566 // { 1567 // STGMEDIUM aMedium; 1568 // hr = pDataObject->GetData( pFormatEtc, &aMedium ); 1569 // if ( SUCCEEDED( hr ) ) 1570 // bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult ); 1571 // } 1572 // else 1573 { 1574 // the supported format of the application is still not found, find one 1575 for ( sal_Int32 nInd = 0; nInd < FORMATS_NUM; nInd++ ) 1576 { 1577 STGMEDIUM aMedium; 1578 FORMATETC aFormat = pFormatTemplates[nInd]; 1579 aFormat.dwAspect = nRequestedAspect; 1580 1581 hr = pDataObject->GetData( &aFormat, &aMedium ); 1582 if ( SUCCEEDED( hr ) ) 1583 { 1584 bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult ); 1585 if ( bSupportedFlavor ) 1586 { 1587 // TODO/LATER: bring the optimization back when other aspects are supported 1588 // m_pNativeImpl->AddSupportedFormat( aFormat ); 1589 break; 1590 } 1591 } 1592 } 1593 } 1594 1595 // If the replacement could not be retrieved, the cached representaion should be used 1596 // currently it is not necessary to retrieve it here, so it is implemented in the object itself 1597 } 1598 // TODO: Investigate if there is already the format name 1599 // and whether this format is really required 1600 else if ( aFlavor.DataType == getCppuType( ( const uno::Reference< io::XInputStream >* ) 0 ) 1601 && aFlavor.MimeType.equalsAscii( "application/x-openoffice-contentstream" ) ) 1602 { 1603 // allow to retrieve stream-representation of the object persistence 1604 bSupportedFlavor = sal_True; 1605 uno::Reference < io::XStream > xTempFileStream( 1606 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 1607 uno::UNO_QUERY ); 1608 1609 if ( !xTempFileStream.is() ) 1610 throw uno::RuntimeException(); // TODO 1611 1612 uno::Reference< io::XOutputStream > xTempOutStream = xTempFileStream->getOutputStream(); 1613 uno::Reference< io::XInputStream > xTempInStream = xTempFileStream->getInputStream(); 1614 if ( xTempOutStream.is() && xTempInStream.is() ) 1615 { 1616 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" ); 1617 if ( !m_pUnoOleObject ) 1618 throw uno::RuntimeException(); 1619 1620 m_pUnoOleObject->StoreObjectToStream( xTempOutStream ); 1621 1622 xTempOutStream->closeOutput(); 1623 xTempOutStream = uno::Reference< io::XOutputStream >(); 1624 } 1625 else 1626 throw io::IOException(); // TODO: 1627 1628 aResult <<= xTempInStream; 1629 } 1630 1631 if ( !bSupportedFlavor ) 1632 throw datatransfer::UnsupportedFlavorException(); 1633 1634 return aResult; 1635 } 1636 1637 //---------------------------------------------- 1638 uno::Sequence< datatransfer::DataFlavor > SAL_CALL OleComponent::getTransferDataFlavors() 1639 throw ( uno::RuntimeException ) 1640 { 1641 ::osl::MutexGuard aGuard( m_aMutex ); 1642 if ( m_bDisposed ) 1643 throw lang::DisposedException(); // TODO 1644 1645 if ( !m_pNativeImpl->m_pOleObject ) 1646 throw embed::WrongStateException(); // TODO: the object is in wrong state 1647 1648 RetrieveObjectDataFlavors_Impl(); 1649 1650 return m_aDataFlavors; 1651 } 1652 1653 //---------------------------------------------- 1654 sal_Bool SAL_CALL OleComponent::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor ) 1655 throw ( uno::RuntimeException ) 1656 { 1657 ::osl::MutexGuard aGuard( m_aMutex ); 1658 if ( m_bDisposed ) 1659 throw lang::DisposedException(); // TODO 1660 1661 if ( !m_pNativeImpl->m_pOleObject ) 1662 throw embed::WrongStateException(); // TODO: the object is in wrong state 1663 1664 if ( !m_aDataFlavors.getLength() ) 1665 { 1666 RetrieveObjectDataFlavors_Impl(); 1667 } 1668 1669 for ( sal_Int32 nInd = 0; nInd < m_aDataFlavors.getLength(); nInd++ ) 1670 if ( m_aDataFlavors[nInd].MimeType.equals( aFlavor.MimeType ) && m_aDataFlavors[nInd].DataType == aFlavor.DataType ) 1671 return sal_True; 1672 1673 return sal_False; 1674 } 1675 1676 void SAL_CALL OleComponent::dispose() throw (::com::sun::star::uno::RuntimeException) 1677 { 1678 try 1679 { 1680 close( sal_True ); 1681 } 1682 catch ( uno::Exception& ) 1683 { 1684 } 1685 } 1686 1687 void SAL_CALL OleComponent::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) 1688 throw ( uno::RuntimeException ) 1689 { 1690 ::osl::MutexGuard aGuard( m_aMutex ); 1691 if ( m_bDisposed ) 1692 throw lang::DisposedException(); // TODO 1693 1694 if ( !m_pInterfaceContainer ) 1695 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); 1696 1697 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ), xListener ); 1698 } 1699 1700 //---------------------------------------------- 1701 void SAL_CALL OleComponent::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) 1702 throw ( uno::RuntimeException ) 1703 { 1704 ::osl::MutexGuard aGuard( m_aMutex ); 1705 if ( m_bDisposed ) 1706 throw lang::DisposedException(); // TODO 1707 1708 if ( m_pInterfaceContainer ) 1709 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ), 1710 xListener ); 1711 } 1712 1713 sal_Int64 SAL_CALL OleComponent::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException) 1714 { 1715 try 1716 { 1717 uno::Sequence < sal_Int8 > aCLSID = GetCLSID(); 1718 if ( MimeConfigurationHelper::ClassIDsEqual( aIdentifier, aCLSID ) ) 1719 return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj; 1720 1721 // compatibility hack for old versions: CLSID was used in wrong order (SvGlobalName order) 1722 sal_Int32 nLength = aIdentifier.getLength(); 1723 if ( nLength == 16 ) 1724 { 1725 for ( sal_Int32 n=8; n<16; n++ ) 1726 if ( aIdentifier[n] != aCLSID[n] ) 1727 return 0; 1728 if ( aIdentifier[7] == aCLSID[6] && 1729 aIdentifier[6] == aCLSID[7] && 1730 aIdentifier[5] == aCLSID[4] && 1731 aIdentifier[4] == aCLSID[5] && 1732 aIdentifier[3] == aCLSID[0] && 1733 aIdentifier[2] == aCLSID[1] && 1734 aIdentifier[1] == aCLSID[2] && 1735 aIdentifier[0] == aCLSID[3] ) 1736 return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj; 1737 } 1738 } 1739 catch ( uno::Exception& ) 1740 { 1741 } 1742 1743 return 0; 1744 } 1745 1746 sal_Bool SAL_CALL OleComponent::isModified() throw (::com::sun::star::uno::RuntimeException) 1747 { 1748 return m_bModified; 1749 } 1750 1751 void SAL_CALL OleComponent::setModified( sal_Bool bModified ) 1752 throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException) 1753 { 1754 m_bModified = bModified; 1755 1756 if ( bModified && m_pInterfaceContainer ) 1757 { 1758 ::cppu::OInterfaceContainerHelper* pContainer = 1759 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XModifyListener >* ) NULL ) ); 1760 if ( pContainer != NULL ) 1761 { 1762 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer ); 1763 while ( pIterator.hasMoreElements() ) 1764 { 1765 try 1766 { 1767 lang::EventObject aEvent( (util::XModifiable*) this ); 1768 ((util::XModifyListener*)pIterator.next())->modified( aEvent ); 1769 } 1770 catch( uno::RuntimeException& ) 1771 { 1772 pIterator.remove(); 1773 } 1774 } 1775 } 1776 } 1777 } 1778 1779 void SAL_CALL OleComponent::addModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener ) throw(::com::sun::star::uno::RuntimeException) 1780 { 1781 ::osl::MutexGuard aGuard( m_aMutex ); 1782 if ( m_bDisposed ) 1783 throw lang::DisposedException(); // TODO 1784 1785 if ( !m_pInterfaceContainer ) 1786 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); 1787 1788 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ), xListener ); 1789 } 1790 1791 void SAL_CALL OleComponent::removeModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener) throw(::com::sun::star::uno::RuntimeException) 1792 { 1793 ::osl::MutexGuard aGuard( m_aMutex ); 1794 if ( m_bDisposed ) 1795 throw lang::DisposedException(); // TODO 1796 1797 if ( m_pInterfaceContainer ) 1798 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ), 1799 xListener ); 1800 } 1801 1802