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