1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: olecomponent.cxx,v $
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>
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
61 // ============ class ComSmart =====================
64 template< class T
> class ComSmart
72 T
* pInterface
= m_pInterface
;
74 pInterface
->Release();
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();
102 ComSmart
& operator=( const ComSmart
<T
>& rObj
)
106 m_pInterface
= rObj
.m_pInterface
;
108 if ( m_pInterface
!= NULL
)
109 m_pInterface
->AddRef();
114 ComSmart
<T
>& operator=( T
* pInterface
)
118 m_pInterface
= pInterface
;
120 if ( m_pInterface
!= NULL
)
121 m_pInterface
->AddRef();
133 return *m_pInterface
;
142 return &m_pInterface
;
145 T
* operator->() const
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
,
177 const ::rtl::OUString
& aFormatShortName
,
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
,
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
;
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
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()),
290 STGM_READWRITE
| STGM_TRANSACTED
, // | STGM_DELETEONRELEASE,
296 //----------------------------------------------
297 sal_Bool
OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM
& aMedium
,
298 const datatransfer::DataFlavor
& aFlavor
,
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
);
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
);
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
)
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];
415 //----------------------------------------------
416 ::rtl::OUString
WinAccToVcl_Impl( const sal_Unicode
* pStr
)
418 ::rtl::OUString aResult
;
426 aResult
+= ::rtl::OUString::createFromAscii( "~" );
427 while( *( ++pStr
) == '&' );
431 aResult
+= ::rtl::OUString( pStr
, 1 );
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 )
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
);
482 } catch( uno::Exception
& ) {}
485 for ( FormatEtcList::iterator aIter
= m_pNativeImpl
->m_aFormatsList
.begin();
486 aIter
!= m_pNativeImpl
->m_aFormatsList
.end();
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();
510 if ( (*aIter
) && (*aIter
)->dwAspect
== nRequestedAspect
)
516 //----------------------------------------------
517 void OleComponent::Dispose()
519 // the mutex must be locked before this method is called
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();
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
;
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
];
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
;
655 while( nNum
== MAX_ENUM_ELE
);
657 m_aDataFlavors
= m_pNativeImpl
->GetFlavorsForAspects( nSupportedAspects
);
661 if ( !m_aDataFlavors
.getLength() )
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
)
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
)
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
)
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
710 FORMATETC aFormat
= { 0, 0, DVASPECT_CONTENT
, -1, TYMED_MFPICT
};
711 hr
= pIOleCache
->Cache( &aFormat
, ADVFCACHE_ONSAVE
, &nConn
);
713 pIOleCache
->Release();
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
);
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
)
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
,
783 OLERENDER_DRAW
, // OLERENDER_FORMAT
786 m_pNativeImpl
->m_pIStorage
,
787 (void**)&m_pNativeImpl
->m_pObj
);
791 // Static objects are not supported
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
)
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
,
822 OLERENDER_DRAW
, // OLERENDER_FORMAT
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 ).
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()),
865 OLERENDER_DRAW
, // OLERENDER_FORMAT
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()),
894 OLERENDER_DRAW
, // OLERENDER_FORMAT
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
,
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 : )
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
);
961 pMalloc
->Free( ( void* )pOleStr
);
963 hr
= OleCreateFromFile( CLSID_NULL
,
964 reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
966 OLERENDER_DRAW
, // OLERENDER_FORMAT
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
) )
1013 hr
= OleRun( m_pNativeImpl
->m_pObj
);
1023 if ( hr
== REGDB_E_CLASSNOTREG
)
1024 throw embed::UnreachableStateException(); // the object server is not installed
1026 throw io::IOException();
1031 //----------------------------------------------
1032 awt::Size
OleComponent::CalculateWithFactor( const awt::Size
& aSize
,
1033 const awt::Size
& aMultiplier
,
1034 const awt::Size
& aDivisor
)
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
;
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
];
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
;
1089 while( nNum
== MAX_ENUM_ELE
);
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
);
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
);
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
);
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
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
)
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
);
1176 // the object uses 0.01 mm as unit, so the metafile size should be converted to object unit
1177 sal_Int64 nMult
= 1;
1201 case MM_ANISOTROPIC
:
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
;
1216 OSL_ENSURE( sal_False
, "Unexpected size is provided!" );
1223 throw lang::IllegalArgumentException();
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
1237 HRESULT hr
= m_pNativeImpl
->m_pViewObject2
->GetExtent( nMSAspect
, -1, NULL
, &aSize
);
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();
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
1262 HRESULT hr
= m_pNativeImpl
->m_pOleObject
->GetExtent( nMSAspect
, &aSize
);
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
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
1287 HRESULT hr
= m_pNativeImpl
->m_pOleObject
->GetUserClassID( &aCLSID
);
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() )
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
);
1332 // Till now was required only for AcrobatReader7.0.8
1334 hr
= m_pNativeImpl
->m_pOleObject
->GetUserClassID( &aCLSID
);
1336 throw io::IOException(); // TODO
1338 hr
= WriteClassStg( m_pNativeImpl
->m_pIStorage
, aCLSID
);
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
);
1353 throw io::IOException(); // TODO
1355 hr
= pPersistStorage
->SaveCompleted( NULL
);
1356 if ( FAILED( hr
) && hr
!= E_UNEXPECTED
)
1357 throw io::IOException(); // TODO
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();
1381 bResult
= pLockObject
->SaveObject_Impl();
1382 pLockObject
->release();
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();
1406 bResult
= pLockObject
->OnShowWindow_Impl( bShow
);
1407 pLockObject
->release();
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
);
1453 //----------------------------------------------
1454 void SAL_CALL
OleComponent::close( sal_Bool bDeliverOwnership
)
1455 throw ( util::CloseVetoException
,
1456 uno::RuntimeException
)
1458 ::osl::MutexGuard
aGuard( m_aMutex
);
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
& )
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();
1507 //----------------------------------------------
1508 void SAL_CALL
OleComponent::addCloseListener( const uno::Reference
< util::XCloseListener
>& xListener
)
1509 throw ( uno::RuntimeException
)
1511 ::osl::MutexGuard
aGuard( m_aMutex
);
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
);
1527 throw lang::DisposedException(); // TODO
1529 if ( m_pInterfaceContainer
)
1530 m_pInterfaceContainer
->removeInterface( ::getCppuType( ( const uno::Reference
< util::XCloseListener
>* )0 ),
1535 //----------------------------------------------
1536 uno::Any SAL_CALL
OleComponent::getTransferData( const datatransfer::DataFlavor
& aFlavor
)
1537 throw ( datatransfer::UnsupportedFlavorException
,
1539 uno::RuntimeException
)
1541 ::osl::MutexGuard
aGuard( m_aMutex
);
1543 throw lang::DisposedException(); // TODO
1545 if ( !m_pNativeImpl
->m_pOleObject
)
1546 throw embed::WrongStateException(); // TODO: the object is in wrong state
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
1565 // TODO/LATER: bring the optimization back when other aspects are supported
1567 // FORMATETC* pFormatEtc = m_pNativeImpl->GetSupportedFormatForAspect( nRequestedAspect );
1568 // if ( pFormatEtc )
1570 // STGMEDIUM aMedium;
1571 // hr = pDataObject->GetData( pFormatEtc, &aMedium );
1572 // if ( SUCCEEDED( hr ) )
1573 // bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
1577 // the supported format of the application is still not found, find one
1578 for ( sal_Int32 nInd
= 0; nInd
< FORMATS_NUM
; nInd
++ )
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 );
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" ) ),
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
>();
1629 throw io::IOException(); // TODO:
1631 aResult
<<= xTempInStream
;
1634 if ( !bSupportedFlavor
)
1635 throw datatransfer::UnsupportedFlavorException();
1640 //----------------------------------------------
1641 uno::Sequence
< datatransfer::DataFlavor
> SAL_CALL
OleComponent::getTransferDataFlavors()
1642 throw ( uno::RuntimeException
)
1644 ::osl::MutexGuard
aGuard( m_aMutex
);
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
);
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
)
1679 void SAL_CALL
OleComponent::dispose() throw (::com::sun::star::uno::RuntimeException
)
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
);
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
);
1709 throw lang::DisposedException(); // TODO
1711 if ( m_pInterfaceContainer
)
1712 m_pInterfaceContainer
->removeInterface( ::getCppuType( ( const uno::Reference
< lang::XEventListener
>* )0 ),
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
] )
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
& )
1749 sal_Bool SAL_CALL
OleComponent::isModified() throw (::com::sun::star::uno::RuntimeException
)
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
& )
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
);
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
);
1798 throw lang::DisposedException(); // TODO
1800 if ( m_pInterfaceContainer
)
1801 m_pInterfaceContainer
->removeInterface( ::getCppuType( ( const uno::Reference
< util::XModifyListener
>* )0 ),