update dev300-m58
[ooovba.git] / embeddedobj / source / msole / olecomponent.cxx
blobd156d19bbec68d954c7f036c1e0e1a44df6de3f5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: olecomponent.cxx,v $
10 * $Revision: 1.42 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_embeddedobj.hxx"
33 #include <com/sun/star/lang/IllegalArgumentException.hpp>
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #include <com/sun/star/embed/WrongStateException.hpp>
36 #include <com/sun/star/embed/UnreachableStateException.hpp>
37 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/io/XTruncate.hpp>
42 #include <platform.h>
44 #include <cppuhelper/interfacecontainer.h>
45 #include <comphelper/mimeconfighelper.hxx>
46 #include <comphelper/storagehelper.hxx>
47 #include <osl/file.hxx>
48 #include <rtl/ref.hxx>
50 #include <olecomponent.hxx>
51 #include <olewrapclient.hxx>
52 #include <advisesink.hxx>
53 #include <oleembobj.hxx>
54 #include <mtnotification.hxx>
56 using namespace ::com::sun::star;
57 using namespace ::comphelper;
58 #define MAX_ENUM_ELE 20
59 #define FORMATS_NUM 3
61 // ============ class ComSmart =====================
62 namespace {
64 template< class T > class ComSmart
66 T* m_pInterface;
68 void OwnRelease()
70 if ( m_pInterface )
72 T* pInterface = m_pInterface;
73 m_pInterface = NULL;
74 pInterface->Release();
78 public:
79 ComSmart()
80 : m_pInterface( NULL )
83 ComSmart( const ComSmart<T>& rObj )
84 : m_pInterface( rObj.m_pInterface )
86 if ( m_pInterface != NULL )
87 m_pInterface->AddRef();
90 ComSmart( T* pInterface )
91 : m_pInterface( pInterface )
93 if ( m_pInterface != NULL )
94 m_pInterface->AddRef();
97 ~ComSmart()
99 OwnRelease();
102 ComSmart& operator=( const ComSmart<T>& rObj )
104 OwnRelease();
106 m_pInterface = rObj.m_pInterface;
108 if ( m_pInterface != NULL )
109 m_pInterface->AddRef();
111 return *this;
114 ComSmart<T>& operator=( T* pInterface )
116 OwnRelease();
118 m_pInterface = pInterface;
120 if ( m_pInterface != NULL )
121 m_pInterface->AddRef();
123 return *this;
126 operator T*() const
128 return m_pInterface;
131 T& operator*() const
133 return *m_pInterface;
136 T** operator&()
138 OwnRelease();
140 m_pInterface = NULL;
142 return &m_pInterface;
145 T* operator->() const
147 return m_pInterface;
150 BOOL operator==( const ComSmart<T>& rObj ) const
152 return ( m_pInterface == rObj.m_pInterface );
155 BOOL operator!=( const ComSmart<T>& rObj ) const
157 return ( m_pInterface != rObj.m_pInterface );
160 BOOL operator==( const T* pInterface ) const
162 return ( m_pInterface == pInterface );
165 BOOL operator!=( const T* pInterface ) const
167 return ( m_pInterface != pInterface );
173 // ============ class ComSmart =====================
175 sal_Bool ConvertBufferToFormat( void* pBuf,
176 sal_uInt32 nBufSize,
177 const ::rtl::OUString& aFormatShortName,
178 uno::Any& aResult );
180 ::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException );
182 typedef ::std::vector< FORMATETC* > FormatEtcList;
184 FORMATETC pFormatTemplates[FORMATS_NUM] = {
185 { CF_ENHMETAFILE, NULL, 0, -1, TYMED_ENHMF },
186 { CF_METAFILEPICT, NULL, 0, -1, TYMED_MFPICT },
187 { CF_BITMAP, NULL, 0, -1, TYMED_GDI } };
190 struct OleComponentNative_Impl {
191 ComSmart< IUnknown > m_pObj;
192 ComSmart< IOleObject > m_pOleObject;
193 ComSmart< IViewObject2 > m_pViewObject2;
194 ComSmart< IStorage > m_pIStorage;
195 FormatEtcList m_aFormatsList;
196 uno::Sequence< datatransfer::DataFlavor > m_aSupportedGraphFormats;
197 uno::Sequence< ::rtl::OUString > m_aGraphShortFormats; //short names for formats from previous sequence
199 OleComponentNative_Impl()
201 // TODO: Extend format list
202 m_aSupportedGraphFormats.realloc( 5 );
203 m_aGraphShortFormats.realloc( 5 );
205 m_aSupportedGraphFormats[0] = datatransfer::DataFlavor(
206 ::rtl::OUString::createFromAscii( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ),
207 ::rtl::OUString::createFromAscii( "Windows Enhanced Metafile" ),
208 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
209 m_aGraphShortFormats[0] = ::rtl::OUString::createFromAscii( "EMF" );
211 m_aSupportedGraphFormats[1] = datatransfer::DataFlavor(
212 ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ),
213 ::rtl::OUString::createFromAscii( "Windows Metafile" ),
214 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
215 m_aGraphShortFormats[1] = ::rtl::OUString::createFromAscii( "WMF" );
217 m_aSupportedGraphFormats[2] = datatransfer::DataFlavor(
218 ::rtl::OUString::createFromAscii( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ),
219 ::rtl::OUString::createFromAscii( "Bitmap" ),
220 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
221 m_aGraphShortFormats[2] = ::rtl::OUString::createFromAscii( "BMP" );
223 m_aSupportedGraphFormats[3] = datatransfer::DataFlavor(
224 ::rtl::OUString::createFromAscii( "image/png" ),
225 ::rtl::OUString::createFromAscii( "PNG" ),
226 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
227 m_aGraphShortFormats[3] = ::rtl::OUString::createFromAscii( "PNG" );
229 m_aSupportedGraphFormats[0] = datatransfer::DataFlavor(
230 ::rtl::OUString::createFromAscii( "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
231 ::rtl::OUString::createFromAscii( "GDIMetafile" ),
232 getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
233 m_aGraphShortFormats[0] = ::rtl::OUString::createFromAscii( "SVM" );
236 void AddSupportedFormat( const FORMATETC& aFormatEtc );
238 FORMATETC* GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect );
240 sal_Bool ConvertDataForFlavor( const STGMEDIUM& aMedium,
241 const datatransfer::DataFlavor& aFlavor,
242 uno::Any& aResult );
244 sal_Bool GraphicalFlavor( const datatransfer::DataFlavor& aFlavor );
246 uno::Sequence< datatransfer::DataFlavor > GetFlavorsForAspects( sal_uInt32 nSupportedAspects );
249 //----------------------------------------------
250 DWORD GetAspectFromFlavor( const datatransfer::DataFlavor& aFlavor )
252 if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=THUMBNAIL" ) ) != -1 )
253 return DVASPECT_THUMBNAIL;
254 else if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=ICON" ) ) != -1 )
255 return DVASPECT_ICON;
256 else if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=DOCPRINT" ) ) != -1 )
257 return DVASPECT_DOCPRINT;
258 else
259 return DVASPECT_CONTENT;
262 //----------------------------------------------
263 ::rtl::OUString GetFlavorSuffixFromAspect( DWORD nAsp )
265 ::rtl::OUString aResult;
267 if ( nAsp == DVASPECT_THUMBNAIL )
268 aResult = ::rtl::OUString::createFromAscii( ";Aspect=THUMBNAIL" );
269 else if ( nAsp == DVASPECT_ICON )
270 aResult = ::rtl::OUString::createFromAscii( ";Aspect=ICON" );
271 else if ( nAsp == DVASPECT_DOCPRINT )
272 aResult = ::rtl::OUString::createFromAscii( ";Aspect=DOCPRINT" );
274 // no suffix for DVASPECT_CONTENT
276 return aResult;
279 //----------------------------------------------
280 HRESULT OpenIStorageFromURL_Impl( const ::rtl::OUString& aURL, IStorage** ppIStorage )
282 OSL_ENSURE( ppIStorage, "The pointer must not be empty!" );
284 ::rtl::OUString aFilePath;
285 if ( !ppIStorage || ::osl::FileBase::getSystemPathFromFileURL( aURL, aFilePath ) != ::osl::FileBase::E_None )
286 throw uno::RuntimeException(); // TODO: something dangerous happend
288 return StgOpenStorage( reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
289 NULL,
290 STGM_READWRITE | STGM_TRANSACTED, // | STGM_DELETEONRELEASE,
291 NULL,
293 ppIStorage );
296 //----------------------------------------------
297 sal_Bool OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM& aMedium,
298 const datatransfer::DataFlavor& aFlavor,
299 uno::Any& aResult )
301 sal_Bool bAnyIsReady = sal_False;
303 // try to convert data from Medium format to specified Flavor format
304 if ( aFlavor.DataType == getCppuType( ( const uno::Sequence< sal_Int8 >* ) 0 ) )
306 // first the GDI-metafile must be generated
308 unsigned char* pBuf = NULL;
309 sal_uInt32 nBufSize = 0;
311 if ( aMedium.tymed == TYMED_MFPICT ) // Win Metafile
313 METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict );
314 if ( pMF )
316 nBufSize = GetMetaFileBitsEx( pMF->hMF, 0, NULL ) + 22;
317 pBuf = new unsigned char[nBufSize];
320 // TODO/LATER: the unit size must be calculated correctly
321 *( (long* )pBuf ) = 0x9ac6cdd7L;
322 *( (short* )( pBuf+6 )) = ( SHORT ) 0;
323 *( (short* )( pBuf+8 )) = ( SHORT ) 0;
324 *( (short* )( pBuf+10 )) = ( SHORT ) pMF->xExt;
325 *( (short* )( pBuf+12 )) = ( SHORT ) pMF->yExt;
326 *( (short* )( pBuf+14 )) = ( USHORT ) 2540;
329 if ( nBufSize && nBufSize == GetMetaFileBitsEx( pMF->hMF, nBufSize - 22, pBuf + 22 ) )
331 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"", 57 ) )
333 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
334 bAnyIsReady = sal_True;
338 GlobalUnlock( aMedium.hMetaFilePict );
341 else if ( aMedium.tymed == TYMED_ENHMF ) // Enh Metafile
343 nBufSize = GetEnhMetaFileBits( aMedium.hEnhMetaFile, 0, NULL );
344 pBuf = new unsigned char[nBufSize];
345 if ( nBufSize && nBufSize == GetEnhMetaFileBits( aMedium.hEnhMetaFile, nBufSize, pBuf ) )
347 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"", 57 ) )
349 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
350 bAnyIsReady = sal_True;
354 else if ( aMedium.tymed == TYMED_GDI ) // Bitmap
356 nBufSize = GetBitmapBits( aMedium.hBitmap, 0, NULL );
357 pBuf = new unsigned char[nBufSize];
358 if ( nBufSize && nBufSize == sal::static_int_cast< ULONG >( GetBitmapBits( aMedium.hBitmap, nBufSize, pBuf ) ) )
360 if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"", 54 ) )
362 aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
363 bAnyIsReady = sal_True;
368 if ( pBuf && !bAnyIsReady )
370 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
371 if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType )
372 && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType
373 && aFlavor.DataType == getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) )
375 bAnyIsReady = ConvertBufferToFormat( ( void* )pBuf, nBufSize, m_aGraphShortFormats[nInd], aResult );
376 break;
380 delete[] pBuf;
383 return bAnyIsReady;
386 //----------------------------------------------
387 sal_Bool OleComponentNative_Impl::GraphicalFlavor( const datatransfer::DataFlavor& aFlavor )
389 // Actually all the required graphical formats must be supported
390 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
391 if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType )
392 && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType )
393 return sal_True;
395 return sal_False;
398 //----------------------------------------------
399 sal_Bool GetClassIDFromSequence_Impl( uno::Sequence< sal_Int8 > aSeq, CLSID& aResult )
401 if ( aSeq.getLength() == 16 )
403 aResult.Data1 = ( ( ( ( ( ( sal_uInt8 )aSeq[0] << 8 ) + ( sal_uInt8 )aSeq[1] ) << 8 ) + ( sal_uInt8 )aSeq[2] ) << 8 ) + ( sal_uInt8 )aSeq[3];
404 aResult.Data2 = ( ( sal_uInt8 )aSeq[4] << 8 ) + ( sal_uInt8 )aSeq[5];
405 aResult.Data3 = ( ( sal_uInt8 )aSeq[6] << 8 ) + ( sal_uInt8 )aSeq[7];
406 for( int nInd = 0; nInd < 8; nInd++ )
407 aResult.Data4[nInd] = ( sal_uInt8 )aSeq[nInd+8];
409 return sal_True;
412 return sal_False;
415 //----------------------------------------------
416 ::rtl::OUString WinAccToVcl_Impl( const sal_Unicode* pStr )
418 ::rtl::OUString aResult;
420 if( pStr )
422 while ( *pStr )
424 if ( *pStr == '&' )
426 aResult += ::rtl::OUString::createFromAscii( "~" );
427 while( *( ++pStr ) == '&' );
429 else
431 aResult += ::rtl::OUString( pStr, 1 );
432 pStr++;
437 return aResult;
440 //----------------------------------------------
441 OleComponent::OleComponent( const uno::Reference< lang::XMultiServiceFactory >& xFactory, OleEmbeddedObject* pUnoOleObject )
442 : m_pInterfaceContainer( NULL )
443 , m_bDisposed( sal_False )
444 , m_bModified( sal_False )
445 , m_pNativeImpl( new OleComponentNative_Impl() )
446 , m_xFactory( xFactory )
447 , m_pOleWrapClientSite( NULL )
448 , m_pImplAdviseSink( NULL )
449 , m_pUnoOleObject( pUnoOleObject )
450 , m_nOLEMiscFlags( 0 )
451 , m_nAdvConn( 0 )
452 , m_bOleInitialized( sal_False )
453 , m_bWorkaroundActive( sal_False )
455 OSL_ENSURE( m_pUnoOleObject, "No owner object is provided!" );
457 HRESULT hr = OleInitialize( NULL );
458 OSL_ENSURE( hr == S_OK || hr == S_FALSE, "The ole can not be successfuly initialized\n" );
459 if ( hr == S_OK || hr == S_FALSE )
460 m_bOleInitialized = sal_True;
462 m_pOleWrapClientSite = new OleWrapperClientSite( ( OleComponent* )this );
463 m_pOleWrapClientSite->AddRef();
465 m_pImplAdviseSink = new OleWrapperAdviseSink( ( OleComponent* )this );
466 m_pImplAdviseSink->AddRef();
470 //----------------------------------------------
471 OleComponent::~OleComponent()
473 OSL_ENSURE( !m_pOleWrapClientSite && !m_pImplAdviseSink && !m_pInterfaceContainer && !m_bOleInitialized,
474 "The object was not closed successfully! DISASTER is possible!" );
476 if ( m_pOleWrapClientSite || m_pImplAdviseSink || m_pInterfaceContainer || m_bOleInitialized )
478 ::osl::MutexGuard aGuard( m_aMutex );
479 m_refCount++;
480 try {
481 Dispose();
482 } catch( uno::Exception& ) {}
485 for ( FormatEtcList::iterator aIter = m_pNativeImpl->m_aFormatsList.begin();
486 aIter != m_pNativeImpl->m_aFormatsList.end();
487 aIter++ )
489 delete (*aIter);
490 (*aIter) = NULL;
492 m_pNativeImpl->m_aFormatsList.clear();
494 delete m_pNativeImpl;
497 //----------------------------------------------
498 void OleComponentNative_Impl::AddSupportedFormat( const FORMATETC& aFormatEtc )
500 FORMATETC* pFormatToInsert = new FORMATETC( aFormatEtc );
501 m_aFormatsList.push_back( pFormatToInsert );
504 //----------------------------------------------
505 FORMATETC* OleComponentNative_Impl::GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect )
507 for ( FormatEtcList::iterator aIter = m_aFormatsList.begin();
508 aIter != m_aFormatsList.end();
509 aIter++ )
510 if ( (*aIter) && (*aIter)->dwAspect == nRequestedAspect )
511 return (*aIter);
513 return NULL;
516 //----------------------------------------------
517 void OleComponent::Dispose()
519 // the mutex must be locked before this method is called
520 if ( m_bDisposed )
521 return;
523 CloseObject();
525 if ( m_pOleWrapClientSite )
527 m_pOleWrapClientSite->disconnectOleComponent();
528 m_pOleWrapClientSite->Release();
529 m_pOleWrapClientSite = NULL;
532 if ( m_pImplAdviseSink )
534 m_pImplAdviseSink->disconnectOleComponent();
535 m_pImplAdviseSink->Release();
536 m_pImplAdviseSink = NULL;
539 if ( m_pInterfaceContainer )
541 lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >( this ) );
542 m_pInterfaceContainer->disposeAndClear( aEvent );
544 delete m_pInterfaceContainer;
545 m_pInterfaceContainer = NULL;
548 if ( m_bOleInitialized )
550 // since the disposing can happen not only from main thread but also from a clipboard
551 // the deinitialization might lead to a disaster, SO7 does not deinitialize OLE at all
552 // so currently the same approach is selected as workaround
553 // OleUninitialize();
554 m_bOleInitialized = sal_False;
557 m_bDisposed = sal_True;
560 //----------------------------------------------
561 void OleComponent::disconnectEmbeddedObject()
563 // must not be called from destructor of UNO OLE object!!!
564 osl::MutexGuard aGuard( m_aMutex );
565 m_pUnoOleObject = NULL;
568 //----------------------------------------------
569 void OleComponent::CreateNewIStorage_Impl()
571 // TODO: in future a global memory could be used instead of file.
573 // write the stream to the temporary file
574 ::rtl::OUString aTempURL;
576 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
577 if ( m_pUnoOleObject )
578 aTempURL = m_pUnoOleObject->CreateTempURLEmpty_Impl();
579 else
580 aTempURL = GetNewTempFileURL_Impl( m_xFactory );
582 if ( !aTempURL.getLength() )
583 throw uno::RuntimeException(); // TODO
585 // open an IStorage based on the temporary file
586 ::rtl::OUString aTempFilePath;
587 if ( ::osl::FileBase::getSystemPathFromFileURL( aTempURL, aTempFilePath ) != ::osl::FileBase::E_None )
588 throw uno::RuntimeException(); // TODO: something dangerous happend
590 HRESULT hr = StgCreateDocfile( reinterpret_cast<LPCWSTR>(aTempFilePath.getStr()), STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED | STGM_DELETEONRELEASE, 0, &m_pNativeImpl->m_pIStorage );
591 if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
592 throw io::IOException(); // TODO: transport error code?
595 //----------------------------------------------
596 uno::Sequence< datatransfer::DataFlavor > OleComponentNative_Impl::GetFlavorsForAspects( sal_uInt32 nSupportedAspects )
598 uno::Sequence< datatransfer::DataFlavor > aResult;
599 for ( sal_uInt32 nAsp = 1; nAsp <= 8; nAsp *= 2 )
600 if ( ( nSupportedAspects & nAsp ) == nAsp )
602 ::rtl::OUString aAspectSuffix = GetFlavorSuffixFromAspect( nAsp );
604 sal_Int32 nLength = aResult.getLength();
605 aResult.realloc( nLength + m_aSupportedGraphFormats.getLength() );
607 for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
609 aResult[nLength + nInd].MimeType = m_aSupportedGraphFormats[nInd].MimeType + aAspectSuffix;
610 aResult[nLength + nInd].HumanPresentableName = m_aSupportedGraphFormats[nInd].HumanPresentableName;
611 aResult[nLength + nInd].DataType = m_aSupportedGraphFormats[nInd].DataType;
615 return aResult;
618 //----------------------------------------------
619 void OleComponent::RetrieveObjectDataFlavors_Impl()
621 if ( !m_pNativeImpl->m_pOleObject )
622 throw embed::WrongStateException(); // TODO: the object is in wrong state
624 if ( !m_aDataFlavors.getLength() )
626 ComSmart< IDataObject > pDataObject;
627 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
628 if ( SUCCEEDED( hr ) && pDataObject )
630 ComSmart< IEnumFORMATETC > pFormatEnum;
631 hr = pDataObject->EnumFormatEtc( DATADIR_GET, &pFormatEnum );
632 if ( SUCCEEDED( hr ) && pFormatEnum )
634 FORMATETC pElem[ MAX_ENUM_ELE ];
635 ULONG nNum = 0;
637 // if it is possible to retrieve at least one supported graphical format for an aspect
638 // this format can be converted to other supported formats
639 sal_uInt32 nSupportedAspects = 0;
642 HRESULT hr = pFormatEnum->Next( MAX_ENUM_ELE, pElem, &nNum );
643 if( hr == S_OK || hr == S_FALSE )
645 for( sal_uInt32 nInd = 0; nInd < FORMATS_NUM; nInd++ )
647 if ( pElem[nInd].cfFormat == pFormatTemplates[nInd].cfFormat
648 && pElem[nInd].tymed == pFormatTemplates[nInd].tymed )
649 nSupportedAspects |= pElem[nInd].dwAspect;
652 else
653 break;
655 while( nNum == MAX_ENUM_ELE );
657 m_aDataFlavors = m_pNativeImpl->GetFlavorsForAspects( nSupportedAspects );
661 if ( !m_aDataFlavors.getLength() )
663 // TODO:
664 // for any reason the object could not provide this information
665 // try to get access to the cached representation
670 //----------------------------------------------
671 sal_Bool OleComponent::InitializeObject_Impl()
672 // There will be no static objects!
674 if ( !m_pNativeImpl->m_pObj )
675 return sal_False;
677 // the linked object will be detected here
678 ComSmart< IOleLink > pOleLink;
679 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink );
680 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
681 if ( m_pUnoOleObject )
682 m_pUnoOleObject->SetObjectIsLink_Impl( sal_Bool( pOleLink != NULL ) );
685 hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IViewObject2, (void**)&m_pNativeImpl->m_pViewObject2 );
686 if ( FAILED( hr ) || !m_pNativeImpl->m_pViewObject2 )
687 return sal_False;
689 // not realy needed for now, since object is updated on saving
690 // m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink );
692 // remove all the caches
693 IOleCache* pIOleCache = NULL;
694 if ( SUCCEEDED( m_pNativeImpl->m_pObj->QueryInterface( IID_IOleCache, (void**)&pIOleCache ) ) && pIOleCache )
696 IEnumSTATDATA* pEnumSD = NULL;
697 HRESULT hr = pIOleCache->EnumCache( &pEnumSD );
699 if ( SUCCEEDED( hr ) && pEnumSD )
701 pEnumSD->Reset();
702 STATDATA aSD;
703 DWORD nNum;
704 while( SUCCEEDED( pEnumSD->Next( 1, &aSD, &nNum ) ) && nNum == 1 )
705 hr = pIOleCache->Uncache( aSD.dwConnection );
708 // No IDataObject implementation, caching must be used instead
709 DWORD nConn;
710 FORMATETC aFormat = { 0, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT };
711 hr = pIOleCache->Cache( &aFormat, ADVFCACHE_ONSAVE, &nConn );
713 pIOleCache->Release();
714 pIOleCache = NULL;
717 hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleObject, (void**)&m_pNativeImpl->m_pOleObject );
718 if ( FAILED( hr ) || !m_pNativeImpl->m_pOleObject )
719 return sal_False; // Static objects are not supported, they should be inserted as graphics
721 m_pNativeImpl->m_pOleObject->GetMiscStatus( DVASPECT_CONTENT, ( DWORD* )&m_nOLEMiscFlags );
722 // TODO: use other misc flags also
723 // the object should have drawable aspect even in case it supports only iconic representation
724 // if ( m_nOLEMiscFlags & OLEMISC_ONLYICONIC )
726 m_pNativeImpl->m_pOleObject->SetClientSite( m_pOleWrapClientSite );
728 // the only need in this registration is workaround for close notification
729 m_pNativeImpl->m_pOleObject->Advise( m_pImplAdviseSink, ( DWORD* )&m_nAdvConn );
730 m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink );
732 OleSetContainedObject( m_pNativeImpl->m_pOleObject, TRUE );
734 return sal_True;
737 //----------------------------------------------
738 void OleComponent::LoadEmbeddedObject( const ::rtl::OUString& aTempURL )
740 if ( !aTempURL.getLength() )
741 throw lang::IllegalArgumentException(); // TODO
743 if ( m_pNativeImpl->m_pIStorage )
744 throw io::IOException(); // TODO the object is already initialized or wrong initialization is done
746 // open an IStorage based on the temporary file
747 HRESULT hr = OpenIStorageFromURL_Impl( aTempURL, &m_pNativeImpl->m_pIStorage );
749 if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
750 throw io::IOException(); // TODO: transport error code?
752 hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj );
753 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
755 // STATSTG aStat;
756 // m_pNativeImpl->m_pIStorage->Stat( &aStat, STATFLAG_NONAME );
757 throw uno::RuntimeException();
760 if ( !InitializeObject_Impl() )
761 throw uno::RuntimeException(); // TODO
764 //----------------------------------------------
765 void OleComponent::CreateObjectFromClipboard()
767 if ( m_pNativeImpl->m_pIStorage )
768 throw io::IOException(); // TODO:the object is already initialized
770 CreateNewIStorage_Impl();
771 if ( !m_pNativeImpl->m_pIStorage )
772 throw uno::RuntimeException(); // TODO
774 IDataObject * pDO = NULL;
775 HRESULT hr = OleGetClipboard( &pDO );
776 if( SUCCEEDED( hr ) && pDO )
778 hr = OleQueryCreateFromData( pDO );
779 if( S_OK == GetScode( hr ) )
781 hr = OleCreateFromData( pDO,
782 IID_IUnknown,
783 OLERENDER_DRAW, // OLERENDER_FORMAT
784 NULL, // &aFormat,
785 NULL,
786 m_pNativeImpl->m_pIStorage,
787 (void**)&m_pNativeImpl->m_pObj );
789 else
791 // Static objects are not supported
792 pDO->Release();
796 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
797 throw uno::RuntimeException();
799 if ( !InitializeObject_Impl() )
800 throw uno::RuntimeException(); // TODO
803 //----------------------------------------------
804 void OleComponent::CreateNewEmbeddedObject( const uno::Sequence< sal_Int8 >& aSeqCLSID )
806 CLSID aClsID;
808 if ( !GetClassIDFromSequence_Impl( aSeqCLSID, aClsID ) )
809 throw lang::IllegalArgumentException(); // TODO
811 if ( m_pNativeImpl->m_pIStorage )
812 throw io::IOException(); // TODO:the object is already initialized
814 CreateNewIStorage_Impl();
815 if ( !m_pNativeImpl->m_pIStorage )
816 throw uno::RuntimeException(); // TODO
818 // FORMATETC aFormat = { CF_METAFILEPICT, NULL, nAspect, -1, TYMED_MFPICT }; // for OLE..._DRAW should be NULL
820 HRESULT hr = OleCreate( aClsID,
821 IID_IUnknown,
822 OLERENDER_DRAW, // OLERENDER_FORMAT
823 NULL, // &aFormat,
824 NULL,
825 m_pNativeImpl->m_pIStorage,
826 (void**)&m_pNativeImpl->m_pObj );
828 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
829 throw uno::RuntimeException(); // TODO
831 if ( !InitializeObject_Impl() )
832 throw uno::RuntimeException(); // TODO
834 // TODO: getExtent???
837 //----------------------------------------------
838 void OleComponent::CreateObjectFromData( const uno::Reference< datatransfer::XTransferable >& )
839 // Static objects are not supported, they should be inserted as graphics
841 // TODO: May be this call is useless since there are no static objects
842 // and nonstatic objects will be created based on OLEstorage ( stream ).
843 // ???
845 // OleQueryCreateFromData...
848 //----------------------------------------------
849 void OleComponent::CreateObjectFromFile( const ::rtl::OUString& aFileURL )
851 if ( m_pNativeImpl->m_pIStorage )
852 throw io::IOException(); // TODO:the object is already initialized
854 CreateNewIStorage_Impl();
855 if ( !m_pNativeImpl->m_pIStorage )
856 throw uno::RuntimeException(); // TODO:
858 ::rtl::OUString aFilePath;
859 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None )
860 throw uno::RuntimeException(); // TODO: something dangerous happend
862 HRESULT hr = OleCreateFromFile( CLSID_NULL,
863 reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
864 IID_IUnknown,
865 OLERENDER_DRAW, // OLERENDER_FORMAT
866 NULL,
867 NULL,
868 m_pNativeImpl->m_pIStorage,
869 (void**)&m_pNativeImpl->m_pObj );
871 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
872 throw uno::RuntimeException(); // TODO
874 if ( !InitializeObject_Impl() )
875 throw uno::RuntimeException(); // TODO
878 //----------------------------------------------
879 void OleComponent::CreateLinkFromFile( const ::rtl::OUString& aFileURL )
881 if ( m_pNativeImpl->m_pIStorage )
882 throw io::IOException(); // TODO:the object is already initialized
884 CreateNewIStorage_Impl();
885 if ( !m_pNativeImpl->m_pIStorage )
886 throw uno::RuntimeException(); // TODO:
888 ::rtl::OUString aFilePath;
889 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None )
890 throw uno::RuntimeException(); // TODO: something dangerous happend
892 HRESULT hr = OleCreateLinkToFile( reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
893 IID_IUnknown,
894 OLERENDER_DRAW, // OLERENDER_FORMAT
895 NULL,
896 NULL,
897 m_pNativeImpl->m_pIStorage,
898 (void**)&m_pNativeImpl->m_pObj );
900 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
901 throw uno::RuntimeException(); // TODO
903 if ( !InitializeObject_Impl() )
904 throw uno::RuntimeException(); // TODO
907 //----------------------------------------------
908 void OleComponent::InitEmbeddedCopyOfLink( OleComponent* pOleLinkComponent )
910 if ( !pOleLinkComponent || !pOleLinkComponent->m_pNativeImpl->m_pObj )
911 throw lang::IllegalArgumentException(); // TODO
913 if ( m_pNativeImpl->m_pIStorage )
914 throw io::IOException(); // TODO:the object is already initialized
916 ComSmart< IDataObject > pDataObject;
917 HRESULT hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
918 if ( SUCCEEDED( hr ) && pDataObject && SUCCEEDED( OleQueryCreateFromData( pDataObject ) ) )
920 // the object must be already disconnected from the temporary URL
921 CreateNewIStorage_Impl();
922 if ( !m_pNativeImpl->m_pIStorage )
923 throw uno::RuntimeException(); // TODO:
925 hr = OleCreateFromData( pDataObject,
926 IID_IUnknown,
927 OLERENDER_DRAW,
928 NULL,
929 NULL,
930 m_pNativeImpl->m_pIStorage,
931 (void**)&m_pNativeImpl->m_pObj );
934 if ( !m_pNativeImpl->m_pObj )
936 ComSmart< IOleLink > pOleLink;
937 hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink );
938 if ( FAILED( hr ) || !pOleLink )
939 throw io::IOException(); // TODO: the object doesn't support IOleLink
941 ComSmart< IMoniker > pMoniker;
942 hr = pOleLink->GetSourceMoniker( &pMoniker );
943 if ( FAILED( hr ) || !pMoniker )
944 throw io::IOException(); // TODO: can not retrieve moniker
946 // In case of file moniker life is easy : )
947 DWORD aMonType = 0;
948 hr = pMoniker->IsSystemMoniker( &aMonType );
949 if ( SUCCEEDED( hr ) && aMonType == MKSYS_FILEMONIKER )
951 ComSmart< IMalloc > pMalloc;
952 CoGetMalloc( 1, &pMalloc ); // if fails there will be a memory leak
953 OSL_ENSURE( pMalloc, "CoGetMalloc() failed!" );
955 LPOLESTR pOleStr = NULL;
956 hr = pOleLink->GetSourceDisplayName( &pOleStr );
957 if ( SUCCEEDED( hr ) && pOleStr )
959 ::rtl::OUString aFilePath( ( sal_Unicode* )pOleStr );
960 if ( pMalloc )
961 pMalloc->Free( ( void* )pOleStr );
963 hr = OleCreateFromFile( CLSID_NULL,
964 reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
965 IID_IUnknown,
966 OLERENDER_DRAW, // OLERENDER_FORMAT
967 NULL,
968 NULL,
969 m_pNativeImpl->m_pIStorage,
970 (void**)&m_pNativeImpl->m_pObj );
974 // in case of other moniker types the only way is to get storage
975 if ( !m_pNativeImpl->m_pObj )
977 ComSmart< IBindCtx > pBindCtx;
978 hr = CreateBindCtx( 0, ( LPBC FAR* )&pBindCtx );
979 if ( SUCCEEDED( hr ) && pBindCtx )
981 ComSmart< IStorage > pObjectStorage;
982 hr = pMoniker->BindToStorage( pBindCtx, NULL, IID_IStorage, (void**)&pObjectStorage );
983 if ( SUCCEEDED( hr ) && pObjectStorage )
985 hr = pObjectStorage->CopyTo( 0, NULL, NULL, m_pNativeImpl->m_pIStorage );
986 if ( SUCCEEDED( hr ) )
987 hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj );
993 // If object could not be created the only way is to use graphical representation
994 if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
995 throw uno::RuntimeException(); // TODO
997 if ( !InitializeObject_Impl() )
998 throw uno::RuntimeException(); // TODO
1001 //----------------------------------------------
1002 void OleComponent::RunObject()
1004 OSL_ENSURE( m_pNativeImpl->m_pOleObject, "The pointer can not be set to NULL here!\n" );
1005 if ( !m_pNativeImpl->m_pOleObject )
1006 throw embed::WrongStateException(); // TODO: the object is in wrong state
1008 if ( !OleIsRunning( m_pNativeImpl->m_pOleObject ) )
1010 HRESULT hr = S_OK;
1013 hr = OleRun( m_pNativeImpl->m_pObj );
1015 catch( ... )
1017 int i = 0;
1018 i++;
1021 if ( FAILED( hr ) )
1023 if ( hr == REGDB_E_CLASSNOTREG )
1024 throw embed::UnreachableStateException(); // the object server is not installed
1025 else
1026 throw io::IOException();
1031 //----------------------------------------------
1032 awt::Size OleComponent::CalculateWithFactor( const awt::Size& aSize,
1033 const awt::Size& aMultiplier,
1034 const awt::Size& aDivisor )
1036 awt::Size aResult;
1038 sal_Int64 nWidth = (sal_Int64)aSize.Width * (sal_Int64)aMultiplier.Width / (sal_Int64)aDivisor.Width;
1039 sal_Int64 nHeight = (sal_Int64)aSize.Height * (sal_Int64)aMultiplier.Height / (sal_Int64)aDivisor.Height;
1040 OSL_ENSURE( nWidth < SAL_MAX_INT32 && nWidth > SAL_MIN_INT32
1041 && nHeight < SAL_MAX_INT32 && nHeight > SAL_MIN_INT32,
1042 "Unacceptable result size!" );
1044 aResult.Width = (sal_Int32)nWidth;
1045 aResult.Height = (sal_Int32)nHeight;
1047 return aResult;
1050 //----------------------------------------------
1051 void OleComponent::CloseObject()
1053 if ( m_pNativeImpl->m_pOleObject && OleIsRunning( m_pNativeImpl->m_pOleObject ) )
1054 m_pNativeImpl->m_pOleObject->Close( OLECLOSE_NOSAVE ); // must be saved before
1057 //----------------------------------------------
1058 uno::Sequence< embed::VerbDescriptor > OleComponent::GetVerbList()
1060 if ( !m_pNativeImpl->m_pOleObject )
1061 throw embed::WrongStateException(); // TODO: the object is in wrong state
1063 if( !m_aVerbList.getLength() )
1065 ComSmart< IEnumOLEVERB > pEnum;
1066 if( SUCCEEDED( m_pNativeImpl->m_pOleObject->EnumVerbs( &pEnum ) ) )
1068 OLEVERB szEle[ MAX_ENUM_ELE ];
1069 ULONG nNum = 0;
1070 sal_Int32 nSeqSize = 0;
1074 HRESULT hr = pEnum->Next( MAX_ENUM_ELE, szEle, &nNum );
1075 if( hr == S_OK || hr == S_FALSE )
1077 m_aVerbList.realloc( nSeqSize += nNum );
1078 for( sal_uInt32 nInd = 0; nInd < nNum; nInd++ )
1080 m_aVerbList[nSeqSize-nNum+nInd].VerbID = szEle[ nInd ].lVerb;
1081 m_aVerbList[nSeqSize-nNum+nInd].VerbName = WinAccToVcl_Impl( reinterpret_cast<const sal_Unicode*>(szEle[ nInd ].lpszVerbName) );
1082 m_aVerbList[nSeqSize-nNum+nInd].VerbFlags = szEle[ nInd ].fuFlags;
1083 m_aVerbList[nSeqSize-nNum+nInd].VerbAttributes = szEle[ nInd ].grfAttribs;
1086 else
1087 break;
1089 while( nNum == MAX_ENUM_ELE );
1093 return m_aVerbList;
1096 //----------------------------------------------
1097 void OleComponent::ExecuteVerb( sal_Int32 nVerbID )
1099 if ( !m_pNativeImpl->m_pOleObject )
1100 throw embed::WrongStateException(); // TODO
1102 HRESULT hr = OleRun( m_pNativeImpl->m_pOleObject );
1103 if ( FAILED( hr ) )
1104 throw io::IOException(); // TODO: a specific exception that transport error code can be thrown here
1106 // TODO: probably extents should be set here and stored in aRect
1107 // TODO: probably the parent window also should be set
1108 hr = m_pNativeImpl->m_pOleObject->DoVerb( nVerbID, NULL, m_pOleWrapClientSite, 0, NULL, NULL );
1110 if ( FAILED( hr ) )
1111 throw io::IOException(); // TODO
1113 // TODO/LATER: the real names should be used here
1114 m_pNativeImpl->m_pOleObject->SetHostNames( L"app name", L"untitled" );
1117 //----------------------------------------------
1118 void OleComponent::SetHostName( const ::rtl::OUString&,
1119 const ::rtl::OUString& )
1121 if ( !m_pNativeImpl->m_pOleObject )
1122 throw embed::WrongStateException(); // TODO: the object is in wrong state
1124 // TODO: use aContName and aEmbDocName in m_pNativeImpl->m_pOleObject->SetHostNames()
1127 //----------------------------------------------
1128 void OleComponent::SetExtent( const awt::Size& aVisAreaSize, sal_Int64 nAspect )
1130 if ( !m_pNativeImpl->m_pOleObject )
1131 throw embed::WrongStateException(); // TODO: the object is in wrong state
1133 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
1135 SIZEL aSize = { aVisAreaSize.Width, aVisAreaSize.Height };
1136 HRESULT hr = m_pNativeImpl->m_pOleObject->SetExtent( nMSAspect, &aSize );
1138 if ( FAILED( hr ) )
1140 // TODO/LATER: is it correct? In future user code probably should be ready for the exception.
1141 // if the object is running but not activated, RPC_E_SERVER_DIED error code is returned by OLE package
1142 // in this case just do nothing
1143 // Also Visio returns E_FAIL on resize if it is in running state
1144 // if ( hr != RPC_E_SERVER_DIED )
1145 throw io::IOException(); // TODO
1149 //----------------------------------------------
1150 awt::Size OleComponent::GetExtent( sal_Int64 nAspect )
1152 if ( !m_pNativeImpl->m_pOleObject )
1153 throw embed::WrongStateException(); // TODO: the object is in wrong state
1155 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
1156 awt::Size aSize;
1157 sal_Bool bGotSize = sal_False;
1159 if ( nMSAspect == DVASPECT_CONTENT )
1161 // Try to get the size from the replacement image first
1162 ComSmart< IDataObject > pDataObject;
1163 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
1164 if ( SUCCEEDED( hr ) || pDataObject )
1166 STGMEDIUM aMedium;
1167 FORMATETC aFormat = pFormatTemplates[1]; // use windows metafile format
1168 aFormat.dwAspect = nMSAspect;
1170 hr = pDataObject->GetData( &aFormat, &aMedium );
1171 if ( SUCCEEDED( hr ) && aMedium.tymed == TYMED_MFPICT ) // Win Metafile
1173 METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict );
1174 if ( pMF )
1176 // the object uses 0.01 mm as unit, so the metafile size should be converted to object unit
1177 sal_Int64 nMult = 1;
1178 sal_Int64 nDiv = 1;
1179 switch( pMF->mm )
1181 case MM_HIENGLISH:
1182 nMult = 254;
1183 nDiv = 100;
1184 break;
1186 case MM_LOENGLISH:
1187 nMult = 254;
1188 nDiv = 10;
1189 break;
1191 case MM_LOMETRIC:
1192 nMult = 10;
1193 break;
1195 case MM_TWIPS:
1196 nMult = 254;
1197 nDiv = 144;
1198 break;
1200 case MM_ISOTROPIC:
1201 case MM_ANISOTROPIC:
1202 case MM_HIMETRIC:
1203 // do nothing
1204 break;
1207 sal_Int64 nX = ( (sal_Int64)abs( pMF->xExt ) ) * nMult / nDiv;
1208 sal_Int64 nY = ( (sal_Int64)abs( pMF->yExt ) ) * nMult / nDiv;
1209 if ( nX < SAL_MAX_INT32 && nY < SAL_MAX_INT32 )
1211 aSize.Width = ( sal_Int32 )nX;
1212 aSize.Height = ( sal_Int32 )nY;
1213 bGotSize = sal_True;
1215 else
1216 OSL_ENSURE( sal_False, "Unexpected size is provided!" );
1222 if ( !bGotSize )
1223 throw lang::IllegalArgumentException();
1225 return aSize;
1228 //----------------------------------------------
1229 awt::Size OleComponent::GetCachedExtent( sal_Int64 nAspect )
1231 if ( !m_pNativeImpl->m_pOleObject )
1232 throw embed::WrongStateException(); // TODO: the object is in wrong state
1234 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
1235 SIZEL aSize;
1237 HRESULT hr = m_pNativeImpl->m_pViewObject2->GetExtent( nMSAspect, -1, NULL, &aSize );
1239 if ( FAILED( hr ) )
1241 // TODO/LATER: is it correct?
1242 // if there is no appropriate cache for the aspect, OLE_E_BLANK error code is returned
1243 // if ( hr == OLE_E_BLANK )
1244 // throw lang::IllegalArgumentException();
1245 //else
1246 // throw io::IOException(); // TODO
1248 throw lang::IllegalArgumentException();
1251 return awt::Size( aSize.cx, aSize.cy );
1254 //----------------------------------------------
1255 awt::Size OleComponent::GetReccomendedExtent( sal_Int64 nAspect )
1257 if ( !m_pNativeImpl->m_pOleObject )
1258 throw embed::WrongStateException(); // TODO: the object is in wrong state
1260 DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
1261 SIZEL aSize;
1262 HRESULT hr = m_pNativeImpl->m_pOleObject->GetExtent( nMSAspect, &aSize );
1263 if ( FAILED( hr ) )
1264 throw lang::IllegalArgumentException();
1266 return awt::Size( aSize.cx, aSize.cy );
1269 //----------------------------------------------
1270 sal_Int64 OleComponent::GetMiscStatus( sal_Int64 nAspect )
1272 if ( !m_pNativeImpl->m_pOleObject )
1273 throw embed::WrongStateException(); // TODO: the object is in wrong state
1275 sal_uInt32 nResult;
1276 m_pNativeImpl->m_pOleObject->GetMiscStatus( ( DWORD )nAspect, ( DWORD* )&nResult );
1277 return ( sal_Int64 )nResult; // first 32 bits are for MS flags
1280 //----------------------------------------------
1281 uno::Sequence< sal_Int8 > OleComponent::GetCLSID()
1283 if ( !m_pNativeImpl->m_pOleObject )
1284 throw embed::WrongStateException(); // TODO: the object is in wrong state
1286 GUID aCLSID;
1287 HRESULT hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
1288 if ( FAILED( hr ) )
1289 throw io::IOException(); // TODO:
1291 return MimeConfigurationHelper::GetSequenceClassID( aCLSID.Data1, aCLSID.Data2, aCLSID.Data3,
1292 aCLSID.Data4[0], aCLSID.Data4[1],
1293 aCLSID.Data4[2], aCLSID.Data4[3],
1294 aCLSID.Data4[4], aCLSID.Data4[5],
1295 aCLSID.Data4[6], aCLSID.Data4[7] );
1298 //----------------------------------------------
1299 sal_Bool OleComponent::IsDirty()
1301 if ( !m_pNativeImpl->m_pOleObject )
1302 throw embed::WrongStateException(); // TODO: the object is in wrong state
1304 if ( IsWorkaroundActive() )
1305 return sal_True;
1307 ComSmart< IPersistStorage > pPersistStorage;
1308 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage );
1309 if ( FAILED( hr ) || !pPersistStorage )
1310 throw io::IOException(); // TODO
1312 hr = pPersistStorage->IsDirty();
1313 return ( hr != S_FALSE );
1316 //----------------------------------------------
1317 void OleComponent::StoreOwnTmpIfNecessary()
1319 if ( !m_pNativeImpl->m_pOleObject )
1320 throw embed::WrongStateException(); // TODO: the object is in wrong state
1322 ComSmart< IPersistStorage > pPersistStorage;
1323 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage );
1324 if ( FAILED( hr ) || !pPersistStorage )
1325 throw io::IOException(); // TODO
1327 if ( m_bWorkaroundActive || pPersistStorage->IsDirty() != S_FALSE )
1329 hr = OleSave( pPersistStorage, m_pNativeImpl->m_pIStorage, TRUE );
1330 if ( FAILED( hr ) )
1332 // Till now was required only for AcrobatReader7.0.8
1333 GUID aCLSID;
1334 hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
1335 if ( FAILED( hr ) )
1336 throw io::IOException(); // TODO
1338 hr = WriteClassStg( m_pNativeImpl->m_pIStorage, aCLSID );
1339 if ( FAILED( hr ) )
1340 throw io::IOException(); // TODO
1342 // the result of the following call is not checked because some objects, for example AcrobatReader7.0.8
1343 // return error even in case the saving was done correctly
1344 hr = pPersistStorage->Save( m_pNativeImpl->m_pIStorage, TRUE );
1346 // another workaround for AcrobatReader7.0.8 object, this object might think that it is not changed
1347 // when it has been created from file, although it must be saved
1348 m_bWorkaroundActive = sal_True;
1351 hr = m_pNativeImpl->m_pIStorage->Commit( STGC_DEFAULT );
1352 if ( FAILED( hr ) )
1353 throw io::IOException(); // TODO
1355 hr = pPersistStorage->SaveCompleted( NULL );
1356 if ( FAILED( hr ) && hr != E_UNEXPECTED )
1357 throw io::IOException(); // TODO
1359 // STATSTG aStat;
1360 // m_pNativeImpl->m_pIStorage->Stat( &aStat, STATFLAG_NONAME );
1364 //----------------------------------------------
1365 sal_Bool OleComponent::SaveObject_Impl()
1367 sal_Bool bResult = sal_False;
1368 OleEmbeddedObject* pLockObject = NULL;
1371 osl::MutexGuard aGuard( m_aMutex );
1372 if ( m_pUnoOleObject )
1374 pLockObject = m_pUnoOleObject;
1375 pLockObject->acquire();
1379 if ( pLockObject )
1381 bResult = pLockObject->SaveObject_Impl();
1382 pLockObject->release();
1385 return bResult;
1388 //----------------------------------------------
1389 sal_Bool OleComponent::OnShowWindow_Impl( bool bShow )
1391 sal_Bool bResult = sal_False;
1392 OleEmbeddedObject* pLockObject = NULL;
1395 osl::MutexGuard aGuard( m_aMutex );
1397 if ( m_pUnoOleObject )
1399 pLockObject = m_pUnoOleObject;
1400 pLockObject->acquire();
1404 if ( pLockObject )
1406 bResult = pLockObject->OnShowWindow_Impl( bShow );
1407 pLockObject->release();
1410 return bResult;
1413 //----------------------------------------------
1414 void OleComponent::OnViewChange_Impl( sal_uInt32 dwAspect )
1416 // TODO: check if it is enough or may be saving notifications are required for Visio2000
1417 ::rtl::Reference< OleEmbeddedObject > xLockObject;
1420 osl::MutexGuard aGuard( m_aMutex );
1421 if ( m_pUnoOleObject )
1422 xLockObject = m_pUnoOleObject;
1425 if ( xLockObject.is() )
1427 // the request will be deleted immedeatelly after execution by it's implementation
1428 MainThreadNotificationRequest* pMTNotifRequest = new MainThreadNotificationRequest( xLockObject, OLECOMP_ONVIEWCHANGE, dwAspect );
1429 MainThreadNotificationRequest::mainThreadWorkerStart( pMTNotifRequest );
1433 //----------------------------------------------
1434 void OleComponent::OnClose_Impl()
1436 ::rtl::Reference< OleEmbeddedObject > xLockObject;
1439 osl::MutexGuard aGuard( m_aMutex );
1440 if ( m_pUnoOleObject )
1441 xLockObject = m_pUnoOleObject;
1444 if ( xLockObject.is() )
1446 // the request will be deleted immedeatelly after execution by it's implementation
1447 MainThreadNotificationRequest* pMTNotifRequest = new MainThreadNotificationRequest( xLockObject, OLECOMP_ONCLOSE );
1448 MainThreadNotificationRequest::mainThreadWorkerStart( pMTNotifRequest );
1452 // XCloseable
1453 //----------------------------------------------
1454 void SAL_CALL OleComponent::close( sal_Bool bDeliverOwnership )
1455 throw ( util::CloseVetoException,
1456 uno::RuntimeException )
1458 ::osl::MutexGuard aGuard( m_aMutex );
1459 if ( m_bDisposed )
1460 throw lang::DisposedException(); // TODO
1462 uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) );
1463 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
1465 if ( m_pInterfaceContainer )
1467 ::cppu::OInterfaceContainerHelper* pContainer =
1468 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) );
1469 if ( pContainer != NULL )
1471 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1472 while ( pIterator.hasMoreElements() )
1476 ( (util::XCloseListener* )pIterator.next() )->queryClosing( aSource, bDeliverOwnership );
1478 catch( uno::RuntimeException& )
1480 pIterator.remove();
1485 pContainer = m_pInterfaceContainer->getContainer(
1486 ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) );
1487 if ( pContainer != NULL )
1489 ::cppu::OInterfaceIteratorHelper pCloseIterator( *pContainer );
1490 while ( pCloseIterator.hasMoreElements() )
1494 ( (util::XCloseListener* )pCloseIterator.next() )->notifyClosing( aSource );
1496 catch( uno::RuntimeException& )
1498 pCloseIterator.remove();
1504 Dispose();
1507 //----------------------------------------------
1508 void SAL_CALL OleComponent::addCloseListener( 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 = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
1518 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ), xListener );
1521 //----------------------------------------------
1522 void SAL_CALL OleComponent::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener )
1523 throw ( uno::RuntimeException )
1525 ::osl::MutexGuard aGuard( m_aMutex );
1526 if ( m_bDisposed )
1527 throw lang::DisposedException(); // TODO
1529 if ( m_pInterfaceContainer )
1530 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ),
1531 xListener );
1534 // XTransferable
1535 //----------------------------------------------
1536 uno::Any SAL_CALL OleComponent::getTransferData( const datatransfer::DataFlavor& aFlavor )
1537 throw ( datatransfer::UnsupportedFlavorException,
1538 io::IOException,
1539 uno::RuntimeException )
1541 ::osl::MutexGuard aGuard( m_aMutex );
1542 if ( m_bDisposed )
1543 throw lang::DisposedException(); // TODO
1545 if ( !m_pNativeImpl->m_pOleObject )
1546 throw embed::WrongStateException(); // TODO: the object is in wrong state
1548 uno::Any aResult;
1549 sal_Bool bSupportedFlavor = sal_False;
1551 if ( m_pNativeImpl->GraphicalFlavor( aFlavor ) )
1553 DWORD nRequestedAspect = GetAspectFromFlavor( aFlavor );
1554 // if own icon is set and icon aspect is requested the own icon can be returned directly
1556 ComSmart< IDataObject > pDataObject;
1557 HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
1558 if ( FAILED( hr ) || !pDataObject )
1559 throw io::IOException(); // TODO: transport error code
1561 // The following optimization does not make much sence currently just because
1562 // only one aspect is supported, and only three formats for the aspect are supported
1563 // and moreover it is not guarantied that the once returned format will be supported further
1564 // example - i52106
1565 // TODO/LATER: bring the optimization back when other aspects are supported
1567 // FORMATETC* pFormatEtc = m_pNativeImpl->GetSupportedFormatForAspect( nRequestedAspect );
1568 // if ( pFormatEtc )
1569 // {
1570 // STGMEDIUM aMedium;
1571 // hr = pDataObject->GetData( pFormatEtc, &aMedium );
1572 // if ( SUCCEEDED( hr ) )
1573 // bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
1574 // }
1575 // else
1577 // the supported format of the application is still not found, find one
1578 for ( sal_Int32 nInd = 0; nInd < FORMATS_NUM; nInd++ )
1580 STGMEDIUM aMedium;
1581 FORMATETC aFormat = pFormatTemplates[nInd];
1582 aFormat.dwAspect = nRequestedAspect;
1584 hr = pDataObject->GetData( &aFormat, &aMedium );
1585 if ( SUCCEEDED( hr ) )
1587 bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
1588 if ( bSupportedFlavor )
1590 // TODO/LATER: bring the optimization back when other aspects are supported
1591 // m_pNativeImpl->AddSupportedFormat( aFormat );
1592 break;
1598 // If the replacement could not be retrieved, the cached representaion should be used
1599 // currently it is not necessary to retrieve it here, so it is implemented in the object itself
1601 // TODO: Investigate if there is already the format name
1602 // and whether this format is really required
1603 else if ( aFlavor.DataType == getCppuType( ( const uno::Reference< io::XInputStream >* ) 0 )
1604 && aFlavor.MimeType.equalsAscii( "application/x-openoffice-contentstream" ) )
1606 // allow to retrieve stream-representation of the object persistence
1607 bSupportedFlavor = sal_True;
1608 uno::Reference < io::XStream > xTempFileStream(
1609 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
1610 uno::UNO_QUERY );
1612 if ( !xTempFileStream.is() )
1613 throw uno::RuntimeException(); // TODO
1615 uno::Reference< io::XOutputStream > xTempOutStream = xTempFileStream->getOutputStream();
1616 uno::Reference< io::XInputStream > xTempInStream = xTempFileStream->getInputStream();
1617 if ( xTempOutStream.is() && xTempInStream.is() )
1619 OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
1620 if ( !m_pUnoOleObject )
1621 throw uno::RuntimeException();
1623 m_pUnoOleObject->StoreObjectToStream( xTempOutStream );
1625 xTempOutStream->closeOutput();
1626 xTempOutStream = uno::Reference< io::XOutputStream >();
1628 else
1629 throw io::IOException(); // TODO:
1631 aResult <<= xTempInStream;
1634 if ( !bSupportedFlavor )
1635 throw datatransfer::UnsupportedFlavorException();
1637 return aResult;
1640 //----------------------------------------------
1641 uno::Sequence< datatransfer::DataFlavor > SAL_CALL OleComponent::getTransferDataFlavors()
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 RetrieveObjectDataFlavors_Impl();
1653 return m_aDataFlavors;
1656 //----------------------------------------------
1657 sal_Bool SAL_CALL OleComponent::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
1658 throw ( uno::RuntimeException )
1660 ::osl::MutexGuard aGuard( m_aMutex );
1661 if ( m_bDisposed )
1662 throw lang::DisposedException(); // TODO
1664 if ( !m_pNativeImpl->m_pOleObject )
1665 throw embed::WrongStateException(); // TODO: the object is in wrong state
1667 if ( !m_aDataFlavors.getLength() )
1669 RetrieveObjectDataFlavors_Impl();
1672 for ( sal_Int32 nInd = 0; nInd < m_aDataFlavors.getLength(); nInd++ )
1673 if ( m_aDataFlavors[nInd].MimeType.equals( aFlavor.MimeType ) && m_aDataFlavors[nInd].DataType == aFlavor.DataType )
1674 return sal_True;
1676 return sal_False;
1679 void SAL_CALL OleComponent::dispose() throw (::com::sun::star::uno::RuntimeException)
1683 close( sal_True );
1685 catch ( uno::Exception& )
1690 void SAL_CALL OleComponent::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
1691 throw ( uno::RuntimeException )
1693 ::osl::MutexGuard aGuard( m_aMutex );
1694 if ( m_bDisposed )
1695 throw lang::DisposedException(); // TODO
1697 if ( !m_pInterfaceContainer )
1698 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
1700 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ), xListener );
1703 //----------------------------------------------
1704 void SAL_CALL OleComponent::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
1705 throw ( uno::RuntimeException )
1707 ::osl::MutexGuard aGuard( m_aMutex );
1708 if ( m_bDisposed )
1709 throw lang::DisposedException(); // TODO
1711 if ( m_pInterfaceContainer )
1712 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ),
1713 xListener );
1716 sal_Int64 SAL_CALL OleComponent::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException)
1720 uno::Sequence < sal_Int8 > aCLSID = GetCLSID();
1721 if ( MimeConfigurationHelper::ClassIDsEqual( aIdentifier, aCLSID ) )
1722 return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj;
1724 // compatibility hack for old versions: CLSID was used in wrong order (SvGlobalName order)
1725 sal_Int32 nLength = aIdentifier.getLength();
1726 if ( nLength == 16 )
1728 for ( sal_Int32 n=8; n<16; n++ )
1729 if ( aIdentifier[n] != aCLSID[n] )
1730 return 0;
1731 if ( aIdentifier[7] == aCLSID[6] &&
1732 aIdentifier[6] == aCLSID[7] &&
1733 aIdentifier[5] == aCLSID[4] &&
1734 aIdentifier[4] == aCLSID[5] &&
1735 aIdentifier[3] == aCLSID[0] &&
1736 aIdentifier[2] == aCLSID[1] &&
1737 aIdentifier[1] == aCLSID[2] &&
1738 aIdentifier[0] == aCLSID[3] )
1739 return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj;
1742 catch ( uno::Exception& )
1746 return 0;
1749 sal_Bool SAL_CALL OleComponent::isModified() throw (::com::sun::star::uno::RuntimeException)
1751 return m_bModified;
1754 void SAL_CALL OleComponent::setModified( sal_Bool bModified )
1755 throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException)
1757 m_bModified = bModified;
1759 if ( bModified && m_pInterfaceContainer )
1761 ::cppu::OInterfaceContainerHelper* pContainer =
1762 m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XModifyListener >* ) NULL ) );
1763 if ( pContainer != NULL )
1765 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
1766 while ( pIterator.hasMoreElements() )
1770 lang::EventObject aEvent( (util::XModifiable*) this );
1771 ((util::XModifyListener*)pIterator.next())->modified( aEvent );
1773 catch( uno::RuntimeException& )
1775 pIterator.remove();
1782 void SAL_CALL OleComponent::addModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener ) throw(::com::sun::star::uno::RuntimeException)
1784 ::osl::MutexGuard aGuard( m_aMutex );
1785 if ( m_bDisposed )
1786 throw lang::DisposedException(); // TODO
1788 if ( !m_pInterfaceContainer )
1789 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
1791 m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ), xListener );
1794 void SAL_CALL OleComponent::removeModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener) throw(::com::sun::star::uno::RuntimeException)
1796 ::osl::MutexGuard aGuard( m_aMutex );
1797 if ( m_bDisposed )
1798 throw lang::DisposedException(); // TODO
1800 if ( m_pInterfaceContainer )
1801 m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ),
1802 xListener );