Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / embeddedobj / source / msole / olecomponent.cxx
blob1bbec2121ca2eb3ca9f61a20199c9f9ec7325f7c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/lang/IllegalArgumentException.hpp>
21 #include <com/sun/star/lang/DisposedException.hpp>
22 #include <com/sun/star/embed/WrongStateException.hpp>
23 #include <com/sun/star/embed/UnreachableStateException.hpp>
24 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/io/TempFile.hpp>
27 #include <com/sun/star/io/XTruncate.hpp>
28 #include <com/sun/star/awt/XRequestCallback.hpp>
30 #include <platform.h>
31 #include <cppuhelper/interfacecontainer.h>
32 #include <comphelper/mimeconfighelper.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/storagehelper.hxx>
35 #include <osl/file.hxx>
36 #include <rtl/ref.hxx>
38 #include <olecomponent.hxx>
39 #include <olewrapclient.hxx>
40 #include <advisesink.hxx>
41 #include <oleembobj.hxx>
42 #include <mtnotification.hxx>
44 using namespace ::com::sun::star;
45 using namespace ::comphelper;
46 #define MAX_ENUM_ELE 20
47 #define FORMATS_NUM 3
49 // ============ class ComSmart =====================
50 namespace {
52 template< class T > class ComSmart
54 T* m_pInterface;
56 void OwnRelease()
58 if ( m_pInterface )
60 T* pInterface = m_pInterface;
61 m_pInterface = NULL;
62 pInterface->Release();
66 public:
67 ComSmart()
68 : m_pInterface( NULL )
71 ComSmart( const ComSmart<T>& rObj )
72 : m_pInterface( rObj.m_pInterface )
74 if ( m_pInterface != NULL )
75 m_pInterface->AddRef();
78 ComSmart( T* pInterface )
79 : m_pInterface( pInterface )
81 if ( m_pInterface != NULL )
82 m_pInterface->AddRef();
85 ~ComSmart()
87 OwnRelease();
90 ComSmart& operator=( const ComSmart<T>& rObj )
92 OwnRelease();
94 m_pInterface = rObj.m_pInterface;
96 if ( m_pInterface != NULL )
97 m_pInterface->AddRef();
99 return *this;
102 ComSmart<T>& operator=( T* pInterface )
104 OwnRelease();
106 m_pInterface = pInterface;
108 if ( m_pInterface != NULL )
109 m_pInterface->AddRef();
111 return *this;
114 operator T*() const
116 return m_pInterface;
119 T& operator*() const
121 return *m_pInterface;
124 T** operator&()
126 OwnRelease();
128 m_pInterface = NULL;
130 return &m_pInterface;
133 T* operator->() const
135 return m_pInterface;
138 BOOL operator==( const ComSmart<T>& rObj ) const
140 return ( m_pInterface == rObj.m_pInterface );
143 BOOL operator!=( const ComSmart<T>& rObj ) const
145 return ( m_pInterface != rObj.m_pInterface );
148 BOOL operator==( const T* pInterface ) const
150 return ( m_pInterface == pInterface );
153 BOOL operator!=( const T* pInterface ) const
155 return ( m_pInterface != pInterface );
161 // ============ class ComSmart =====================
163 sal_Bool ConvertBufferToFormat( void* pBuf,
164 sal_uInt32 nBufSize,
165 const OUString& aFormatShortName,
166 uno::Any& aResult );
168 OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException );
170 typedef ::std::vector< FORMATETC* > FormatEtcList;
172 FORMATETC pFormatTemplates[FORMATS_NUM] = {
173 { CF_ENHMETAFILE, NULL, 0, -1, TYMED_ENHMF },
174 { CF_METAFILEPICT, NULL, 0, -1, TYMED_MFPICT },
175 { CF_BITMAP, NULL, 0, -1, TYMED_GDI } };
178 struct OleComponentNative_Impl {
179 ComSmart< IUnknown > m_pObj;
180 ComSmart< IOleObject > m_pOleObject;
181 ComSmart< IViewObject2 > m_pViewObject2;
182 ComSmart< IStorage > m_pIStorage;
183 FormatEtcList m_aFormatsList;
184 uno::Sequence< datatransfer::DataFlavor > m_aSupportedGraphFormats;
186 OleComponentNative_Impl()
188 // TODO: Extend format list
189 m_aSupportedGraphFormats.realloc( 5 );
191 m_aSupportedGraphFormats[0] = datatransfer::DataFlavor(
192 OUString( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ),
193 OUString( "Windows Enhanced Metafile" ),
194 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
196 m_aSupportedGraphFormats[1] = datatransfer::DataFlavor(
197 OUString( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ),
198 OUString( "Windows Metafile" ),
199 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
201 m_aSupportedGraphFormats[2] = datatransfer::DataFlavor(
202 OUString( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ),
203 OUString( "Bitmap" ),
204 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
206 m_aSupportedGraphFormats[3] = datatransfer::DataFlavor(
207 OUString( "image/png" ),
208 OUString( "PNG" ),
209 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
211 m_aSupportedGraphFormats[0] = datatransfer::DataFlavor(
212 OUString( "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
213 OUString( "GDIMetafile" ),
214 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
217 void AddSupportedFormat( const FORMATETC& aFormatEtc );
219 FORMATETC* GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect );
221 sal_Bool ConvertDataForFlavor( const STGMEDIUM& aMedium,
222 const datatransfer::DataFlavor& aFlavor,
223 uno::Any& aResult );
225 sal_Bool GraphicalFlavor( const datatransfer::DataFlavor& aFlavor );
227 uno::Sequence< datatransfer::DataFlavor > GetFlavorsForAspects( sal_uInt32 nSupportedAspects );
230 //----------------------------------------------
231 DWORD GetAspectFromFlavor( const datatransfer::DataFlavor& aFlavor )
233 if ( aFlavor.MimeType.indexOf( ";Aspect=THUMBNAIL" ) != -1 )
234 return DVASPECT_THUMBNAIL;
235 else if ( aFlavor.MimeType.indexOf( ";Aspect=ICON" ) != -1 )
236 return DVASPECT_ICON;
237 else if ( aFlavor.MimeType.indexOf( ";Aspect=DOCPRINT" ) != -1 )
238 return DVASPECT_DOCPRINT;
239 else
240 return DVASPECT_CONTENT;
243 //----------------------------------------------
244 OUString GetFlavorSuffixFromAspect( DWORD nAsp )
246 OUString aResult;
248 if ( nAsp == DVASPECT_THUMBNAIL )
249 aResult = ";Aspect=THUMBNAIL";
250 else if ( nAsp == DVASPECT_ICON )
251 aResult = ";Aspect=ICON";
252 else if ( nAsp == DVASPECT_DOCPRINT )
253 aResult = ";Aspect=DOCPRINT";
255 // no suffix for DVASPECT_CONTENT
257 return aResult;
260 //----------------------------------------------
261 HRESULT OpenIStorageFromURL_Impl( const OUString& aURL, IStorage** ppIStorage )
263 OSL_ENSURE( ppIStorage, "The pointer must not be empty!" );
265 OUString aFilePath;
266 if ( !ppIStorage || ::osl::FileBase::getSystemPathFromFileURL( aURL, aFilePath ) != ::osl::FileBase::E_None )
267 throw uno::RuntimeException(); // TODO: something dangerous happened
269 return StgOpenStorage( reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
270 NULL,
271 STGM_READWRITE | STGM_TRANSACTED, // | STGM_DELETEONRELEASE,
272 NULL,
274 ppIStorage );
277 //----------------------------------------------
278 sal_Bool OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM& aMedium,
279 const datatransfer::DataFlavor& aFlavor,
280 uno::Any& aResult )
282 sal_Bool bAnyIsReady = sal_False;
284 // try to convert data from Medium format to specified Flavor format
285 if ( aFlavor.DataType == getCppuType( ( const uno::Sequence< sal_Int8 >* ) 0 ) )
287 // first the GDI-metafile must be generated
289 unsigned char* pBuf = NULL;
290 sal_uInt32 nBufSize = 0;
291 OUString aFormat;
293 if ( aMedium.tymed == TYMED_MFPICT ) // Win Metafile
295 aFormat = "image/x-wmf";
296 METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict );
297 if ( pMF )
299 nBufSize = GetMetaFileBitsEx( pMF->hMF, 0, NULL ) + 22;
300 pBuf = new unsigned char[nBufSize];
303 // TODO/LATER: the unit size must be calculated correctly
304 *( (long* )pBuf ) = 0x9ac6cdd7L;
305 *( (short* )( pBuf+6 )) = ( SHORT ) 0;
306 *( (short* )( pBuf+8 )) = ( SHORT ) 0;
307 *( (short* )( pBuf+10 )) = ( SHORT ) pMF->xExt;
308 *( (short* )( pBuf+12 )) = ( SHORT ) pMF->yExt;
309 *( (short* )( pBuf+14 )) = ( USHORT ) 2540;
312 if ( nBufSize && nBufSize == GetMetaFileBitsEx( pMF->hMF, nBufSize - 22, pBuf + 22 ) )
314 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"", 57 ) )
316 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
317 bAnyIsReady = sal_True;
321 GlobalUnlock( aMedium.hMetaFilePict );
324 else if ( aMedium.tymed == TYMED_ENHMF ) // Enh Metafile
326 aFormat = "image/x-emf";
327 nBufSize = GetEnhMetaFileBits( aMedium.hEnhMetaFile, 0, NULL );
328 pBuf = new unsigned char[nBufSize];
329 if ( nBufSize && nBufSize == GetEnhMetaFileBits( aMedium.hEnhMetaFile, nBufSize, pBuf ) )
331 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"", 57 ) )
333 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
334 bAnyIsReady = sal_True;
338 else if ( aMedium.tymed == TYMED_GDI ) // Bitmap
340 aFormat = "image/x-MS-bmp";
341 nBufSize = GetBitmapBits( aMedium.hBitmap, 0, NULL );
342 pBuf = new unsigned char[nBufSize];
343 if ( nBufSize && nBufSize == sal::static_int_cast< ULONG >( GetBitmapBits( aMedium.hBitmap, nBufSize, pBuf ) ) )
345 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"", 54 ) )
347 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
348 bAnyIsReady = sal_True;
353 if ( pBuf && !bAnyIsReady )
355 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
356 if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType )
357 && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType
358 && aFlavor.DataType == getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) )
360 bAnyIsReady = ConvertBufferToFormat( ( void* )pBuf, nBufSize, aFormat, aResult );
361 break;
365 delete[] pBuf;
368 return bAnyIsReady;
371 //----------------------------------------------
372 sal_Bool OleComponentNative_Impl::GraphicalFlavor( const datatransfer::DataFlavor& aFlavor )
374 // Actually all the required graphical formats must be supported
375 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
376 if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType )
377 && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType )
378 return sal_True;
380 return sal_False;
383 //----------------------------------------------
384 sal_Bool GetClassIDFromSequence_Impl( uno::Sequence< sal_Int8 > aSeq, CLSID& aResult )
386 if ( aSeq.getLength() == 16 )
388 aResult.Data1 = ( ( ( ( ( ( sal_uInt8 )aSeq[0] << 8 ) + ( sal_uInt8 )aSeq[1] ) << 8 ) + ( sal_uInt8 )aSeq[2] ) << 8 ) + ( sal_uInt8 )aSeq[3];
389 aResult.Data2 = ( ( sal_uInt8 )aSeq[4] << 8 ) + ( sal_uInt8 )aSeq[5];
390 aResult.Data3 = ( ( sal_uInt8 )aSeq[6] << 8 ) + ( sal_uInt8 )aSeq[7];
391 for( int nInd = 0; nInd < 8; nInd++ )
392 aResult.Data4[nInd] = ( sal_uInt8 )aSeq[nInd+8];
394 return sal_True;
397 return sal_False;
400 //----------------------------------------------
401 OUString WinAccToVcl_Impl( const sal_Unicode* pStr )
403 OUString aResult;
405 if( pStr )
407 while ( *pStr )
409 if ( *pStr == '&' )
411 aResult += "~";
412 while( *( ++pStr ) == '&' );
414 else
416 aResult += OUString( pStr, 1 );
417 pStr++;
422 return aResult;
425 //----------------------------------------------
426 OleComponent::OleComponent( const uno::Reference< lang::XMultiServiceFactory >& xFactory, OleEmbeddedObject* pUnoOleObject )
427 : m_pInterfaceContainer( NULL )
428 , m_bDisposed( sal_False )
429 , m_bModified( sal_False )
430 , m_pNativeImpl( new OleComponentNative_Impl() )
431 , m_pUnoOleObject( pUnoOleObject )
432 , m_pOleWrapClientSite( NULL )
433 , m_pImplAdviseSink( NULL )
434 , m_nOLEMiscFlags( 0 )
435 , m_nAdvConn( 0 )
436 , m_xFactory( xFactory )
437 , m_bOleInitialized( sal_False )
438 , m_bWorkaroundActive( sal_False )
440 OSL_ENSURE( m_pUnoOleObject, "No owner object is provided!" );
442 HRESULT hr = OleInitialize( NULL );
443 OSL_ENSURE( hr == S_OK || hr == S_FALSE, "The ole can not be successfully initialized\n" );
444 if ( hr == S_OK || hr == S_FALSE )
445 m_bOleInitialized = sal_True;
447 m_pOleWrapClientSite = new OleWrapperClientSite( ( OleComponent* )this );
448 m_pOleWrapClientSite->AddRef();
450 m_pImplAdviseSink = new OleWrapperAdviseSink( ( OleComponent* )this );
451 m_pImplAdviseSink->AddRef();
455 //----------------------------------------------
456 OleComponent::~OleComponent()
458 OSL_ENSURE( !m_pOleWrapClientSite && !m_pImplAdviseSink && !m_pInterfaceContainer && !m_bOleInitialized,
459 "The object was not closed successfully! DISASTER is possible!" );
461 if ( m_pOleWrapClientSite || m_pImplAdviseSink || m_pInterfaceContainer || m_bOleInitialized )
463 ::osl::MutexGuard aGuard( m_aMutex );
464 m_refCount++;
465 try {
466 Dispose();
467 } catch( const uno::Exception& ) {}
470 for ( FormatEtcList::iterator aIter = m_pNativeImpl->m_aFormatsList.begin();
471 aIter != m_pNativeImpl->m_aFormatsList.end();
472 ++aIter )
474 delete (*aIter);
475 (*aIter) = NULL;
477 m_pNativeImpl->m_aFormatsList.clear();
479 delete m_pNativeImpl;
482 //----------------------------------------------
483 void OleComponentNative_Impl::AddSupportedFormat( const FORMATETC& aFormatEtc )
485 FORMATETC* pFormatToInsert = new FORMATETC( aFormatEtc );
486 m_aFormatsList.push_back( pFormatToInsert );
489 //----------------------------------------------
490 FORMATETC* OleComponentNative_Impl::GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect )
492 for ( FormatEtcList::iterator aIter = m_aFormatsList.begin();
493 aIter != m_aFormatsList.end();
494 ++aIter )
495 if ( (*aIter) && (*aIter)->dwAspect == nRequestedAspect )
496 return (*aIter);
498 return NULL;
501 //----------------------------------------------
502 void OleComponent::Dispose()
504 // the mutex must be locked before this method is called
505 if ( m_bDisposed )
506 return;
508 CloseObject();
510 if ( m_pOleWrapClientSite )
512 m_pOleWrapClientSite->disconnectOleComponent();
513 m_pOleWrapClientSite->Release();
514 m_pOleWrapClientSite = NULL;
517 if ( m_pImplAdviseSink )
519 m_pImplAdviseSink->disconnectOleComponent();
520 m_pImplAdviseSink->Release();
521 m_pImplAdviseSink = NULL;
524 if ( m_pInterfaceContainer )
526 lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >( this ) );
527 m_pInterfaceContainer->disposeAndClear( aEvent );
529 delete m_pInterfaceContainer;
530 m_pInterfaceContainer = NULL;
533 if ( m_bOleInitialized )
535 // since the disposing can happen not only from main thread but also from a clipboard
536 // the deinitialization might lead to a disaster, SO7 does not deinitialize OLE at all
537 // so currently the same approach is selected as workaround
538 // OleUninitialize();
539 m_bOleInitialized = sal_False;
542 m_bDisposed = sal_True;
545 //----------------------------------------------
546 void OleComponent::disconnectEmbeddedObject()
548 // must not be called from destructor of UNO OLE object!!!
549 osl::MutexGuard aGuard( m_aMutex );
550 m_pUnoOleObject = NULL;
553 //----------------------------------------------
554 void OleComponent::CreateNewIStorage_Impl()
556 // TODO: in future a global memory could be used instead of file.
558 // write the stream to the temporary file
559 OUString aTempURL;
561 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
562 if ( m_pUnoOleObject )
563 aTempURL = m_pUnoOleObject->CreateTempURLEmpty_Impl();
564 else
565 aTempURL = GetNewTempFileURL_Impl( m_xFactory );
567 if ( !aTempURL.getLength() )
568 throw uno::RuntimeException(); // TODO
570 // open an IStorage based on the temporary file
571 OUString aTempFilePath;
572 if ( ::osl::FileBase::getSystemPathFromFileURL( aTempURL, aTempFilePath ) != ::osl::FileBase::E_None )
573 throw uno::RuntimeException(); // TODO: something dangerous happened
575 HRESULT hr = StgCreateDocfile( reinterpret_cast<LPCWSTR>(aTempFilePath.getStr()), STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED | STGM_DELETEONRELEASE, 0, &m_pNativeImpl->m_pIStorage );
576 if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
577 throw io::IOException(); // TODO: transport error code?
580 //----------------------------------------------
581 uno::Sequence< datatransfer::DataFlavor > OleComponentNative_Impl::GetFlavorsForAspects( sal_uInt32 nSupportedAspects )
583 uno::Sequence< datatransfer::DataFlavor > aResult;
584 for ( sal_uInt32 nAsp = 1; nAsp <= 8; nAsp *= 2 )
585 if ( ( nSupportedAspects & nAsp ) == nAsp )
587 OUString aAspectSuffix = GetFlavorSuffixFromAspect( nAsp );
589 sal_Int32 nLength = aResult.getLength();
590 aResult.realloc( nLength + m_aSupportedGraphFormats.getLength() );
592 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
594 aResult[nLength + nInd].MimeType = m_aSupportedGraphFormats[nInd].MimeType + aAspectSuffix;
595 aResult[nLength + nInd].HumanPresentableName = m_aSupportedGraphFormats[nInd].HumanPresentableName;
596 aResult[nLength + nInd].DataType = m_aSupportedGraphFormats[nInd].DataType;
600 return aResult;
603 //----------------------------------------------
604 void OleComponent::RetrieveObjectDataFlavors_Impl()
606 if ( !m_pNativeImpl->m_pOleObject )
607 throw embed::WrongStateException(); // TODO: the object is in wrong state
609 if ( !m_aDataFlavors.getLength() )
611 ComSmart< IDataObject > pDataObject;
612 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
613 if ( SUCCEEDED( hr ) && pDataObject )
615 ComSmart< IEnumFORMATETC > pFormatEnum;
616 hr = pDataObject->EnumFormatEtc( DATADIR_GET, &pFormatEnum );
617 if ( SUCCEEDED( hr ) && pFormatEnum )
619 FORMATETC pElem[ MAX_ENUM_ELE ];
620 ULONG nNum = 0;
622 // if it is possible to retrieve at least one supported graphical format for an aspect
623 // this format can be converted to other supported formats
624 sal_uInt32 nSupportedAspects = 0;
627 HRESULT hr2 = pFormatEnum->Next( MAX_ENUM_ELE, pElem, &nNum );
628 if( hr2 == S_OK || hr2 == S_FALSE )
630 for( sal_uInt32 nInd = 0; nInd < FORMATS_NUM; nInd++ )
632 if ( pElem[nInd].cfFormat == pFormatTemplates[nInd].cfFormat
633 && pElem[nInd].tymed == pFormatTemplates[nInd].tymed )
634 nSupportedAspects |= pElem[nInd].dwAspect;
637 else
638 break;
640 while( nNum == MAX_ENUM_ELE );
642 m_aDataFlavors = m_pNativeImpl->GetFlavorsForAspects( nSupportedAspects );
646 if ( !m_aDataFlavors.getLength() )
648 // TODO:
649 // for any reason the object could not provide this information
650 // try to get access to the cached representation
655 //----------------------------------------------
656 sal_Bool OleComponent::InitializeObject_Impl()
657 // There will be no static objects!
659 if ( !m_pNativeImpl->m_pObj )
660 return sal_False;
662 // the linked object will be detected here
663 ComSmart< IOleLink > pOleLink;
664 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink );
665 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
666 if ( m_pUnoOleObject )
667 m_pUnoOleObject->SetObjectIsLink_Impl( sal_Bool( pOleLink != NULL ) );
670 hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IViewObject2, (void**)&m_pNativeImpl->m_pViewObject2 );
671 if ( FAILED( hr ) || !m_pNativeImpl->m_pViewObject2 )
672 return sal_False;
675 // remove all the caches
676 IOleCache* pIOleCache = NULL;
677 if ( SUCCEEDED( m_pNativeImpl->m_pObj->QueryInterface( IID_IOleCache, (void**)&pIOleCache ) ) && pIOleCache )
679 IEnumSTATDATA* pEnumSD = NULL;
680 HRESULT hr2 = pIOleCache->EnumCache( &pEnumSD );
682 if ( SUCCEEDED( hr2 ) && pEnumSD )
684 pEnumSD->Reset();
685 STATDATA aSD;
686 DWORD nNum;
687 while( SUCCEEDED( pEnumSD->Next( 1, &aSD, &nNum ) ) && nNum == 1 )
688 hr2 = pIOleCache->Uncache( aSD.dwConnection );
691 // No IDataObject implementation, caching must be used instead
692 DWORD nConn;
693 FORMATETC aFormat = { 0, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT };
694 hr2 = pIOleCache->Cache( &aFormat, ADVFCACHE_ONSAVE, &nConn );
696 pIOleCache->Release();
697 pIOleCache = NULL;
700 hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleObject, (void**)&m_pNativeImpl->m_pOleObject );
701 if ( FAILED( hr ) || !m_pNativeImpl->m_pOleObject )
702 return sal_False; // Static objects are not supported, they should be inserted as graphics
704 m_pNativeImpl->m_pOleObject->GetMiscStatus( DVASPECT_CONTENT, ( DWORD* )&m_nOLEMiscFlags );
705 // TODO: use other misc flags also
706 // the object should have drawable aspect even in case it supports only iconic representation
707 // if ( m_nOLEMiscFlags & OLEMISC_ONLYICONIC )
709 m_pNativeImpl->m_pOleObject->SetClientSite( m_pOleWrapClientSite );
711 // the only need in this registration is workaround for close notification
712 m_pNativeImpl->m_pOleObject->Advise( m_pImplAdviseSink, ( DWORD* )&m_nAdvConn );
713 m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink );
715 OleSetContainedObject( m_pNativeImpl->m_pOleObject, TRUE );
717 return sal_True;
720 //----------------------------------------------
721 void OleComponent::LoadEmbeddedObject( const OUString& aTempURL )
723 if ( !aTempURL.getLength() )
724 throw lang::IllegalArgumentException(); // TODO
726 if ( m_pNativeImpl->m_pIStorage )
727 throw io::IOException(); // TODO the object is already initialized or wrong initialization is done
729 // open an IStorage based on the temporary file
730 HRESULT hr = OpenIStorageFromURL_Impl( aTempURL, &m_pNativeImpl->m_pIStorage );
732 if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
733 throw io::IOException(); // TODO: transport error code?
735 hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj );
736 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
738 throw uno::RuntimeException();
741 if ( !InitializeObject_Impl() )
742 throw uno::RuntimeException(); // TODO
745 //----------------------------------------------
746 void OleComponent::CreateObjectFromClipboard()
748 if ( m_pNativeImpl->m_pIStorage )
749 throw io::IOException(); // TODO:the object is already initialized
751 CreateNewIStorage_Impl();
752 if ( !m_pNativeImpl->m_pIStorage )
753 throw uno::RuntimeException(); // TODO
755 IDataObject * pDO = NULL;
756 HRESULT hr = OleGetClipboard( &pDO );
757 if( SUCCEEDED( hr ) && pDO )
759 hr = OleQueryCreateFromData( pDO );
760 if( S_OK == GetScode( hr ) )
762 hr = OleCreateFromData( pDO,
763 IID_IUnknown,
764 OLERENDER_DRAW, // OLERENDER_FORMAT
765 NULL, // &aFormat,
766 NULL,
767 m_pNativeImpl->m_pIStorage,
768 (void**)&m_pNativeImpl->m_pObj );
770 else
772 // Static objects are not supported
773 pDO->Release();
777 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
778 throw uno::RuntimeException();
780 if ( !InitializeObject_Impl() )
781 throw uno::RuntimeException(); // TODO
784 //----------------------------------------------
785 void OleComponent::CreateNewEmbeddedObject( const uno::Sequence< sal_Int8 >& aSeqCLSID )
787 CLSID aClsID;
789 if ( !GetClassIDFromSequence_Impl( aSeqCLSID, aClsID ) )
790 throw lang::IllegalArgumentException(); // TODO
792 if ( m_pNativeImpl->m_pIStorage )
793 throw io::IOException(); // TODO:the object is already initialized
795 CreateNewIStorage_Impl();
796 if ( !m_pNativeImpl->m_pIStorage )
797 throw uno::RuntimeException(); // TODO
799 // FORMATETC aFormat = { CF_METAFILEPICT, NULL, nAspect, -1, TYMED_MFPICT }; // for OLE..._DRAW should be NULL
801 HRESULT hr = OleCreate( aClsID,
802 IID_IUnknown,
803 OLERENDER_DRAW, // OLERENDER_FORMAT
804 NULL, // &aFormat,
805 NULL,
806 m_pNativeImpl->m_pIStorage,
807 (void**)&m_pNativeImpl->m_pObj );
809 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
810 throw uno::RuntimeException(); // TODO
812 if ( !InitializeObject_Impl() )
813 throw uno::RuntimeException(); // TODO
815 // TODO: getExtent???
818 //----------------------------------------------
819 void OleComponent::CreateObjectFromData( const uno::Reference< datatransfer::XTransferable >& )
820 // Static objects are not supported, they should be inserted as graphics
822 // TODO: May be this call is useless since there are no static objects
823 // and nonstatic objects will be created based on OLEstorage ( stream ).
824 // ???
826 // OleQueryCreateFromData...
829 //----------------------------------------------
830 void OleComponent::CreateObjectFromFile( const OUString& aFileURL )
832 if ( m_pNativeImpl->m_pIStorage )
833 throw io::IOException(); // TODO:the object is already initialized
835 CreateNewIStorage_Impl();
836 if ( !m_pNativeImpl->m_pIStorage )
837 throw uno::RuntimeException(); // TODO:
839 OUString aFilePath;
840 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None )
841 throw uno::RuntimeException(); // TODO: something dangerous happened
843 HRESULT hr = OleCreateFromFile( CLSID_NULL,
844 reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
845 IID_IUnknown,
846 OLERENDER_DRAW, // OLERENDER_FORMAT
847 NULL,
848 NULL,
849 m_pNativeImpl->m_pIStorage,
850 (void**)&m_pNativeImpl->m_pObj );
852 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
853 throw uno::RuntimeException(); // TODO
855 if ( !InitializeObject_Impl() )
856 throw uno::RuntimeException(); // TODO
859 //----------------------------------------------
860 void OleComponent::CreateLinkFromFile( const OUString& aFileURL )
862 if ( m_pNativeImpl->m_pIStorage )
863 throw io::IOException(); // TODO:the object is already initialized
865 CreateNewIStorage_Impl();
866 if ( !m_pNativeImpl->m_pIStorage )
867 throw uno::RuntimeException(); // TODO:
869 OUString aFilePath;
870 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None )
871 throw uno::RuntimeException(); // TODO: something dangerous happened
873 HRESULT hr = OleCreateLinkToFile( reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
874 IID_IUnknown,
875 OLERENDER_DRAW, // OLERENDER_FORMAT
876 NULL,
877 NULL,
878 m_pNativeImpl->m_pIStorage,
879 (void**)&m_pNativeImpl->m_pObj );
881 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
882 throw uno::RuntimeException(); // TODO
884 if ( !InitializeObject_Impl() )
885 throw uno::RuntimeException(); // TODO
888 //----------------------------------------------
889 void OleComponent::InitEmbeddedCopyOfLink( OleComponent* pOleLinkComponent )
891 if ( !pOleLinkComponent || !pOleLinkComponent->m_pNativeImpl->m_pObj )
892 throw lang::IllegalArgumentException(); // TODO
894 if ( m_pNativeImpl->m_pIStorage )
895 throw io::IOException(); // TODO:the object is already initialized
897 ComSmart< IDataObject > pDataObject;
898 HRESULT hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
899 if ( SUCCEEDED( hr ) && pDataObject && SUCCEEDED( OleQueryCreateFromData( pDataObject ) ) )
901 // the object must be already disconnected from the temporary URL
902 CreateNewIStorage_Impl();
903 if ( !m_pNativeImpl->m_pIStorage )
904 throw uno::RuntimeException(); // TODO:
906 hr = OleCreateFromData( pDataObject,
907 IID_IUnknown,
908 OLERENDER_DRAW,
909 NULL,
910 NULL,
911 m_pNativeImpl->m_pIStorage,
912 (void**)&m_pNativeImpl->m_pObj );
915 if ( !m_pNativeImpl->m_pObj )
917 ComSmart< IOleLink > pOleLink;
918 hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink );
919 if ( FAILED( hr ) || !pOleLink )
920 throw io::IOException(); // TODO: the object doesn't support IOleLink
922 ComSmart< IMoniker > pMoniker;
923 hr = pOleLink->GetSourceMoniker( &pMoniker );
924 if ( FAILED( hr ) || !pMoniker )
925 throw io::IOException(); // TODO: can not retrieve moniker
927 // In case of file moniker life is easy : )
928 DWORD aMonType = 0;
929 hr = pMoniker->IsSystemMoniker( &aMonType );
930 if ( SUCCEEDED( hr ) && aMonType == MKSYS_FILEMONIKER )
932 ComSmart< IMalloc > pMalloc;
933 CoGetMalloc( 1, &pMalloc ); // if fails there will be a memory leak
934 OSL_ENSURE( pMalloc, "CoGetMalloc() failed!" );
936 LPOLESTR pOleStr = NULL;
937 hr = pOleLink->GetSourceDisplayName( &pOleStr );
938 if ( SUCCEEDED( hr ) && pOleStr )
940 OUString aFilePath( ( sal_Unicode* )pOleStr );
941 if ( pMalloc )
942 pMalloc->Free( ( void* )pOleStr );
944 hr = OleCreateFromFile( CLSID_NULL,
945 reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
946 IID_IUnknown,
947 OLERENDER_DRAW, // OLERENDER_FORMAT
948 NULL,
949 NULL,
950 m_pNativeImpl->m_pIStorage,
951 (void**)&m_pNativeImpl->m_pObj );
955 // in case of other moniker types the only way is to get storage
956 if ( !m_pNativeImpl->m_pObj )
958 ComSmart< IBindCtx > pBindCtx;
959 hr = CreateBindCtx( 0, ( LPBC FAR* )&pBindCtx );
960 if ( SUCCEEDED( hr ) && pBindCtx )
962 ComSmart< IStorage > pObjectStorage;
963 hr = pMoniker->BindToStorage( pBindCtx, NULL, IID_IStorage, (void**)&pObjectStorage );
964 if ( SUCCEEDED( hr ) && pObjectStorage )
966 hr = pObjectStorage->CopyTo( 0, NULL, NULL, m_pNativeImpl->m_pIStorage );
967 if ( SUCCEEDED( hr ) )
968 hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj );
974 // If object could not be created the only way is to use graphical representation
975 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
976 throw uno::RuntimeException(); // TODO
978 if ( !InitializeObject_Impl() )
979 throw uno::RuntimeException(); // TODO
982 //----------------------------------------------
983 void OleComponent::RunObject()
985 OSL_ENSURE( m_pNativeImpl->m_pOleObject, "The pointer can not be set to NULL here!\n" );
986 if ( !m_pNativeImpl->m_pOleObject )
987 throw embed::WrongStateException(); // TODO: the object is in wrong state
989 if ( !OleIsRunning( m_pNativeImpl->m_pOleObject ) )
991 HRESULT hr = S_OK;
994 hr = OleRun( m_pNativeImpl->m_pObj );
996 catch( ... )
998 int i = 0;
999 i++;
1002 if ( FAILED( hr ) )
1004 if ( hr == REGDB_E_CLASSNOTREG )
1005 throw embed::UnreachableStateException(); // the object server is not installed
1006 else
1007 throw io::IOException();
1012 //----------------------------------------------
1013 awt::Size OleComponent::CalculateWithFactor( const awt::Size& aSize,
1014 const awt::Size& aMultiplier,
1015 const awt::Size& aDivisor )
1017 awt::Size aResult;
1019 sal_Int64 nWidth = (sal_Int64)aSize.Width * (sal_Int64)aMultiplier.Width / (sal_Int64)aDivisor.Width;
1020 sal_Int64 nHeight = (sal_Int64)aSize.Height * (sal_Int64)aMultiplier.Height / (sal_Int64)aDivisor.Height;
1021 OSL_ENSURE( nWidth < SAL_MAX_INT32 && nWidth > SAL_MIN_INT32
1022 && nHeight < SAL_MAX_INT32 && nHeight > SAL_MIN_INT32,
1023 "Unacceptable result size!" );
1025 aResult.Width = (sal_Int32)nWidth;
1026 aResult.Height = (sal_Int32)nHeight;
1028 return aResult;
1031 //----------------------------------------------
1032 void OleComponent::CloseObject()
1034 if ( m_pNativeImpl->m_pOleObject && OleIsRunning( m_pNativeImpl->m_pOleObject ) )
1035 m_pNativeImpl->m_pOleObject->Close( OLECLOSE_NOSAVE ); // must be saved before
1038 //----------------------------------------------
1039 uno::Sequence< embed::VerbDescriptor > OleComponent::GetVerbList()
1041 if ( !m_pNativeImpl->m_pOleObject )
1042 throw embed::WrongStateException(); // TODO: the object is in wrong state
1044 if( !m_aVerbList.getLength() )
1046 ComSmart< IEnumOLEVERB > pEnum;
1047 if( SUCCEEDED( m_pNativeImpl->m_pOleObject->EnumVerbs( &pEnum ) ) )
1049 OLEVERB szEle[ MAX_ENUM_ELE ];
1050 ULONG nNum = 0;
1051 sal_Int32 nSeqSize = 0;
1055 HRESULT hr = pEnum->Next( MAX_ENUM_ELE, szEle, &nNum );
1056 if( hr == S_OK || hr == S_FALSE )
1058 m_aVerbList.realloc( nSeqSize += nNum );
1059 for( sal_uInt32 nInd = 0; nInd < nNum; nInd++ )
1061 m_aVerbList[nSeqSize-nNum+nInd].VerbID = szEle[ nInd ].lVerb;
1062 m_aVerbList[nSeqSize-nNum+nInd].VerbName = WinAccToVcl_Impl( reinterpret_cast<const sal_Unicode*>(szEle[ nInd ].lpszVerbName) );
1063 m_aVerbList[nSeqSize-nNum+nInd].VerbFlags = szEle[ nInd ].fuFlags;
1064 m_aVerbList[nSeqSize-nNum+nInd].VerbAttributes = szEle[ nInd ].grfAttribs;
1067 else
1068 break;
1070 while( nNum == MAX_ENUM_ELE );
1074 return m_aVerbList;
1077 //----------------------------------------------
1078 void OleComponent::ExecuteVerb( sal_Int32 nVerbID )
1080 if ( !m_pNativeImpl->m_pOleObject )
1081 throw embed::WrongStateException(); // TODO
1083 HRESULT hr = OleRun( m_pNativeImpl->m_pOleObject );
1084 if ( FAILED( hr ) )
1085 throw io::IOException(); // TODO: a specific exception that transport error code can be thrown here
1087 // TODO: probably extents should be set here and stored in aRect
1088 // TODO: probably the parent window also should be set
1089 hr = m_pNativeImpl->m_pOleObject->DoVerb( nVerbID, NULL, m_pOleWrapClientSite, 0, NULL, NULL );
1091 if ( FAILED( hr ) )
1092 throw io::IOException(); // TODO
1094 // TODO/LATER: the real names should be used here
1095 m_pNativeImpl->m_pOleObject->SetHostNames( L"app name", L"untitled" );
1098 //----------------------------------------------
1099 void OleComponent::SetHostName( const OUString&,
1100 const OUString& )
1102 if ( !m_pNativeImpl->m_pOleObject )
1103 throw embed::WrongStateException(); // TODO: the object is in wrong state
1105 // TODO: use aContName and aEmbDocName in m_pNativeImpl->m_pOleObject->SetHostNames()
1108 //----------------------------------------------
1109 void OleComponent::SetExtent( const awt::Size& aVisAreaSize, sal_Int64 nAspect )
1111 if ( !m_pNativeImpl->m_pOleObject )
1112 throw embed::WrongStateException(); // TODO: the object is in wrong state
1114 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
1116 SIZEL aSize = { aVisAreaSize.Width, aVisAreaSize.Height };
1117 HRESULT hr = m_pNativeImpl->m_pOleObject->SetExtent( nMSAspect, &aSize );
1119 if ( FAILED( hr ) )
1121 // TODO/LATER: is it correct? In future user code probably should be ready for the exception.
1122 // if the object is running but not activated, RPC_E_SERVER_DIED error code is returned by OLE package
1123 // in this case just do nothing
1124 // Also Visio returns E_FAIL on resize if it is in running state
1125 // if ( hr != RPC_E_SERVER_DIED )
1126 throw io::IOException(); // TODO
1130 //----------------------------------------------
1131 awt::Size OleComponent::GetExtent( sal_Int64 nAspect )
1133 if ( !m_pNativeImpl->m_pOleObject )
1134 throw embed::WrongStateException(); // TODO: the object is in wrong state
1136 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
1137 awt::Size aSize;
1138 sal_Bool bGotSize = sal_False;
1140 if ( nMSAspect == DVASPECT_CONTENT )
1142 // Try to get the size from the replacement image first
1143 ComSmart< IDataObject > pDataObject;
1144 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
1145 if ( SUCCEEDED( hr ) || pDataObject )
1147 STGMEDIUM aMedium;
1148 FORMATETC aFormat = pFormatTemplates[1]; // use windows metafile format
1149 aFormat.dwAspect = nMSAspect;
1151 hr = pDataObject->GetData( &aFormat, &aMedium );
1152 if ( SUCCEEDED( hr ) && aMedium.tymed == TYMED_MFPICT ) // Win Metafile
1154 METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict );
1155 if ( pMF )
1157 // the object uses 0.01 mm as unit, so the metafile size should be converted to object unit
1158 sal_Int64 nMult = 1;
1159 sal_Int64 nDiv = 1;
1160 switch( pMF->mm )
1162 case MM_HIENGLISH:
1163 nMult = 254;
1164 nDiv = 100;
1165 break;
1167 case MM_LOENGLISH:
1168 nMult = 254;
1169 nDiv = 10;
1170 break;
1172 case MM_LOMETRIC:
1173 nMult = 10;
1174 break;
1176 case MM_TWIPS:
1177 nMult = 254;
1178 nDiv = 144;
1179 break;
1181 case MM_ISOTROPIC:
1182 case MM_ANISOTROPIC:
1183 case MM_HIMETRIC:
1184 // do nothing
1185 break;
1188 sal_Int64 nX = ( (sal_Int64)abs( pMF->xExt ) ) * nMult / nDiv;
1189 sal_Int64 nY = ( (sal_Int64)abs( pMF->yExt ) ) * nMult / nDiv;
1190 if ( nX < SAL_MAX_INT32 && nY < SAL_MAX_INT32 )
1192 aSize.Width = ( sal_Int32 )nX;
1193 aSize.Height = ( sal_Int32 )nY;
1194 bGotSize = sal_True;
1196 else
1197 OSL_FAIL( "Unexpected size is provided!" );
1200 // i113605, to release storage medium
1201 if ( SUCCEEDED( hr ) )
1202 ::ReleaseStgMedium(&aMedium);
1206 if ( !bGotSize )
1207 throw lang::IllegalArgumentException();
1209 return aSize;
1212 //----------------------------------------------
1213 awt::Size OleComponent::GetCachedExtent( sal_Int64 nAspect )
1215 if ( !m_pNativeImpl->m_pOleObject )
1216 throw embed::WrongStateException(); // TODO: the object is in wrong state
1218 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
1219 SIZEL aSize;
1221 HRESULT hr = m_pNativeImpl->m_pViewObject2->GetExtent( nMSAspect, -1, NULL, &aSize );
1223 if ( FAILED( hr ) )
1225 // TODO/LATER: is it correct?
1226 // if there is no appropriate cache for the aspect, OLE_E_BLANK error code is returned
1227 // if ( hr == OLE_E_BLANK )
1228 // throw lang::IllegalArgumentException();
1229 //else
1230 // throw io::IOException(); // TODO
1232 throw lang::IllegalArgumentException();
1235 return awt::Size( aSize.cx, aSize.cy );
1238 //----------------------------------------------
1239 awt::Size OleComponent::GetReccomendedExtent( sal_Int64 nAspect )
1241 if ( !m_pNativeImpl->m_pOleObject )
1242 throw embed::WrongStateException(); // TODO: the object is in wrong state
1244 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
1245 SIZEL aSize;
1246 HRESULT hr = m_pNativeImpl->m_pOleObject->GetExtent( nMSAspect, &aSize );
1247 if ( FAILED( hr ) )
1248 throw lang::IllegalArgumentException();
1250 return awt::Size( aSize.cx, aSize.cy );
1253 //----------------------------------------------
1254 sal_Int64 OleComponent::GetMiscStatus( sal_Int64 nAspect )
1256 if ( !m_pNativeImpl->m_pOleObject )
1257 throw embed::WrongStateException(); // TODO: the object is in wrong state
1259 sal_uInt32 nResult;
1260 m_pNativeImpl->m_pOleObject->GetMiscStatus( ( DWORD )nAspect, ( DWORD* )&nResult );
1261 return ( sal_Int64 )nResult; // first 32 bits are for MS flags
1264 //----------------------------------------------
1265 uno::Sequence< sal_Int8 > OleComponent::GetCLSID()
1267 if ( !m_pNativeImpl->m_pOleObject )
1268 throw embed::WrongStateException(); // TODO: the object is in wrong state
1270 GUID aCLSID;
1271 HRESULT hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
1272 if ( FAILED( hr ) )
1273 throw io::IOException(); // TODO:
1275 return MimeConfigurationHelper::GetSequenceClassID( aCLSID.Data1, aCLSID.Data2, aCLSID.Data3,
1276 aCLSID.Data4[0], aCLSID.Data4[1],
1277 aCLSID.Data4[2], aCLSID.Data4[3],
1278 aCLSID.Data4[4], aCLSID.Data4[5],
1279 aCLSID.Data4[6], aCLSID.Data4[7] );
1282 //----------------------------------------------
1283 sal_Bool OleComponent::IsDirty()
1285 if ( !m_pNativeImpl->m_pOleObject )
1286 throw embed::WrongStateException(); // TODO: the object is in wrong state
1288 if ( IsWorkaroundActive() )
1289 return sal_True;
1291 ComSmart< IPersistStorage > pPersistStorage;
1292 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage );
1293 if ( FAILED( hr ) || !pPersistStorage )
1294 throw io::IOException(); // TODO
1296 hr = pPersistStorage->IsDirty();
1297 return ( hr != S_FALSE );
1300 //----------------------------------------------
1301 void OleComponent::StoreOwnTmpIfNecessary()
1303 if ( !m_pNativeImpl->m_pOleObject )
1304 throw embed::WrongStateException(); // TODO: the object is in wrong state
1306 ComSmart< IPersistStorage > pPersistStorage;
1307 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage );
1308 if ( FAILED( hr ) || !pPersistStorage )
1309 throw io::IOException(); // TODO
1311 if ( m_bWorkaroundActive || pPersistStorage->IsDirty() != S_FALSE )
1313 hr = OleSave( pPersistStorage, m_pNativeImpl->m_pIStorage, TRUE );
1314 if ( FAILED( hr ) )
1316 // Till now was required only for AcrobatReader7.0.8
1317 GUID aCLSID;
1318 hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
1319 if ( FAILED( hr ) )
1320 throw io::IOException(); // TODO
1322 hr = WriteClassStg( m_pNativeImpl->m_pIStorage, aCLSID );
1323 if ( FAILED( hr ) )
1324 throw io::IOException(); // TODO
1326 // the result of the following call is not checked because some objects, for example AcrobatReader7.0.8
1327 // return error even in case the saving was done correctly
1328 hr = pPersistStorage->Save( m_pNativeImpl->m_pIStorage, TRUE );
1330 // another workaround for AcrobatReader7.0.8 object, this object might think that it is not changed
1331 // when it has been created from file, although it must be saved
1332 m_bWorkaroundActive = sal_True;
1335 hr = m_pNativeImpl->m_pIStorage->Commit( STGC_DEFAULT );
1336 if ( FAILED( hr ) )
1337 throw io::IOException(); // TODO
1339 hr = pPersistStorage->SaveCompleted( NULL );
1340 if ( FAILED( hr ) && hr != E_UNEXPECTED )
1341 throw io::IOException(); // TODO
1346 //----------------------------------------------
1347 sal_Bool OleComponent::SaveObject_Impl()
1349 sal_Bool bResult = sal_False;
1350 OleEmbeddedObject* pLockObject = NULL;
1353 osl::MutexGuard aGuard( m_aMutex );
1354 if ( m_pUnoOleObject )
1356 pLockObject = m_pUnoOleObject;
1357 pLockObject->acquire();
1361 if ( pLockObject )
1363 bResult = pLockObject->SaveObject_Impl();
1364 pLockObject->release();
1367 return bResult;
1370 //----------------------------------------------
1371 sal_Bool OleComponent::OnShowWindow_Impl( bool bShow )
1373 sal_Bool bResult = sal_False;
1374 OleEmbeddedObject* pLockObject = NULL;
1377 osl::MutexGuard aGuard( m_aMutex );
1379 if ( m_pUnoOleObject )
1381 pLockObject = m_pUnoOleObject;
1382 pLockObject->acquire();
1386 if ( pLockObject )
1388 bResult = pLockObject->OnShowWindow_Impl( bShow );
1389 pLockObject->release();
1392 return bResult;
1395 //----------------------------------------------
1396 void OleComponent::OnViewChange_Impl( sal_uInt32 dwAspect )
1398 // TODO: check if it is enough or may be saving notifications are required for Visio2000
1399 ::rtl::Reference< OleEmbeddedObject > xLockObject;
1402 osl::MutexGuard aGuard( m_aMutex );
1403 if ( m_pUnoOleObject )
1404 xLockObject = m_pUnoOleObject;
1407 if ( xLockObject.is() )
1409 uno::Reference < awt::XRequestCallback > xRequestCallback(
1410 m_xFactory->createInstance(
1411 OUString("com.sun.star.awt.AsyncCallback")),
1412 uno::UNO_QUERY );
1413 xRequestCallback->addCallback( new MainThreadNotificationRequest( xLockObject, OLECOMP_ONVIEWCHANGE, dwAspect ), uno::Any() );
1417 //----------------------------------------------
1418 void OleComponent::OnClose_Impl()
1420 ::rtl::Reference< OleEmbeddedObject > xLockObject;
1423 osl::MutexGuard aGuard( m_aMutex );
1424 if ( m_pUnoOleObject )
1425 xLockObject = m_pUnoOleObject;
1428 if ( xLockObject.is() )
1430 uno::Reference < awt::XRequestCallback > xRequestCallback(
1431 m_xFactory->createInstance(
1432 OUString("com.sun.star.awt.AsyncCallback")),
1433 uno::UNO_QUERY );
1434 xRequestCallback->addCallback( new MainThreadNotificationRequest( xLockObject, OLECOMP_ONCLOSE ), uno::Any() );
1438 // XCloseable
1439 //----------------------------------------------
1440 void SAL_CALL OleComponent::close( sal_Bool bDeliverOwnership )
1441 throw ( util::CloseVetoException,
1442 uno::RuntimeException )
1444 ::osl::MutexGuard aGuard( m_aMutex );
1445 if ( m_bDisposed )
1446 throw lang::DisposedException(); // TODO
1448 uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) );
1449 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
1451 if ( m_pInterfaceContainer )
1453 ::cppu::OInterfaceContainerHelper* pContainer =
1454 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) );
1455 if ( pContainer != NULL )
1457 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1458 while ( pIterator.hasMoreElements() )
1462 ( (util::XCloseListener* )pIterator.next() )->queryClosing( aSource, bDeliverOwnership );
1464 catch( const uno::RuntimeException& )
1466 pIterator.remove();
1471 pContainer = m_pInterfaceContainer->getContainer(
1472 ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) );
1473 if ( pContainer != NULL )
1475 ::cppu::OInterfaceIteratorHelper pCloseIterator( *pContainer );
1476 while ( pCloseIterator.hasMoreElements() )
1480 ( (util::XCloseListener* )pCloseIterator.next() )->notifyClosing( aSource );
1482 catch( const uno::RuntimeException& )
1484 pCloseIterator.remove();
1490 Dispose();
1493 //----------------------------------------------
1494 void SAL_CALL OleComponent::addCloseListener( const uno::Reference< util::XCloseListener >& xListener )
1495 throw ( uno::RuntimeException )
1497 ::osl::MutexGuard aGuard( m_aMutex );
1498 if ( m_bDisposed )
1499 throw lang::DisposedException(); // TODO
1501 if ( !m_pInterfaceContainer )
1502 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
1504 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ), xListener );
1507 //----------------------------------------------
1508 void SAL_CALL OleComponent::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener )
1509 throw ( uno::RuntimeException )
1511 ::osl::MutexGuard aGuard( m_aMutex );
1512 if ( m_bDisposed )
1513 throw lang::DisposedException(); // TODO
1515 if ( m_pInterfaceContainer )
1516 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ),
1517 xListener );
1520 // XTransferable
1521 //----------------------------------------------
1522 uno::Any SAL_CALL OleComponent::getTransferData( const datatransfer::DataFlavor& aFlavor )
1523 throw ( datatransfer::UnsupportedFlavorException,
1524 io::IOException,
1525 uno::RuntimeException )
1527 ::osl::MutexGuard aGuard( m_aMutex );
1528 if ( m_bDisposed )
1529 throw lang::DisposedException(); // TODO
1531 if ( !m_pNativeImpl->m_pOleObject )
1532 throw embed::WrongStateException(); // TODO: the object is in wrong state
1534 uno::Any aResult;
1535 sal_Bool bSupportedFlavor = sal_False;
1537 if ( m_pNativeImpl->GraphicalFlavor( aFlavor ) )
1539 DWORD nRequestedAspect = GetAspectFromFlavor( aFlavor );
1540 // if own icon is set and icon aspect is requested the own icon can be returned directly
1542 ComSmart< IDataObject > pDataObject;
1543 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
1544 if ( FAILED( hr ) || !pDataObject )
1545 throw io::IOException(); // TODO: transport error code
1547 // The following optimization does not make much sence currently just because
1548 // only one aspect is supported, and only three formats for the aspect are supported
1549 // and moreover it is not guarantied that the once returned format will be supported further
1550 // example - i52106
1551 // TODO/LATER: bring the optimization back when other aspects are supported
1553 // FORMATETC* pFormatEtc = m_pNativeImpl->GetSupportedFormatForAspect( nRequestedAspect );
1554 // if ( pFormatEtc )
1555 // {
1556 // STGMEDIUM aMedium;
1557 // hr = pDataObject->GetData( pFormatEtc, &aMedium );
1558 // if ( SUCCEEDED( hr ) )
1559 // bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
1560 // }
1561 // else
1563 // the supported format of the application is still not found, find one
1564 for ( sal_Int32 nInd = 0; nInd < FORMATS_NUM; nInd++ )
1566 STGMEDIUM aMedium;
1567 FORMATETC aFormat = pFormatTemplates[nInd];
1568 aFormat.dwAspect = nRequestedAspect;
1570 hr = pDataObject->GetData( &aFormat, &aMedium );
1571 if ( SUCCEEDED( hr ) )
1573 bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
1574 ::ReleaseStgMedium(&aMedium); // i113605, to release storage medium
1575 if ( bSupportedFlavor )
1577 // TODO/LATER: bring the optimization back when other aspects are supported
1578 // m_pNativeImpl->AddSupportedFormat( aFormat );
1579 break;
1585 // If the replacement could not be retrieved, the cached representaion should be used
1586 // currently it is not necessary to retrieve it here, so it is implemented in the object itself
1588 // TODO: Investigate if there is already the format name
1589 // and whether this format is really required
1590 else if ( aFlavor.DataType == getCppuType( ( const uno::Reference< io::XInputStream >* ) 0 )
1591 && aFlavor.MimeType == "application/x-openoffice-contentstream" )
1593 // allow to retrieve stream-representation of the object persistence
1594 bSupportedFlavor = sal_True;
1595 uno::Reference < io::XStream > xTempFileStream(
1596 io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
1597 uno::UNO_QUERY_THROW );
1599 uno::Reference< io::XOutputStream > xTempOutStream = xTempFileStream->getOutputStream();
1600 uno::Reference< io::XInputStream > xTempInStream = xTempFileStream->getInputStream();
1601 if ( xTempOutStream.is() && xTempInStream.is() )
1603 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
1604 if ( !m_pUnoOleObject )
1605 throw uno::RuntimeException();
1607 m_pUnoOleObject->StoreObjectToStream( xTempOutStream );
1609 xTempOutStream->closeOutput();
1610 xTempOutStream = uno::Reference< io::XOutputStream >();
1612 else
1613 throw io::IOException(); // TODO:
1615 aResult <<= xTempInStream;
1618 if ( !bSupportedFlavor )
1619 throw datatransfer::UnsupportedFlavorException();
1621 return aResult;
1624 //----------------------------------------------
1625 uno::Sequence< datatransfer::DataFlavor > SAL_CALL OleComponent::getTransferDataFlavors()
1626 throw ( uno::RuntimeException )
1628 ::osl::MutexGuard aGuard( m_aMutex );
1629 if ( m_bDisposed )
1630 throw lang::DisposedException(); // TODO
1632 if ( !m_pNativeImpl->m_pOleObject )
1633 throw embed::WrongStateException(); // TODO: the object is in wrong state
1635 RetrieveObjectDataFlavors_Impl();
1637 return m_aDataFlavors;
1640 //----------------------------------------------
1641 sal_Bool SAL_CALL OleComponent::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
1642 throw ( uno::RuntimeException )
1644 ::osl::MutexGuard aGuard( m_aMutex );
1645 if ( m_bDisposed )
1646 throw lang::DisposedException(); // TODO
1648 if ( !m_pNativeImpl->m_pOleObject )
1649 throw embed::WrongStateException(); // TODO: the object is in wrong state
1651 if ( !m_aDataFlavors.getLength() )
1653 RetrieveObjectDataFlavors_Impl();
1656 for ( sal_Int32 nInd = 0; nInd < m_aDataFlavors.getLength(); nInd++ )
1657 if ( m_aDataFlavors[nInd].MimeType.equals( aFlavor.MimeType ) && m_aDataFlavors[nInd].DataType == aFlavor.DataType )
1658 return sal_True;
1660 return sal_False;
1663 void SAL_CALL OleComponent::dispose() throw (::com::sun::star::uno::RuntimeException)
1667 close( sal_True );
1669 catch ( const uno::Exception& )
1674 void SAL_CALL OleComponent::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
1675 throw ( uno::RuntimeException )
1677 ::osl::MutexGuard aGuard( m_aMutex );
1678 if ( m_bDisposed )
1679 throw lang::DisposedException(); // TODO
1681 if ( !m_pInterfaceContainer )
1682 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
1684 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ), xListener );
1687 //----------------------------------------------
1688 void SAL_CALL OleComponent::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
1689 throw ( uno::RuntimeException )
1691 ::osl::MutexGuard aGuard( m_aMutex );
1692 if ( m_bDisposed )
1693 throw lang::DisposedException(); // TODO
1695 if ( m_pInterfaceContainer )
1696 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ),
1697 xListener );
1700 sal_Int64 SAL_CALL OleComponent::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException)
1704 uno::Sequence < sal_Int8 > aCLSID = GetCLSID();
1705 if ( MimeConfigurationHelper::ClassIDsEqual( aIdentifier, aCLSID ) )
1706 return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj;
1708 // compatibility hack for old versions: CLSID was used in wrong order (SvGlobalName order)
1709 sal_Int32 nLength = aIdentifier.getLength();
1710 if ( nLength == 16 )
1712 for ( sal_Int32 n=8; n<16; n++ )
1713 if ( aIdentifier[n] != aCLSID[n] )
1714 return 0;
1715 if ( aIdentifier[7] == aCLSID[6] &&
1716 aIdentifier[6] == aCLSID[7] &&
1717 aIdentifier[5] == aCLSID[4] &&
1718 aIdentifier[4] == aCLSID[5] &&
1719 aIdentifier[3] == aCLSID[0] &&
1720 aIdentifier[2] == aCLSID[1] &&
1721 aIdentifier[1] == aCLSID[2] &&
1722 aIdentifier[0] == aCLSID[3] )
1723 return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj;
1726 catch ( const uno::Exception& )
1730 return 0;
1733 sal_Bool SAL_CALL OleComponent::isModified() throw (::com::sun::star::uno::RuntimeException)
1735 return m_bModified;
1738 void SAL_CALL OleComponent::setModified( sal_Bool bModified )
1739 throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException)
1741 m_bModified = bModified;
1743 if ( bModified && m_pInterfaceContainer )
1745 ::cppu::OInterfaceContainerHelper* pContainer =
1746 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XModifyListener >* ) NULL ) );
1747 if ( pContainer != NULL )
1749 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1750 while ( pIterator.hasMoreElements() )
1754 lang::EventObject aEvent( (util::XModifiable*) this );
1755 ((util::XModifyListener*)pIterator.next())->modified( aEvent );
1757 catch( const uno::RuntimeException& )
1759 pIterator.remove();
1766 void SAL_CALL OleComponent::addModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener ) throw(::com::sun::star::uno::RuntimeException)
1768 ::osl::MutexGuard aGuard( m_aMutex );
1769 if ( m_bDisposed )
1770 throw lang::DisposedException(); // TODO
1772 if ( !m_pInterfaceContainer )
1773 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
1775 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ), xListener );
1778 void SAL_CALL OleComponent::removeModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener) throw(::com::sun::star::uno::RuntimeException)
1780 ::osl::MutexGuard aGuard( m_aMutex );
1781 if ( m_bDisposed )
1782 throw lang::DisposedException(); // TODO
1784 if ( m_pInterfaceContainer )
1785 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ),
1786 xListener );
1789 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */