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 <graphconvert.hxx>
39 #include <olecomponent.hxx>
40 #include <olepersist.hxx>
41 #include <olewrapclient.hxx>
42 #include <advisesink.hxx>
43 #include <oleembobj.hxx>
44 #include <mtnotification.hxx>
47 using namespace ::com::sun::star
;
48 using namespace ::comphelper
;
49 #define MAX_ENUM_ELE 20
52 // ============ class ComSmart =====================
55 template< class T
> class ComSmart
63 T
* pInterface
= m_pInterface
;
64 m_pInterface
= nullptr;
65 pInterface
->Release();
71 : m_pInterface( nullptr )
74 ComSmart( const ComSmart
<T
>& rObj
)
75 : m_pInterface( rObj
.m_pInterface
)
77 if ( m_pInterface
!= NULL
)
78 m_pInterface
->AddRef();
81 ComSmart( T
* pInterface
)
82 : m_pInterface( pInterface
)
84 if ( m_pInterface
!= NULL
)
85 m_pInterface
->AddRef();
93 ComSmart
& operator=( const ComSmart
<T
>& rObj
)
97 m_pInterface
= rObj
.m_pInterface
;
99 if ( m_pInterface
!= NULL
)
100 m_pInterface
->AddRef();
105 ComSmart
<T
>& operator=( T
* pInterface
)
109 m_pInterface
= pInterface
;
111 if ( m_pInterface
!= NULL
)
112 m_pInterface
->AddRef();
124 return *m_pInterface
;
131 m_pInterface
= nullptr;
133 return &m_pInterface
;
136 T
* operator->() const
141 BOOL
operator==( const ComSmart
<T
>& rObj
) const
143 return ( m_pInterface
== rObj
.m_pInterface
);
146 BOOL
operator!=( const ComSmart
<T
>& rObj
) const
148 return ( m_pInterface
!= rObj
.m_pInterface
);
151 BOOL
operator==( const T
* pInterface
) const
153 return ( m_pInterface
== pInterface
);
156 BOOL
operator!=( const T
* pInterface
) const
158 return ( m_pInterface
!= pInterface
);
164 // ============ class ComSmart =====================
166 typedef ::std::vector
< FORMATETC
* > FormatEtcList
;
168 FORMATETC pFormatTemplates
[FORMATS_NUM
] = {
169 { CF_ENHMETAFILE
, nullptr, 0, -1, TYMED_ENHMF
},
170 { CF_METAFILEPICT
, nullptr, 0, -1, TYMED_MFPICT
},
171 { CF_BITMAP
, nullptr, 0, -1, TYMED_GDI
} };
174 struct OleComponentNative_Impl
{
175 ComSmart
< IUnknown
> m_pObj
;
176 ComSmart
< IOleObject
> m_pOleObject
;
177 ComSmart
< IViewObject2
> m_pViewObject2
;
178 ComSmart
< IStorage
> m_pIStorage
;
179 FormatEtcList m_aFormatsList
;
180 uno::Sequence
< datatransfer::DataFlavor
> m_aSupportedGraphFormats
;
182 OleComponentNative_Impl()
184 // TODO: Extend format list
185 m_aSupportedGraphFormats
.realloc( 5 );
187 m_aSupportedGraphFormats
[0] = datatransfer::DataFlavor(
188 OUString( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ),
189 OUString( "Windows Enhanced Metafile" ),
190 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
192 m_aSupportedGraphFormats
[1] = datatransfer::DataFlavor(
193 OUString( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ),
194 OUString( "Windows Metafile" ),
195 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
197 m_aSupportedGraphFormats
[2] = datatransfer::DataFlavor(
198 OUString( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ),
199 OUString( "Bitmap" ),
200 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
202 m_aSupportedGraphFormats
[3] = datatransfer::DataFlavor(
203 OUString( "image/png" ),
205 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
207 m_aSupportedGraphFormats
[0] = datatransfer::DataFlavor(
208 OUString( "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
209 OUString( "GDIMetafile" ),
210 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
213 bool ConvertDataForFlavor( const STGMEDIUM
& aMedium
,
214 const datatransfer::DataFlavor
& aFlavor
,
217 bool GraphicalFlavor( const datatransfer::DataFlavor
& aFlavor
);
219 uno::Sequence
< datatransfer::DataFlavor
> GetFlavorsForAspects( sal_uInt32 nSupportedAspects
);
223 DWORD
GetAspectFromFlavor( const datatransfer::DataFlavor
& aFlavor
)
225 if ( aFlavor
.MimeType
.indexOf( ";Aspect=THUMBNAIL" ) != -1 )
226 return DVASPECT_THUMBNAIL
;
227 else if ( aFlavor
.MimeType
.indexOf( ";Aspect=ICON" ) != -1 )
228 return DVASPECT_ICON
;
229 else if ( aFlavor
.MimeType
.indexOf( ";Aspect=DOCPRINT" ) != -1 )
230 return DVASPECT_DOCPRINT
;
232 return DVASPECT_CONTENT
;
236 OUString
GetFlavorSuffixFromAspect( DWORD nAsp
)
240 if ( nAsp
== DVASPECT_THUMBNAIL
)
241 aResult
= ";Aspect=THUMBNAIL";
242 else if ( nAsp
== DVASPECT_ICON
)
243 aResult
= ";Aspect=ICON";
244 else if ( nAsp
== DVASPECT_DOCPRINT
)
245 aResult
= ";Aspect=DOCPRINT";
247 // no suffix for DVASPECT_CONTENT
253 HRESULT
OpenIStorageFromURL_Impl( const OUString
& aURL
, IStorage
** ppIStorage
)
255 OSL_ENSURE( ppIStorage
, "The pointer must not be empty!" );
258 if ( !ppIStorage
|| ::osl::FileBase::getSystemPathFromFileURL( aURL
, aFilePath
) != ::osl::FileBase::E_None
)
259 throw uno::RuntimeException(); // TODO: something dangerous happened
261 return StgOpenStorage( reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
263 STGM_READWRITE
| STGM_TRANSACTED
, // | STGM_DELETEONRELEASE,
270 bool OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM
& aMedium
,
271 const datatransfer::DataFlavor
& aFlavor
,
274 bool bAnyIsReady
= false;
276 // try to convert data from Medium format to specified Flavor format
277 if ( aFlavor
.DataType
== cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() )
279 // first the GDI-metafile must be generated
281 std::unique_ptr
<sal_Int8
[]> pBuf
;
282 sal_uInt32 nBufSize
= 0;
285 if ( aMedium
.tymed
== TYMED_MFPICT
) // Win Metafile
287 aFormat
= "image/x-wmf";
288 METAFILEPICT
* pMF
= static_cast<METAFILEPICT
*>(GlobalLock( aMedium
.hMetaFilePict
));
291 nBufSize
= GetMetaFileBitsEx( pMF
->hMF
, 0, nullptr ) + 22;
292 pBuf
.reset(new sal_Int8
[nBufSize
]);
295 // TODO/LATER: the unit size must be calculated correctly
296 *reinterpret_cast<long*>( pBuf
.get() ) = 0x9ac6cdd7L
;
297 *reinterpret_cast<short*>( pBuf
.get()+6 ) = ( SHORT
) 0;
298 *reinterpret_cast<short*>( pBuf
.get()+8 ) = ( SHORT
) 0;
299 *reinterpret_cast<short*>( pBuf
.get()+10 ) = ( SHORT
) pMF
->xExt
;
300 *reinterpret_cast<short*>( pBuf
.get()+12 ) = ( SHORT
) pMF
->yExt
;
301 *reinterpret_cast<short*>( pBuf
.get()+14 ) = ( USHORT
) 2540;
304 if ( nBufSize
&& nBufSize
== GetMetaFileBitsEx( pMF
->hMF
, nBufSize
- 22, pBuf
.get() + 22 ) )
306 if ( aFlavor
.MimeType
.matchAsciiL( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"", 57 ) )
308 aResult
<<= uno::Sequence
< sal_Int8
>( pBuf
.get(), nBufSize
);
313 GlobalUnlock( aMedium
.hMetaFilePict
);
316 else if ( aMedium
.tymed
== TYMED_ENHMF
) // Enh Metafile
318 aFormat
= "image/x-emf";
319 nBufSize
= GetEnhMetaFileBits( aMedium
.hEnhMetaFile
, 0, nullptr );
320 pBuf
.reset(new sal_Int8
[nBufSize
]);
321 if ( nBufSize
&& nBufSize
== GetEnhMetaFileBits( aMedium
.hEnhMetaFile
, nBufSize
, reinterpret_cast<LPBYTE
>(pBuf
.get()) ) )
323 if ( aFlavor
.MimeType
.matchAsciiL( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"", 57 ) )
325 aResult
<<= uno::Sequence
< sal_Int8
>( pBuf
.get(), nBufSize
);
330 else if ( aMedium
.tymed
== TYMED_GDI
) // Bitmap
332 aFormat
= "image/x-MS-bmp";
333 nBufSize
= GetBitmapBits( aMedium
.hBitmap
, 0, nullptr );
334 pBuf
.reset(new sal_Int8
[nBufSize
]);
335 if ( nBufSize
&& nBufSize
== sal::static_int_cast
< ULONG
>( GetBitmapBits( aMedium
.hBitmap
, nBufSize
, pBuf
.get() ) ) )
337 if ( aFlavor
.MimeType
.matchAsciiL( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"", 54 ) )
339 aResult
<<= uno::Sequence
< sal_Int8
>( pBuf
.get(), nBufSize
);
345 if ( pBuf
&& !bAnyIsReady
)
347 for ( sal_Int32 nInd
= 0; nInd
< m_aSupportedGraphFormats
.getLength(); nInd
++ )
348 if ( aFlavor
.MimeType
.match( m_aSupportedGraphFormats
[nInd
].MimeType
)
349 && aFlavor
.DataType
== m_aSupportedGraphFormats
[nInd
].DataType
350 && aFlavor
.DataType
== cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() )
352 bAnyIsReady
= ConvertBufferToFormat( pBuf
.get(), nBufSize
, aFormat
, aResult
);
362 bool OleComponentNative_Impl::GraphicalFlavor( const datatransfer::DataFlavor
& aFlavor
)
364 // Actually all the required graphical formats must be supported
365 for ( sal_Int32 nInd
= 0; nInd
< m_aSupportedGraphFormats
.getLength(); nInd
++ )
366 if ( aFlavor
.MimeType
.match( m_aSupportedGraphFormats
[nInd
].MimeType
)
367 && aFlavor
.DataType
== m_aSupportedGraphFormats
[nInd
].DataType
)
374 bool GetClassIDFromSequence_Impl( uno::Sequence
< sal_Int8
> const & aSeq
, CLSID
& aResult
)
376 if ( aSeq
.getLength() == 16 )
378 aResult
.Data1
= ( ( ( ( ( ( sal_uInt8
)aSeq
[0] << 8 ) + ( sal_uInt8
)aSeq
[1] ) << 8 ) + ( sal_uInt8
)aSeq
[2] ) << 8 ) + ( sal_uInt8
)aSeq
[3];
379 aResult
.Data2
= ( ( sal_uInt8
)aSeq
[4] << 8 ) + ( sal_uInt8
)aSeq
[5];
380 aResult
.Data3
= ( ( sal_uInt8
)aSeq
[6] << 8 ) + ( sal_uInt8
)aSeq
[7];
381 for( int nInd
= 0; nInd
< 8; nInd
++ )
382 aResult
.Data4
[nInd
] = ( sal_uInt8
)aSeq
[nInd
+8];
391 OUString
WinAccToVcl_Impl( const sal_Unicode
* pStr
)
402 while( *( ++pStr
) == '&' );
406 aResult
+= OUString( pStr
, 1 );
416 OleComponent::OleComponent( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
, OleEmbeddedObject
* pUnoOleObject
)
417 : m_pInterfaceContainer( nullptr )
418 , m_bDisposed( false )
419 , m_bModified( false )
420 , m_pNativeImpl( new OleComponentNative_Impl() )
421 , m_pUnoOleObject( pUnoOleObject
)
422 , m_pOleWrapClientSite( nullptr )
423 , m_pImplAdviseSink( nullptr )
424 , m_nOLEMiscFlags( 0 )
426 , m_xFactory( xFactory
)
427 , m_bOleInitialized( false )
428 , m_bWorkaroundActive( false )
430 OSL_ENSURE( m_pUnoOleObject
, "No owner object is provided!" );
432 HRESULT hr
= OleInitialize( nullptr );
433 OSL_ENSURE( hr
== S_OK
|| hr
== S_FALSE
, "The ole can not be successfully initialized\n" );
434 if ( hr
== S_OK
|| hr
== S_FALSE
)
435 m_bOleInitialized
= true;
437 m_pOleWrapClientSite
= new OleWrapperClientSite( this );
438 m_pOleWrapClientSite
->AddRef();
440 m_pImplAdviseSink
= new OleWrapperAdviseSink( this );
441 m_pImplAdviseSink
->AddRef();
446 OleComponent::~OleComponent()
448 OSL_ENSURE( !m_pOleWrapClientSite
&& !m_pImplAdviseSink
&& !m_pInterfaceContainer
&& !m_bOleInitialized
,
449 "The object was not closed successfully! DISASTER is possible!" );
451 if ( m_pOleWrapClientSite
|| m_pImplAdviseSink
|| m_pInterfaceContainer
|| m_bOleInitialized
)
453 ::osl::MutexGuard
aGuard( m_aMutex
);
457 } catch( const uno::Exception
& ) {}
460 for ( FormatEtcList::iterator aIter
= m_pNativeImpl
->m_aFormatsList
.begin();
461 aIter
!= m_pNativeImpl
->m_aFormatsList
.end();
467 m_pNativeImpl
->m_aFormatsList
.clear();
469 delete m_pNativeImpl
;
472 void OleComponent::Dispose()
474 // the mutex must be locked before this method is called
480 if ( m_pOleWrapClientSite
)
482 m_pOleWrapClientSite
->disconnectOleComponent();
483 m_pOleWrapClientSite
->Release();
484 m_pOleWrapClientSite
= nullptr;
487 if ( m_pImplAdviseSink
)
489 m_pImplAdviseSink
->disconnectOleComponent();
490 m_pImplAdviseSink
->Release();
491 m_pImplAdviseSink
= nullptr;
494 if ( m_pInterfaceContainer
)
496 lang::EventObject
aEvent( static_cast< ::cppu::OWeakObject
* >( this ) );
497 m_pInterfaceContainer
->disposeAndClear( aEvent
);
499 delete m_pInterfaceContainer
;
500 m_pInterfaceContainer
= nullptr;
503 if ( m_bOleInitialized
)
505 // since the disposing can happen not only from main thread but also from a clipboard
506 // the deinitialization might lead to a disaster, SO7 does not deinitialize OLE at all
507 // so currently the same approach is selected as workaround
508 // OleUninitialize();
509 m_bOleInitialized
= false;
516 void OleComponent::disconnectEmbeddedObject()
518 // must not be called from destructor of UNO OLE object!!!
519 osl::MutexGuard
aGuard( m_aMutex
);
520 m_pUnoOleObject
= nullptr;
524 void OleComponent::CreateNewIStorage_Impl()
526 // TODO: in future a global memory could be used instead of file.
528 // write the stream to the temporary file
531 OSL_ENSURE( m_pUnoOleObject
, "Unexpected object absence!" );
532 if ( m_pUnoOleObject
)
533 aTempURL
= m_pUnoOleObject
->CreateTempURLEmpty_Impl();
535 aTempURL
= GetNewTempFileURL_Impl( m_xFactory
);
537 if ( !aTempURL
.getLength() )
538 throw uno::RuntimeException(); // TODO
540 // open an IStorage based on the temporary file
541 OUString aTempFilePath
;
542 if ( ::osl::FileBase::getSystemPathFromFileURL( aTempURL
, aTempFilePath
) != ::osl::FileBase::E_None
)
543 throw uno::RuntimeException(); // TODO: something dangerous happened
545 HRESULT hr
= StgCreateDocfile( reinterpret_cast<LPCWSTR
>(aTempFilePath
.getStr()), STGM_CREATE
| STGM_READWRITE
| STGM_TRANSACTED
| STGM_DELETEONRELEASE
, 0, &m_pNativeImpl
->m_pIStorage
);
546 if ( FAILED( hr
) || !m_pNativeImpl
->m_pIStorage
)
547 throw io::IOException(); // TODO: transport error code?
551 uno::Sequence
< datatransfer::DataFlavor
> OleComponentNative_Impl::GetFlavorsForAspects( sal_uInt32 nSupportedAspects
)
553 uno::Sequence
< datatransfer::DataFlavor
> aResult
;
554 for ( sal_uInt32 nAsp
= 1; nAsp
<= 8; nAsp
*= 2 )
555 if ( ( nSupportedAspects
& nAsp
) == nAsp
)
557 OUString aAspectSuffix
= GetFlavorSuffixFromAspect( nAsp
);
559 sal_Int32 nLength
= aResult
.getLength();
560 aResult
.realloc( nLength
+ m_aSupportedGraphFormats
.getLength() );
562 for ( sal_Int32 nInd
= 0; nInd
< m_aSupportedGraphFormats
.getLength(); nInd
++ )
564 aResult
[nLength
+ nInd
].MimeType
= m_aSupportedGraphFormats
[nInd
].MimeType
+ aAspectSuffix
;
565 aResult
[nLength
+ nInd
].HumanPresentableName
= m_aSupportedGraphFormats
[nInd
].HumanPresentableName
;
566 aResult
[nLength
+ nInd
].DataType
= m_aSupportedGraphFormats
[nInd
].DataType
;
574 void OleComponent::RetrieveObjectDataFlavors_Impl()
576 if ( !m_pNativeImpl
->m_pOleObject
)
577 throw embed::WrongStateException(); // TODO: the object is in wrong state
579 if ( !m_aDataFlavors
.getLength() )
581 ComSmart
< IDataObject
> pDataObject
;
582 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IDataObject
, reinterpret_cast<void**>(&pDataObject
) );
583 if ( SUCCEEDED( hr
) && pDataObject
)
585 ComSmart
< IEnumFORMATETC
> pFormatEnum
;
586 hr
= pDataObject
->EnumFormatEtc( DATADIR_GET
, &pFormatEnum
);
587 if ( SUCCEEDED( hr
) && pFormatEnum
)
589 FORMATETC pElem
[ MAX_ENUM_ELE
];
592 // if it is possible to retrieve at least one supported graphical format for an aspect
593 // this format can be converted to other supported formats
594 sal_uInt32 nSupportedAspects
= 0;
597 HRESULT hr2
= pFormatEnum
->Next( MAX_ENUM_ELE
, pElem
, &nNum
);
598 if( hr2
== S_OK
|| hr2
== S_FALSE
)
600 for( sal_uInt32 nInd
= 0; nInd
< FORMATS_NUM
; nInd
++ )
602 if ( pElem
[nInd
].cfFormat
== pFormatTemplates
[nInd
].cfFormat
603 && pElem
[nInd
].tymed
== pFormatTemplates
[nInd
].tymed
)
604 nSupportedAspects
|= pElem
[nInd
].dwAspect
;
610 while( nNum
== MAX_ENUM_ELE
);
612 m_aDataFlavors
= m_pNativeImpl
->GetFlavorsForAspects( nSupportedAspects
);
616 if ( !m_aDataFlavors
.getLength() )
619 // for any reason the object could not provide this information
620 // try to get access to the cached representation
626 bool OleComponent::InitializeObject_Impl()
627 // There will be no static objects!
629 if ( !m_pNativeImpl
->m_pObj
)
632 // the linked object will be detected here
633 ComSmart
< IOleLink
> pOleLink
;
634 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IOleLink
, reinterpret_cast<void**>(&pOleLink
) );
635 OSL_ENSURE( m_pUnoOleObject
, "Unexpected object absence!" );
636 if ( m_pUnoOleObject
)
637 m_pUnoOleObject
->SetObjectIsLink_Impl( bool( pOleLink
!= nullptr ) );
640 hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IViewObject2
, reinterpret_cast<void**>(&m_pNativeImpl
->m_pViewObject2
) );
641 if ( FAILED( hr
) || !m_pNativeImpl
->m_pViewObject2
)
644 // remove all the caches
645 IOleCache
* pIOleCache
= nullptr;
646 if ( SUCCEEDED( m_pNativeImpl
->m_pObj
->QueryInterface( IID_IOleCache
, reinterpret_cast<void**>(&pIOleCache
) ) ) && pIOleCache
)
648 IEnumSTATDATA
* pEnumSD
= nullptr;
649 HRESULT hr2
= pIOleCache
->EnumCache( &pEnumSD
);
651 if ( SUCCEEDED( hr2
) && pEnumSD
)
656 while( SUCCEEDED( pEnumSD
->Next( 1, &aSD
, &nNum
) ) && nNum
== 1 )
657 hr2
= pIOleCache
->Uncache( aSD
.dwConnection
);
660 // No IDataObject implementation, caching must be used instead
662 FORMATETC aFormat
= { 0, nullptr, DVASPECT_CONTENT
, -1, TYMED_MFPICT
};
663 hr2
= pIOleCache
->Cache( &aFormat
, ADVFCACHE_ONSAVE
, &nConn
);
665 pIOleCache
->Release();
666 pIOleCache
= nullptr;
669 hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IOleObject
, reinterpret_cast<void**>(&m_pNativeImpl
->m_pOleObject
) );
670 if ( FAILED( hr
) || !m_pNativeImpl
->m_pOleObject
)
671 return false; // Static objects are not supported, they should be inserted as graphics
673 m_pNativeImpl
->m_pOleObject
->GetMiscStatus( DVASPECT_CONTENT
, reinterpret_cast<DWORD
*>(&m_nOLEMiscFlags
) );
674 // TODO: use other misc flags also
675 // the object should have drawable aspect even in case it supports only iconic representation
676 // if ( m_nOLEMiscFlags & OLEMISC_ONLYICONIC )
678 m_pNativeImpl
->m_pOleObject
->SetClientSite( m_pOleWrapClientSite
);
680 // the only need in this registration is workaround for close notification
681 m_pNativeImpl
->m_pOleObject
->Advise( m_pImplAdviseSink
, reinterpret_cast<DWORD
*>(&m_nAdvConn
) );
682 m_pNativeImpl
->m_pViewObject2
->SetAdvise( DVASPECT_CONTENT
, 0, m_pImplAdviseSink
);
684 OleSetContainedObject( m_pNativeImpl
->m_pOleObject
, TRUE
);
691 HRESULT
OleLoadSeh(LPSTORAGE pIStorage
, LPVOID
* ppObj
)
695 hr
= OleLoad(pIStorage
, IID_IUnknown
, nullptr, ppObj
);
696 } __except( EXCEPTION_EXECUTE_HANDLER
) {
703 void OleComponent::LoadEmbeddedObject( const OUString
& aTempURL
)
705 if ( !aTempURL
.getLength() )
706 throw lang::IllegalArgumentException(); // TODO
708 if ( m_pNativeImpl
->m_pIStorage
)
709 throw io::IOException(); // TODO the object is already initialized or wrong initialization is done
711 // open an IStorage based on the temporary file
712 HRESULT hr
= OpenIStorageFromURL_Impl( aTempURL
, &m_pNativeImpl
->m_pIStorage
);
714 if ( FAILED( hr
) || !m_pNativeImpl
->m_pIStorage
)
715 throw io::IOException(); // TODO: transport error code?
717 hr
= OleLoadSeh(m_pNativeImpl
->m_pIStorage
, reinterpret_cast<void**>(&m_pNativeImpl
->m_pObj
));
718 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
720 throw uno::RuntimeException();
723 if ( !InitializeObject_Impl() )
724 throw uno::RuntimeException(); // TODO
728 void OleComponent::CreateObjectFromClipboard()
730 if ( m_pNativeImpl
->m_pIStorage
)
731 throw io::IOException(); // TODO:the object is already initialized
733 CreateNewIStorage_Impl();
734 if ( !m_pNativeImpl
->m_pIStorage
)
735 throw uno::RuntimeException(); // TODO
737 IDataObject
* pDO
= nullptr;
738 HRESULT hr
= OleGetClipboard( &pDO
);
739 if( SUCCEEDED( hr
) && pDO
)
741 hr
= OleQueryCreateFromData( pDO
);
742 if( S_OK
== GetScode( hr
) )
744 hr
= OleCreateFromData( pDO
,
746 OLERENDER_DRAW
, // OLERENDER_FORMAT
747 nullptr, // &aFormat,
749 m_pNativeImpl
->m_pIStorage
,
750 reinterpret_cast<void**>(&m_pNativeImpl
->m_pObj
) );
754 // Static objects are not supported
759 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
760 throw uno::RuntimeException();
762 if ( !InitializeObject_Impl() )
763 throw uno::RuntimeException(); // TODO
767 void OleComponent::CreateNewEmbeddedObject( const uno::Sequence
< sal_Int8
>& aSeqCLSID
)
771 if ( !GetClassIDFromSequence_Impl( aSeqCLSID
, aClsID
) )
772 throw lang::IllegalArgumentException(); // TODO
774 if ( m_pNativeImpl
->m_pIStorage
)
775 throw io::IOException(); // TODO:the object is already initialized
777 CreateNewIStorage_Impl();
778 if ( !m_pNativeImpl
->m_pIStorage
)
779 throw uno::RuntimeException(); // TODO
781 // FORMATETC aFormat = { CF_METAFILEPICT, NULL, nAspect, -1, TYMED_MFPICT }; // for OLE..._DRAW should be NULL
783 HRESULT hr
= OleCreate( aClsID
,
785 OLERENDER_DRAW
, // OLERENDER_FORMAT
786 nullptr, // &aFormat,
788 m_pNativeImpl
->m_pIStorage
,
789 reinterpret_cast<void**>(&m_pNativeImpl
->m_pObj
) );
791 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
792 throw uno::RuntimeException(); // TODO
794 if ( !InitializeObject_Impl() )
795 throw uno::RuntimeException(); // TODO
797 // TODO: getExtent???
801 void OleComponent::CreateObjectFromData( const uno::Reference
< datatransfer::XTransferable
>& )
802 // Static objects are not supported, they should be inserted as graphics
804 // TODO: May be this call is useless since there are no static objects
805 // and nonstatic objects will be created based on OLEstorage ( stream ).
808 // OleQueryCreateFromData...
812 void OleComponent::CreateObjectFromFile( const OUString
& aFileURL
)
814 if ( m_pNativeImpl
->m_pIStorage
)
815 throw io::IOException(); // TODO:the object is already initialized
817 CreateNewIStorage_Impl();
818 if ( !m_pNativeImpl
->m_pIStorage
)
819 throw uno::RuntimeException(); // TODO:
822 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL
, aFilePath
) != ::osl::FileBase::E_None
)
823 throw uno::RuntimeException(); // TODO: something dangerous happened
825 HRESULT hr
= OleCreateFromFile( CLSID_NULL
,
826 reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
828 OLERENDER_DRAW
, // OLERENDER_FORMAT
831 m_pNativeImpl
->m_pIStorage
,
832 reinterpret_cast<void**>(&m_pNativeImpl
->m_pObj
) );
834 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
835 throw uno::RuntimeException(); // TODO
837 if ( !InitializeObject_Impl() )
838 throw uno::RuntimeException(); // TODO
842 void OleComponent::CreateLinkFromFile( const OUString
& aFileURL
)
844 if ( m_pNativeImpl
->m_pIStorage
)
845 throw io::IOException(); // TODO:the object is already initialized
847 CreateNewIStorage_Impl();
848 if ( !m_pNativeImpl
->m_pIStorage
)
849 throw uno::RuntimeException(); // TODO:
852 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL
, aFilePath
) != ::osl::FileBase::E_None
)
853 throw uno::RuntimeException(); // TODO: something dangerous happened
855 HRESULT hr
= OleCreateLinkToFile( reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
857 OLERENDER_DRAW
, // OLERENDER_FORMAT
860 m_pNativeImpl
->m_pIStorage
,
861 reinterpret_cast<void**>(&m_pNativeImpl
->m_pObj
) );
863 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
864 throw uno::RuntimeException(); // TODO
866 if ( !InitializeObject_Impl() )
867 throw uno::RuntimeException(); // TODO
871 void OleComponent::InitEmbeddedCopyOfLink( OleComponent
* pOleLinkComponent
)
873 if ( !pOleLinkComponent
|| !pOleLinkComponent
->m_pNativeImpl
->m_pObj
)
874 throw lang::IllegalArgumentException(); // TODO
876 if ( m_pNativeImpl
->m_pIStorage
)
877 throw io::IOException(); // TODO:the object is already initialized
879 ComSmart
< IDataObject
> pDataObject
;
880 HRESULT hr
= pOleLinkComponent
->m_pNativeImpl
->m_pObj
->QueryInterface( IID_IDataObject
, reinterpret_cast<void**>(&pDataObject
) );
881 if ( SUCCEEDED( hr
) && pDataObject
&& SUCCEEDED( OleQueryCreateFromData( pDataObject
) ) )
883 // the object must be already disconnected from the temporary URL
884 CreateNewIStorage_Impl();
885 if ( !m_pNativeImpl
->m_pIStorage
)
886 throw uno::RuntimeException(); // TODO:
888 hr
= OleCreateFromData( pDataObject
,
893 m_pNativeImpl
->m_pIStorage
,
894 reinterpret_cast<void**>(&m_pNativeImpl
->m_pObj
) );
897 if ( !m_pNativeImpl
->m_pObj
)
899 ComSmart
< IOleLink
> pOleLink
;
900 hr
= pOleLinkComponent
->m_pNativeImpl
->m_pObj
->QueryInterface( IID_IOleLink
, reinterpret_cast<void**>(&pOleLink
) );
901 if ( FAILED( hr
) || !pOleLink
)
902 throw io::IOException(); // TODO: the object doesn't support IOleLink
904 ComSmart
< IMoniker
> pMoniker
;
905 hr
= pOleLink
->GetSourceMoniker( &pMoniker
);
906 if ( FAILED( hr
) || !pMoniker
)
907 throw io::IOException(); // TODO: can not retrieve moniker
909 // In case of file moniker life is easy : )
911 hr
= pMoniker
->IsSystemMoniker( &aMonType
);
912 if ( SUCCEEDED( hr
) && aMonType
== MKSYS_FILEMONIKER
)
914 ComSmart
< IMalloc
> pMalloc
;
915 CoGetMalloc( 1, &pMalloc
); // if fails there will be a memory leak
916 OSL_ENSURE( pMalloc
, "CoGetMalloc() failed!" );
918 LPOLESTR pOleStr
= nullptr;
919 hr
= pOleLink
->GetSourceDisplayName( &pOleStr
);
920 if ( SUCCEEDED( hr
) && pOleStr
)
922 OUString
aFilePath( pOleStr
);
924 pMalloc
->Free( pOleStr
);
926 hr
= OleCreateFromFile( CLSID_NULL
,
927 reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
929 OLERENDER_DRAW
, // OLERENDER_FORMAT
932 m_pNativeImpl
->m_pIStorage
,
933 reinterpret_cast<void**>(&m_pNativeImpl
->m_pObj
) );
937 // in case of other moniker types the only way is to get storage
938 if ( !m_pNativeImpl
->m_pObj
)
940 ComSmart
< IBindCtx
> pBindCtx
;
941 hr
= CreateBindCtx( 0, &pBindCtx
);
942 if ( SUCCEEDED( hr
) && pBindCtx
)
944 ComSmart
< IStorage
> pObjectStorage
;
945 hr
= pMoniker
->BindToStorage( pBindCtx
, nullptr, IID_IStorage
, reinterpret_cast<void**>(&pObjectStorage
) );
946 if ( SUCCEEDED( hr
) && pObjectStorage
)
948 hr
= pObjectStorage
->CopyTo( 0, nullptr, nullptr, m_pNativeImpl
->m_pIStorage
);
949 if ( SUCCEEDED( hr
) )
950 hr
= OleLoadSeh(m_pNativeImpl
->m_pIStorage
, reinterpret_cast<void**>(&m_pNativeImpl
->m_pObj
));
956 // If object could not be created the only way is to use graphical representation
957 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
958 throw uno::RuntimeException(); // TODO
960 if ( !InitializeObject_Impl() )
961 throw uno::RuntimeException(); // TODO
965 void OleComponent::RunObject()
967 OSL_ENSURE( m_pNativeImpl
->m_pOleObject
, "The pointer can not be set to NULL here!\n" );
968 if ( !m_pNativeImpl
->m_pOleObject
)
969 throw embed::WrongStateException(); // TODO: the object is in wrong state
971 if ( !OleIsRunning( m_pNativeImpl
->m_pOleObject
) )
973 HRESULT hr
= OleRun( m_pNativeImpl
->m_pObj
);
977 if ( hr
== REGDB_E_CLASSNOTREG
)
978 throw embed::UnreachableStateException(); // the object server is not installed
980 throw io::IOException();
986 awt::Size
OleComponent::CalculateWithFactor( const awt::Size
& aSize
,
987 const awt::Size
& aMultiplier
,
988 const awt::Size
& aDivisor
)
992 sal_Int64 nWidth
= (sal_Int64
)aSize
.Width
* (sal_Int64
)aMultiplier
.Width
/ (sal_Int64
)aDivisor
.Width
;
993 sal_Int64 nHeight
= (sal_Int64
)aSize
.Height
* (sal_Int64
)aMultiplier
.Height
/ (sal_Int64
)aDivisor
.Height
;
994 OSL_ENSURE( nWidth
< SAL_MAX_INT32
&& nWidth
> SAL_MIN_INT32
995 && nHeight
< SAL_MAX_INT32
&& nHeight
> SAL_MIN_INT32
,
996 "Unacceptable result size!" );
998 aResult
.Width
= (sal_Int32
)nWidth
;
999 aResult
.Height
= (sal_Int32
)nHeight
;
1005 void OleComponent::CloseObject()
1007 if ( m_pNativeImpl
->m_pOleObject
&& OleIsRunning( m_pNativeImpl
->m_pOleObject
) )
1008 m_pNativeImpl
->m_pOleObject
->Close( OLECLOSE_NOSAVE
); // must be saved before
1012 uno::Sequence
< embed::VerbDescriptor
> OleComponent::GetVerbList()
1014 if ( !m_pNativeImpl
->m_pOleObject
)
1015 throw embed::WrongStateException(); // TODO: the object is in wrong state
1017 if( !m_aVerbList
.getLength() )
1019 ComSmart
< IEnumOLEVERB
> pEnum
;
1020 if( SUCCEEDED( m_pNativeImpl
->m_pOleObject
->EnumVerbs( &pEnum
) ) )
1022 OLEVERB szEle
[ MAX_ENUM_ELE
];
1024 sal_Int32 nSeqSize
= 0;
1028 HRESULT hr
= pEnum
->Next( MAX_ENUM_ELE
, szEle
, &nNum
);
1029 if( hr
== S_OK
|| hr
== S_FALSE
)
1031 m_aVerbList
.realloc( nSeqSize
+= nNum
);
1032 for( sal_uInt32 nInd
= 0; nInd
< nNum
; nInd
++ )
1034 m_aVerbList
[nSeqSize
-nNum
+nInd
].VerbID
= szEle
[ nInd
].lVerb
;
1035 m_aVerbList
[nSeqSize
-nNum
+nInd
].VerbName
= WinAccToVcl_Impl( reinterpret_cast<const sal_Unicode
*>(szEle
[ nInd
].lpszVerbName
) );
1036 m_aVerbList
[nSeqSize
-nNum
+nInd
].VerbFlags
= szEle
[ nInd
].fuFlags
;
1037 m_aVerbList
[nSeqSize
-nNum
+nInd
].VerbAttributes
= szEle
[ nInd
].grfAttribs
;
1043 while( nNum
== MAX_ENUM_ELE
);
1051 void OleComponent::ExecuteVerb( sal_Int32 nVerbID
)
1053 if ( !m_pNativeImpl
->m_pOleObject
)
1054 throw embed::WrongStateException(); // TODO
1056 HRESULT hr
= OleRun( m_pNativeImpl
->m_pOleObject
);
1058 throw io::IOException(); // TODO: a specific exception that transport error code can be thrown here
1060 // TODO: probably extents should be set here and stored in aRect
1061 // TODO: probably the parent window also should be set
1062 hr
= m_pNativeImpl
->m_pOleObject
->DoVerb( nVerbID
, nullptr, m_pOleWrapClientSite
, 0, nullptr, nullptr );
1065 throw io::IOException(); // TODO
1069 void OleComponent::SetHostName( const OUString
&,
1070 const OUString
& aEmbDocName
)
1072 if ( !m_pNativeImpl
->m_pOleObject
)
1073 throw embed::WrongStateException(); // TODO: the object is in wrong state
1075 m_pNativeImpl
->m_pOleObject
->SetHostNames( L
"app name", reinterpret_cast<const wchar_t*>( aEmbDocName
.getStr() ) );
1079 void OleComponent::SetExtent( const awt::Size
& aVisAreaSize
, sal_Int64 nAspect
)
1081 if ( !m_pNativeImpl
->m_pOleObject
)
1082 throw embed::WrongStateException(); // TODO: the object is in wrong state
1084 DWORD nMSAspect
= ( DWORD
)nAspect
; // first 32 bits are for MS aspects
1086 SIZEL aSize
= { aVisAreaSize
.Width
, aVisAreaSize
.Height
};
1087 HRESULT hr
= m_pNativeImpl
->m_pOleObject
->SetExtent( nMSAspect
, &aSize
);
1091 // TODO/LATER: is it correct? In future user code probably should be ready for the exception.
1092 // if the object is running but not activated, RPC_E_SERVER_DIED error code is returned by OLE package
1093 // in this case just do nothing
1094 // Also Visio returns E_FAIL on resize if it is in running state
1095 // if ( hr != RPC_E_SERVER_DIED )
1096 throw io::IOException(); // TODO
1101 awt::Size
OleComponent::GetExtent( sal_Int64 nAspect
)
1103 if ( !m_pNativeImpl
->m_pOleObject
)
1104 throw embed::WrongStateException(); // TODO: the object is in wrong state
1106 DWORD nMSAspect
= ( DWORD
)nAspect
; // first 32 bits are for MS aspects
1108 bool bGotSize
= false;
1110 if ( nMSAspect
== DVASPECT_CONTENT
)
1112 // Try to get the size from the replacement image first
1113 ComSmart
< IDataObject
> pDataObject
;
1114 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IDataObject
, reinterpret_cast<void**>(&pDataObject
) );
1115 if ( SUCCEEDED( hr
) || pDataObject
)
1118 FORMATETC aFormat
= pFormatTemplates
[1]; // use windows metafile format
1119 aFormat
.dwAspect
= nMSAspect
;
1121 hr
= pDataObject
->GetData( &aFormat
, &aMedium
);
1122 if ( SUCCEEDED( hr
) && aMedium
.tymed
== TYMED_MFPICT
) // Win Metafile
1124 METAFILEPICT
* pMF
= static_cast<METAFILEPICT
*>(GlobalLock( aMedium
.hMetaFilePict
));
1127 // the object uses 0.01 mm as unit, so the metafile size should be converted to object unit
1128 sal_Int64 nMult
= 1;
1152 case MM_ANISOTROPIC
:
1158 sal_Int64 nX
= ( (sal_Int64
)abs( pMF
->xExt
) ) * nMult
/ nDiv
;
1159 sal_Int64 nY
= ( (sal_Int64
)abs( pMF
->yExt
) ) * nMult
/ nDiv
;
1160 if ( nX
< SAL_MAX_INT32
&& nY
< SAL_MAX_INT32
)
1162 aSize
.Width
= ( sal_Int32
)nX
;
1163 aSize
.Height
= ( sal_Int32
)nY
;
1167 OSL_FAIL( "Unexpected size is provided!" );
1170 // i113605, to release storage medium
1171 if ( SUCCEEDED( hr
) )
1172 ::ReleaseStgMedium(&aMedium
);
1177 throw lang::IllegalArgumentException();
1183 awt::Size
OleComponent::GetCachedExtent( sal_Int64 nAspect
)
1185 if ( !m_pNativeImpl
->m_pOleObject
)
1186 throw embed::WrongStateException(); // TODO: the object is in wrong state
1188 DWORD nMSAspect
= ( DWORD
)nAspect
; // first 32 bits are for MS aspects
1191 HRESULT hr
= m_pNativeImpl
->m_pViewObject2
->GetExtent( nMSAspect
, -1, nullptr, &aSize
);
1195 // TODO/LATER: is it correct?
1196 // if there is no appropriate cache for the aspect, OLE_E_BLANK error code is returned
1197 // if ( hr == OLE_E_BLANK )
1198 // throw lang::IllegalArgumentException();
1200 // throw io::IOException(); // TODO
1202 throw lang::IllegalArgumentException();
1205 return awt::Size( aSize
.cx
, aSize
.cy
);
1209 awt::Size
OleComponent::GetReccomendedExtent( sal_Int64 nAspect
)
1211 if ( !m_pNativeImpl
->m_pOleObject
)
1212 throw embed::WrongStateException(); // TODO: the object is in wrong state
1214 DWORD nMSAspect
= ( DWORD
)nAspect
; // first 32 bits are for MS aspects
1216 HRESULT hr
= m_pNativeImpl
->m_pOleObject
->GetExtent( nMSAspect
, &aSize
);
1218 throw lang::IllegalArgumentException();
1220 return awt::Size( aSize
.cx
, aSize
.cy
);
1224 sal_Int64
OleComponent::GetMiscStatus( sal_Int64 nAspect
)
1226 if ( !m_pNativeImpl
->m_pOleObject
)
1227 throw embed::WrongStateException(); // TODO: the object is in wrong state
1230 m_pNativeImpl
->m_pOleObject
->GetMiscStatus( ( DWORD
)nAspect
, &nResult
);
1231 return ( sal_Int64
)nResult
; // first 32 bits are for MS flags
1235 uno::Sequence
< sal_Int8
> OleComponent::GetCLSID()
1237 if ( !m_pNativeImpl
->m_pOleObject
)
1238 throw embed::WrongStateException(); // TODO: the object is in wrong state
1241 HRESULT hr
= m_pNativeImpl
->m_pOleObject
->GetUserClassID( &aCLSID
);
1243 throw io::IOException(); // TODO:
1245 return MimeConfigurationHelper::GetSequenceClassID( aCLSID
.Data1
, aCLSID
.Data2
, aCLSID
.Data3
,
1246 aCLSID
.Data4
[0], aCLSID
.Data4
[1],
1247 aCLSID
.Data4
[2], aCLSID
.Data4
[3],
1248 aCLSID
.Data4
[4], aCLSID
.Data4
[5],
1249 aCLSID
.Data4
[6], aCLSID
.Data4
[7] );
1253 bool OleComponent::IsDirty()
1255 if ( !m_pNativeImpl
->m_pOleObject
)
1256 throw embed::WrongStateException(); // TODO: the object is in wrong state
1258 if ( IsWorkaroundActive() )
1261 ComSmart
< IPersistStorage
> pPersistStorage
;
1262 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IPersistStorage
, reinterpret_cast<void**>(&pPersistStorage
) );
1263 if ( FAILED( hr
) || !pPersistStorage
)
1264 throw io::IOException(); // TODO
1266 hr
= pPersistStorage
->IsDirty();
1267 return ( hr
!= S_FALSE
);
1271 void OleComponent::StoreOwnTmpIfNecessary()
1273 if ( !m_pNativeImpl
->m_pOleObject
)
1274 throw embed::WrongStateException(); // TODO: the object is in wrong state
1276 ComSmart
< IPersistStorage
> pPersistStorage
;
1277 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IPersistStorage
, reinterpret_cast<void**>(&pPersistStorage
) );
1278 if ( FAILED( hr
) || !pPersistStorage
)
1279 throw io::IOException(); // TODO
1281 if ( m_bWorkaroundActive
|| pPersistStorage
->IsDirty() != S_FALSE
)
1283 hr
= OleSave( pPersistStorage
, m_pNativeImpl
->m_pIStorage
, TRUE
);
1286 // Till now was required only for AcrobatReader7.0.8
1288 hr
= m_pNativeImpl
->m_pOleObject
->GetUserClassID( &aCLSID
);
1290 throw io::IOException(); // TODO
1292 hr
= WriteClassStg( m_pNativeImpl
->m_pIStorage
, aCLSID
);
1294 throw io::IOException(); // TODO
1296 // the result of the following call is not checked because some objects, for example AcrobatReader7.0.8
1297 // return error even in case the saving was done correctly
1298 hr
= pPersistStorage
->Save( m_pNativeImpl
->m_pIStorage
, TRUE
);
1300 // another workaround for AcrobatReader7.0.8 object, this object might think that it is not changed
1301 // when it has been created from file, although it must be saved
1302 m_bWorkaroundActive
= true;
1305 hr
= m_pNativeImpl
->m_pIStorage
->Commit( STGC_DEFAULT
);
1307 throw io::IOException(); // TODO
1309 hr
= pPersistStorage
->SaveCompleted( nullptr );
1310 if ( FAILED( hr
) && hr
!= E_UNEXPECTED
)
1311 throw io::IOException(); // TODO
1317 bool OleComponent::SaveObject_Impl()
1319 bool bResult
= false;
1320 OleEmbeddedObject
* pLockObject
= nullptr;
1323 osl::MutexGuard
aGuard( m_aMutex
);
1324 if ( m_pUnoOleObject
)
1326 pLockObject
= m_pUnoOleObject
;
1327 pLockObject
->acquire();
1333 bResult
= pLockObject
->SaveObject_Impl();
1334 pLockObject
->release();
1341 bool OleComponent::OnShowWindow_Impl( bool bShow
)
1343 bool bResult
= false;
1344 OleEmbeddedObject
* pLockObject
= nullptr;
1347 osl::MutexGuard
aGuard( m_aMutex
);
1349 if ( m_pUnoOleObject
)
1351 pLockObject
= m_pUnoOleObject
;
1352 pLockObject
->acquire();
1358 bResult
= pLockObject
->OnShowWindow_Impl( bShow
);
1359 pLockObject
->release();
1366 void OleComponent::OnViewChange_Impl( sal_uInt32 dwAspect
)
1368 // TODO: check if it is enough or may be saving notifications are required for Visio2000
1369 ::rtl::Reference
< OleEmbeddedObject
> xLockObject
;
1372 osl::MutexGuard
aGuard( m_aMutex
);
1373 if ( m_pUnoOleObject
)
1374 xLockObject
= m_pUnoOleObject
;
1377 if ( xLockObject
.is() )
1379 uno::Reference
< awt::XRequestCallback
> xRequestCallback(
1380 m_xFactory
->createInstance("com.sun.star.awt.AsyncCallback"),
1382 xRequestCallback
->addCallback( new MainThreadNotificationRequest( xLockObject
, OLECOMP_ONVIEWCHANGE
, dwAspect
), uno::Any() );
1387 void OleComponent::OnClose_Impl()
1389 ::rtl::Reference
< OleEmbeddedObject
> xLockObject
;
1392 osl::MutexGuard
aGuard( m_aMutex
);
1393 if ( m_pUnoOleObject
)
1394 xLockObject
= m_pUnoOleObject
;
1397 if ( xLockObject
.is() )
1399 uno::Reference
< awt::XRequestCallback
> xRequestCallback(
1400 m_xFactory
->createInstance("com.sun.star.awt.AsyncCallback"),
1402 xRequestCallback
->addCallback( new MainThreadNotificationRequest( xLockObject
, OLECOMP_ONCLOSE
), uno::Any() );
1408 void SAL_CALL
OleComponent::close( sal_Bool bDeliverOwnership
)
1409 throw ( util::CloseVetoException
,
1410 uno::RuntimeException
)
1412 ::osl::MutexGuard
aGuard( m_aMutex
);
1414 throw lang::DisposedException(); // TODO
1416 uno::Reference
< uno::XInterface
> xSelfHold( static_cast< ::cppu::OWeakObject
* >( this ) );
1417 lang::EventObject
aSource( static_cast< ::cppu::OWeakObject
* >( this ) );
1419 if ( m_pInterfaceContainer
)
1421 ::cppu::OInterfaceContainerHelper
* pContainer
=
1422 m_pInterfaceContainer
->getContainer( cppu::UnoType
<util::XCloseListener
>::get());
1423 if ( pContainer
!= nullptr )
1425 ::cppu::OInterfaceIteratorHelper
pIterator( *pContainer
);
1426 while ( pIterator
.hasMoreElements() )
1430 static_cast<util::XCloseListener
*>( pIterator
.next() )->queryClosing( aSource
, bDeliverOwnership
);
1432 catch( const uno::RuntimeException
& )
1439 pContainer
= m_pInterfaceContainer
->getContainer(
1440 cppu::UnoType
<util::XCloseListener
>::get());
1441 if ( pContainer
!= nullptr )
1443 ::cppu::OInterfaceIteratorHelper
pCloseIterator( *pContainer
);
1444 while ( pCloseIterator
.hasMoreElements() )
1448 static_cast<util::XCloseListener
*>( pCloseIterator
.next() )->notifyClosing( aSource
);
1450 catch( const uno::RuntimeException
& )
1452 pCloseIterator
.remove();
1462 void SAL_CALL
OleComponent::addCloseListener( const uno::Reference
< util::XCloseListener
>& xListener
)
1463 throw ( uno::RuntimeException
)
1465 ::osl::MutexGuard
aGuard( m_aMutex
);
1467 throw lang::DisposedException(); // TODO
1469 if ( !m_pInterfaceContainer
)
1470 m_pInterfaceContainer
= new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex
);
1472 m_pInterfaceContainer
->addInterface( cppu::UnoType
<util::XCloseListener
>::get(), xListener
);
1476 void SAL_CALL
OleComponent::removeCloseListener( const uno::Reference
< util::XCloseListener
>& xListener
)
1477 throw ( uno::RuntimeException
)
1479 ::osl::MutexGuard
aGuard( m_aMutex
);
1481 throw lang::DisposedException(); // TODO
1483 if ( m_pInterfaceContainer
)
1484 m_pInterfaceContainer
->removeInterface( cppu::UnoType
<util::XCloseListener
>::get(),
1490 uno::Any SAL_CALL
OleComponent::getTransferData( const datatransfer::DataFlavor
& aFlavor
)
1491 throw ( datatransfer::UnsupportedFlavorException
,
1493 uno::RuntimeException
)
1495 ::osl::MutexGuard
aGuard( m_aMutex
);
1497 throw lang::DisposedException(); // TODO
1499 if ( !m_pNativeImpl
->m_pOleObject
)
1500 throw embed::WrongStateException(); // TODO: the object is in wrong state
1503 bool bSupportedFlavor
= false;
1505 if ( m_pNativeImpl
->GraphicalFlavor( aFlavor
) )
1507 DWORD nRequestedAspect
= GetAspectFromFlavor( aFlavor
);
1508 // if own icon is set and icon aspect is requested the own icon can be returned directly
1510 ComSmart
< IDataObject
> pDataObject
;
1511 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IDataObject
, reinterpret_cast<void**>(&pDataObject
) );
1512 if ( FAILED( hr
) || !pDataObject
)
1513 throw io::IOException(); // TODO: transport error code
1515 // The following optimization does not make much sense currently just because
1516 // only one aspect is supported, and only three formats for the aspect are supported
1517 // and moreover it is not guarantied that the once returned format will be supported further
1519 // TODO/LATER: bring the optimization back when other aspects are supported
1521 // FORMATETC* pFormatEtc = m_pNativeImpl->GetSupportedFormatForAspect( nRequestedAspect );
1522 // if ( pFormatEtc )
1524 // STGMEDIUM aMedium;
1525 // hr = pDataObject->GetData( pFormatEtc, &aMedium );
1526 // if ( SUCCEEDED( hr ) )
1527 // bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
1531 // the supported format of the application is still not found, find one
1532 for ( sal_Int32 nInd
= 0; nInd
< FORMATS_NUM
; nInd
++ )
1535 FORMATETC aFormat
= pFormatTemplates
[nInd
];
1536 aFormat
.dwAspect
= nRequestedAspect
;
1538 hr
= pDataObject
->GetData( &aFormat
, &aMedium
);
1539 if ( SUCCEEDED( hr
) )
1541 bSupportedFlavor
= m_pNativeImpl
->ConvertDataForFlavor( aMedium
, aFlavor
, aResult
);
1542 ::ReleaseStgMedium(&aMedium
); // i113605, to release storage medium
1543 if ( bSupportedFlavor
)
1545 // TODO/LATER: bring the optimization back when other aspects are supported
1546 // m_pNativeImpl->AddSupportedFormat( aFormat );
1553 // If the replacement could not be retrieved, the cached representaion should be used
1554 // currently it is not necessary to retrieve it here, so it is implemented in the object itself
1556 // TODO: Investigate if there is already the format name
1557 // and whether this format is really required
1558 else if ( aFlavor
.DataType
== cppu::UnoType
<io::XInputStream
>::get()
1559 && aFlavor
.MimeType
== "application/x-openoffice-contentstream" )
1561 // allow to retrieve stream-representation of the object persistence
1562 bSupportedFlavor
= true;
1563 uno::Reference
< io::XStream
> xTempFileStream(
1564 io::TempFile::create(comphelper::getComponentContext(m_xFactory
)),
1565 uno::UNO_QUERY_THROW
);
1567 uno::Reference
< io::XOutputStream
> xTempOutStream
= xTempFileStream
->getOutputStream();
1568 uno::Reference
< io::XInputStream
> xTempInStream
= xTempFileStream
->getInputStream();
1569 if ( xTempOutStream
.is() && xTempInStream
.is() )
1571 OSL_ENSURE( m_pUnoOleObject
, "Unexpected object absence!" );
1572 if ( !m_pUnoOleObject
)
1573 throw uno::RuntimeException();
1575 m_pUnoOleObject
->StoreObjectToStream( xTempOutStream
);
1577 xTempOutStream
->closeOutput();
1578 xTempOutStream
.clear();
1581 throw io::IOException(); // TODO:
1583 aResult
<<= xTempInStream
;
1586 if ( !bSupportedFlavor
)
1587 throw datatransfer::UnsupportedFlavorException();
1593 uno::Sequence
< datatransfer::DataFlavor
> SAL_CALL
OleComponent::getTransferDataFlavors()
1594 throw ( uno::RuntimeException
)
1596 ::osl::MutexGuard
aGuard( m_aMutex
);
1598 throw lang::DisposedException(); // TODO
1600 if ( !m_pNativeImpl
->m_pOleObject
)
1601 throw embed::WrongStateException(); // TODO: the object is in wrong state
1603 RetrieveObjectDataFlavors_Impl();
1605 return m_aDataFlavors
;
1609 sal_Bool SAL_CALL
OleComponent::isDataFlavorSupported( const datatransfer::DataFlavor
& aFlavor
)
1610 throw ( uno::RuntimeException
)
1612 ::osl::MutexGuard
aGuard( m_aMutex
);
1614 throw lang::DisposedException(); // TODO
1616 if ( !m_pNativeImpl
->m_pOleObject
)
1617 throw embed::WrongStateException(); // TODO: the object is in wrong state
1619 if ( !m_aDataFlavors
.getLength() )
1621 RetrieveObjectDataFlavors_Impl();
1624 for ( sal_Int32 nInd
= 0; nInd
< m_aDataFlavors
.getLength(); nInd
++ )
1625 if ( m_aDataFlavors
[nInd
].MimeType
.equals( aFlavor
.MimeType
) && m_aDataFlavors
[nInd
].DataType
== aFlavor
.DataType
)
1631 void SAL_CALL
OleComponent::dispose() throw (css::uno::RuntimeException
)
1637 catch ( const uno::Exception
& )
1642 void SAL_CALL
OleComponent::addEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
1643 throw ( uno::RuntimeException
)
1645 ::osl::MutexGuard
aGuard( m_aMutex
);
1647 throw lang::DisposedException(); // TODO
1649 if ( !m_pInterfaceContainer
)
1650 m_pInterfaceContainer
= new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex
);
1652 m_pInterfaceContainer
->addInterface( cppu::UnoType
<lang::XEventListener
>::get(), xListener
);
1656 void SAL_CALL
OleComponent::removeEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
1657 throw ( uno::RuntimeException
)
1659 ::osl::MutexGuard
aGuard( m_aMutex
);
1661 throw lang::DisposedException(); // TODO
1663 if ( m_pInterfaceContainer
)
1664 m_pInterfaceContainer
->removeInterface( cppu::UnoType
<lang::XEventListener
>::get(),
1668 sal_Int64 SAL_CALL
OleComponent::getSomething( const css::uno::Sequence
< sal_Int8
>& aIdentifier
) throw(css::uno::RuntimeException
)
1672 uno::Sequence
< sal_Int8
> aCLSID
= GetCLSID();
1673 if ( MimeConfigurationHelper::ClassIDsEqual( aIdentifier
, aCLSID
) )
1674 return reinterpret_cast<sal_Int64
>(static_cast<IUnknown
*>(m_pNativeImpl
->m_pObj
));
1676 // compatibility hack for old versions: CLSID was used in wrong order (SvGlobalName order)
1677 sal_Int32 nLength
= aIdentifier
.getLength();
1678 if ( nLength
== 16 )
1680 for ( sal_Int32 n
=8; n
<16; n
++ )
1681 if ( aIdentifier
[n
] != aCLSID
[n
] )
1683 if ( aIdentifier
[7] == aCLSID
[6] &&
1684 aIdentifier
[6] == aCLSID
[7] &&
1685 aIdentifier
[5] == aCLSID
[4] &&
1686 aIdentifier
[4] == aCLSID
[5] &&
1687 aIdentifier
[3] == aCLSID
[0] &&
1688 aIdentifier
[2] == aCLSID
[1] &&
1689 aIdentifier
[1] == aCLSID
[2] &&
1690 aIdentifier
[0] == aCLSID
[3] )
1691 return reinterpret_cast<sal_Int64
>(static_cast<IUnknown
*>(m_pNativeImpl
->m_pObj
));
1694 catch ( const uno::Exception
& )
1701 sal_Bool SAL_CALL
OleComponent::isModified() throw (css::uno::RuntimeException
)
1706 void SAL_CALL
OleComponent::setModified( sal_Bool bModified
)
1707 throw (css::beans::PropertyVetoException
, css::uno::RuntimeException
)
1709 m_bModified
= bModified
;
1711 if ( bModified
&& m_pInterfaceContainer
)
1713 ::cppu::OInterfaceContainerHelper
* pContainer
=
1714 m_pInterfaceContainer
->getContainer( cppu::UnoType
<util::XModifyListener
>::get());
1715 if ( pContainer
!= nullptr )
1717 ::cppu::OInterfaceIteratorHelper
pIterator( *pContainer
);
1718 while ( pIterator
.hasMoreElements() )
1722 lang::EventObject
aEvent( static_cast<util::XModifiable
*>(this) );
1723 static_cast<util::XModifyListener
*>(pIterator
.next())->modified( aEvent
);
1725 catch( const uno::RuntimeException
& )
1734 void SAL_CALL
OleComponent::addModifyListener( const css::uno::Reference
< css::util::XModifyListener
>& xListener
) throw(css::uno::RuntimeException
)
1736 ::osl::MutexGuard
aGuard( m_aMutex
);
1738 throw lang::DisposedException(); // TODO
1740 if ( !m_pInterfaceContainer
)
1741 m_pInterfaceContainer
= new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex
);
1743 m_pInterfaceContainer
->addInterface( cppu::UnoType
<util::XModifyListener
>::get(), xListener
);
1746 void SAL_CALL
OleComponent::removeModifyListener( const css::uno::Reference
< css::util::XModifyListener
>& xListener
) throw(css::uno::RuntimeException
)
1748 ::osl::MutexGuard
aGuard( m_aMutex
);
1750 throw lang::DisposedException(); // TODO
1752 if ( m_pInterfaceContainer
)
1753 m_pInterfaceContainer
->removeInterface( cppu::UnoType
<util::XModifyListener
>::get(),
1757 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */