1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <com/sun/star/lang/IllegalArgumentException.hpp>
30 #include <com/sun/star/lang/DisposedException.hpp>
31 #include <com/sun/star/embed/WrongStateException.hpp>
32 #include <com/sun/star/embed/UnreachableStateException.hpp>
33 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/io/XTruncate.hpp>
36 #include <com/sun/star/awt/XRequestCallback.hpp>
39 #include <cppuhelper/interfacecontainer.h>
40 #include <comphelper/mimeconfighelper.hxx>
41 #include <comphelper/storagehelper.hxx>
42 #include <osl/file.hxx>
43 #include <rtl/ref.hxx>
45 #include <olecomponent.hxx>
46 #include <olewrapclient.hxx>
47 #include <advisesink.hxx>
48 #include <oleembobj.hxx>
49 #include <mtnotification.hxx>
51 using namespace ::com::sun::star
;
52 using namespace ::comphelper
;
53 #define MAX_ENUM_ELE 20
56 // ============ class ComSmart =====================
59 template< class T
> class ComSmart
67 T
* pInterface
= m_pInterface
;
69 pInterface
->Release();
75 : m_pInterface( NULL
)
78 ComSmart( const ComSmart
<T
>& rObj
)
79 : m_pInterface( rObj
.m_pInterface
)
81 if ( m_pInterface
!= NULL
)
82 m_pInterface
->AddRef();
85 ComSmart( T
* pInterface
)
86 : m_pInterface( pInterface
)
88 if ( m_pInterface
!= NULL
)
89 m_pInterface
->AddRef();
97 ComSmart
& operator=( const ComSmart
<T
>& rObj
)
101 m_pInterface
= rObj
.m_pInterface
;
103 if ( m_pInterface
!= NULL
)
104 m_pInterface
->AddRef();
109 ComSmart
<T
>& operator=( T
* pInterface
)
113 m_pInterface
= pInterface
;
115 if ( m_pInterface
!= NULL
)
116 m_pInterface
->AddRef();
128 return *m_pInterface
;
137 return &m_pInterface
;
140 T
* operator->() const
145 BOOL
operator==( const ComSmart
<T
>& rObj
) const
147 return ( m_pInterface
== rObj
.m_pInterface
);
150 BOOL
operator!=( const ComSmart
<T
>& rObj
) const
152 return ( m_pInterface
!= rObj
.m_pInterface
);
155 BOOL
operator==( const T
* pInterface
) const
157 return ( m_pInterface
== pInterface
);
160 BOOL
operator!=( const T
* pInterface
) const
162 return ( m_pInterface
!= pInterface
);
168 // ============ class ComSmart =====================
170 sal_Bool
ConvertBufferToFormat( void* pBuf
,
172 const ::rtl::OUString
& aFormatShortName
,
175 ::rtl::OUString
GetNewTempFileURL_Impl( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
) throw( io::IOException
);
177 typedef ::std::vector
< FORMATETC
* > FormatEtcList
;
179 FORMATETC pFormatTemplates
[FORMATS_NUM
] = {
180 { CF_ENHMETAFILE
, NULL
, 0, -1, TYMED_ENHMF
},
181 { CF_METAFILEPICT
, NULL
, 0, -1, TYMED_MFPICT
},
182 { CF_BITMAP
, NULL
, 0, -1, TYMED_GDI
} };
185 struct OleComponentNative_Impl
{
186 ComSmart
< IUnknown
> m_pObj
;
187 ComSmart
< IOleObject
> m_pOleObject
;
188 ComSmart
< IViewObject2
> m_pViewObject2
;
189 ComSmart
< IStorage
> m_pIStorage
;
190 FormatEtcList m_aFormatsList
;
191 uno::Sequence
< datatransfer::DataFlavor
> m_aSupportedGraphFormats
;
193 OleComponentNative_Impl()
195 // TODO: Extend format list
196 m_aSupportedGraphFormats
.realloc( 5 );
198 m_aSupportedGraphFormats
[0] = datatransfer::DataFlavor(
199 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" )),
200 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Windows Enhanced Metafile" )),
201 getCppuType( (const uno::Sequence
< sal_Int8
>*) 0 ) );
203 m_aSupportedGraphFormats
[1] = datatransfer::DataFlavor(
204 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" )),
205 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Windows Metafile" )),
206 getCppuType( (const uno::Sequence
< sal_Int8
>*) 0 ) );
208 m_aSupportedGraphFormats
[2] = datatransfer::DataFlavor(
209 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" )),
210 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Bitmap" )),
211 getCppuType( (const uno::Sequence
< sal_Int8
>*) 0 ) );
213 m_aSupportedGraphFormats
[3] = datatransfer::DataFlavor(
214 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "image/png" )),
215 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "PNG" )),
216 getCppuType( (const uno::Sequence
< sal_Int8
>*) 0 ) );
218 m_aSupportedGraphFormats
[0] = datatransfer::DataFlavor(
219 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" )),
220 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "GDIMetafile" )),
221 getCppuType( (const uno::Sequence
< sal_Int8
>*) 0 ) );
224 void AddSupportedFormat( const FORMATETC
& aFormatEtc
);
226 FORMATETC
* GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect
);
228 sal_Bool
ConvertDataForFlavor( const STGMEDIUM
& aMedium
,
229 const datatransfer::DataFlavor
& aFlavor
,
232 sal_Bool
GraphicalFlavor( const datatransfer::DataFlavor
& aFlavor
);
234 uno::Sequence
< datatransfer::DataFlavor
> GetFlavorsForAspects( sal_uInt32 nSupportedAspects
);
237 //----------------------------------------------
238 DWORD
GetAspectFromFlavor( const datatransfer::DataFlavor
& aFlavor
)
240 if ( aFlavor
.MimeType
.indexOf( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ";Aspect=THUMBNAIL" )) ) != -1 )
241 return DVASPECT_THUMBNAIL
;
242 else if ( aFlavor
.MimeType
.indexOf( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ";Aspect=ICON" )) ) != -1 )
243 return DVASPECT_ICON
;
244 else if ( aFlavor
.MimeType
.indexOf( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ";Aspect=DOCPRINT" )) ) != -1 )
245 return DVASPECT_DOCPRINT
;
247 return DVASPECT_CONTENT
;
250 //----------------------------------------------
251 ::rtl::OUString
GetFlavorSuffixFromAspect( DWORD nAsp
)
253 ::rtl::OUString aResult
;
255 if ( nAsp
== DVASPECT_THUMBNAIL
)
256 aResult
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ";Aspect=THUMBNAIL" ));
257 else if ( nAsp
== DVASPECT_ICON
)
258 aResult
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ";Aspect=ICON" ));
259 else if ( nAsp
== DVASPECT_DOCPRINT
)
260 aResult
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ";Aspect=DOCPRINT" ));
262 // no suffix for DVASPECT_CONTENT
267 //----------------------------------------------
268 HRESULT
OpenIStorageFromURL_Impl( const ::rtl::OUString
& aURL
, IStorage
** ppIStorage
)
270 OSL_ENSURE( ppIStorage
, "The pointer must not be empty!" );
272 ::rtl::OUString aFilePath
;
273 if ( !ppIStorage
|| ::osl::FileBase::getSystemPathFromFileURL( aURL
, aFilePath
) != ::osl::FileBase::E_None
)
274 throw uno::RuntimeException(); // TODO: something dangerous happend
276 return StgOpenStorage( reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
278 STGM_READWRITE
| STGM_TRANSACTED
, // | STGM_DELETEONRELEASE,
284 //----------------------------------------------
285 sal_Bool
OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM
& aMedium
,
286 const datatransfer::DataFlavor
& aFlavor
,
289 sal_Bool bAnyIsReady
= sal_False
;
291 // try to convert data from Medium format to specified Flavor format
292 if ( aFlavor
.DataType
== getCppuType( ( const uno::Sequence
< sal_Int8
>* ) 0 ) )
294 // first the GDI-metafile must be generated
296 unsigned char* pBuf
= NULL
;
297 sal_uInt32 nBufSize
= 0;
298 ::rtl::OUString aFormat
;
300 if ( aMedium
.tymed
== TYMED_MFPICT
) // Win Metafile
302 aFormat
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("image/x-wmf"));
303 METAFILEPICT
* pMF
= ( METAFILEPICT
* )GlobalLock( aMedium
.hMetaFilePict
);
306 nBufSize
= GetMetaFileBitsEx( pMF
->hMF
, 0, NULL
) + 22;
307 pBuf
= new unsigned char[nBufSize
];
310 // TODO/LATER: the unit size must be calculated correctly
311 *( (long* )pBuf
) = 0x9ac6cdd7L
;
312 *( (short* )( pBuf
+6 )) = ( SHORT
) 0;
313 *( (short* )( pBuf
+8 )) = ( SHORT
) 0;
314 *( (short* )( pBuf
+10 )) = ( SHORT
) pMF
->xExt
;
315 *( (short* )( pBuf
+12 )) = ( SHORT
) pMF
->yExt
;
316 *( (short* )( pBuf
+14 )) = ( USHORT
) 2540;
319 if ( nBufSize
&& nBufSize
== GetMetaFileBitsEx( pMF
->hMF
, nBufSize
- 22, pBuf
+ 22 ) )
321 if ( aFlavor
.MimeType
.matchAsciiL( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"", 57 ) )
323 aResult
<<= uno::Sequence
< sal_Int8
>( ( sal_Int8
* )pBuf
, nBufSize
);
324 bAnyIsReady
= sal_True
;
328 GlobalUnlock( aMedium
.hMetaFilePict
);
331 else if ( aMedium
.tymed
== TYMED_ENHMF
) // Enh Metafile
333 aFormat
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("image/x-emf"));
334 nBufSize
= GetEnhMetaFileBits( aMedium
.hEnhMetaFile
, 0, NULL
);
335 pBuf
= new unsigned char[nBufSize
];
336 if ( nBufSize
&& nBufSize
== GetEnhMetaFileBits( aMedium
.hEnhMetaFile
, nBufSize
, pBuf
) )
338 if ( aFlavor
.MimeType
.matchAsciiL( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"", 57 ) )
340 aResult
<<= uno::Sequence
< sal_Int8
>( ( sal_Int8
* )pBuf
, nBufSize
);
341 bAnyIsReady
= sal_True
;
345 else if ( aMedium
.tymed
== TYMED_GDI
) // Bitmap
347 aFormat
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("image/x-MS-bmp"));
348 nBufSize
= GetBitmapBits( aMedium
.hBitmap
, 0, NULL
);
349 pBuf
= new unsigned char[nBufSize
];
350 if ( nBufSize
&& nBufSize
== sal::static_int_cast
< ULONG
>( GetBitmapBits( aMedium
.hBitmap
, nBufSize
, pBuf
) ) )
352 if ( aFlavor
.MimeType
.matchAsciiL( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"", 54 ) )
354 aResult
<<= uno::Sequence
< sal_Int8
>( ( sal_Int8
* )pBuf
, nBufSize
);
355 bAnyIsReady
= sal_True
;
360 if ( pBuf
&& !bAnyIsReady
)
362 for ( sal_Int32 nInd
= 0; nInd
< m_aSupportedGraphFormats
.getLength(); nInd
++ )
363 if ( aFlavor
.MimeType
.match( m_aSupportedGraphFormats
[nInd
].MimeType
)
364 && aFlavor
.DataType
== m_aSupportedGraphFormats
[nInd
].DataType
365 && aFlavor
.DataType
== getCppuType( (const uno::Sequence
< sal_Int8
>*) 0 ) )
367 bAnyIsReady
= ConvertBufferToFormat( ( void* )pBuf
, nBufSize
, aFormat
, aResult
);
378 //----------------------------------------------
379 sal_Bool
OleComponentNative_Impl::GraphicalFlavor( const datatransfer::DataFlavor
& aFlavor
)
381 // Actually all the required graphical formats must be supported
382 for ( sal_Int32 nInd
= 0; nInd
< m_aSupportedGraphFormats
.getLength(); nInd
++ )
383 if ( aFlavor
.MimeType
.match( m_aSupportedGraphFormats
[nInd
].MimeType
)
384 && aFlavor
.DataType
== m_aSupportedGraphFormats
[nInd
].DataType
)
390 //----------------------------------------------
391 sal_Bool
GetClassIDFromSequence_Impl( uno::Sequence
< sal_Int8
> aSeq
, CLSID
& aResult
)
393 if ( aSeq
.getLength() == 16 )
395 aResult
.Data1
= ( ( ( ( ( ( sal_uInt8
)aSeq
[0] << 8 ) + ( sal_uInt8
)aSeq
[1] ) << 8 ) + ( sal_uInt8
)aSeq
[2] ) << 8 ) + ( sal_uInt8
)aSeq
[3];
396 aResult
.Data2
= ( ( sal_uInt8
)aSeq
[4] << 8 ) + ( sal_uInt8
)aSeq
[5];
397 aResult
.Data3
= ( ( sal_uInt8
)aSeq
[6] << 8 ) + ( sal_uInt8
)aSeq
[7];
398 for( int nInd
= 0; nInd
< 8; nInd
++ )
399 aResult
.Data4
[nInd
] = ( sal_uInt8
)aSeq
[nInd
+8];
407 //----------------------------------------------
408 ::rtl::OUString
WinAccToVcl_Impl( const sal_Unicode
* pStr
)
410 ::rtl::OUString aResult
;
418 aResult
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "~" ));
419 while( *( ++pStr
) == '&' );
423 aResult
+= ::rtl::OUString( pStr
, 1 );
432 //----------------------------------------------
433 OleComponent::OleComponent( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
, OleEmbeddedObject
* pUnoOleObject
)
434 : m_pInterfaceContainer( NULL
)
435 , m_bDisposed( sal_False
)
436 , m_bModified( sal_False
)
437 , m_pNativeImpl( new OleComponentNative_Impl() )
438 , m_pUnoOleObject( pUnoOleObject
)
439 , m_pOleWrapClientSite( NULL
)
440 , m_pImplAdviseSink( NULL
)
441 , m_nOLEMiscFlags( 0 )
443 , m_xFactory( xFactory
)
444 , m_bOleInitialized( sal_False
)
445 , m_bWorkaroundActive( sal_False
)
447 OSL_ENSURE( m_pUnoOleObject
, "No owner object is provided!" );
449 HRESULT hr
= OleInitialize( NULL
);
450 OSL_ENSURE( hr
== S_OK
|| hr
== S_FALSE
, "The ole can not be successfuly initialized\n" );
451 if ( hr
== S_OK
|| hr
== S_FALSE
)
452 m_bOleInitialized
= sal_True
;
454 m_pOleWrapClientSite
= new OleWrapperClientSite( ( OleComponent
* )this );
455 m_pOleWrapClientSite
->AddRef();
457 m_pImplAdviseSink
= new OleWrapperAdviseSink( ( OleComponent
* )this );
458 m_pImplAdviseSink
->AddRef();
462 //----------------------------------------------
463 OleComponent::~OleComponent()
465 OSL_ENSURE( !m_pOleWrapClientSite
&& !m_pImplAdviseSink
&& !m_pInterfaceContainer
&& !m_bOleInitialized
,
466 "The object was not closed successfully! DISASTER is possible!" );
468 if ( m_pOleWrapClientSite
|| m_pImplAdviseSink
|| m_pInterfaceContainer
|| m_bOleInitialized
)
470 ::osl::MutexGuard
aGuard( m_aMutex
);
474 } catch( const uno::Exception
& ) {}
477 for ( FormatEtcList::iterator aIter
= m_pNativeImpl
->m_aFormatsList
.begin();
478 aIter
!= m_pNativeImpl
->m_aFormatsList
.end();
484 m_pNativeImpl
->m_aFormatsList
.clear();
486 delete m_pNativeImpl
;
489 //----------------------------------------------
490 void OleComponentNative_Impl::AddSupportedFormat( const FORMATETC
& aFormatEtc
)
492 FORMATETC
* pFormatToInsert
= new FORMATETC( aFormatEtc
);
493 m_aFormatsList
.push_back( pFormatToInsert
);
496 //----------------------------------------------
497 FORMATETC
* OleComponentNative_Impl::GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect
)
499 for ( FormatEtcList::iterator aIter
= m_aFormatsList
.begin();
500 aIter
!= m_aFormatsList
.end();
502 if ( (*aIter
) && (*aIter
)->dwAspect
== nRequestedAspect
)
508 //----------------------------------------------
509 void OleComponent::Dispose()
511 // the mutex must be locked before this method is called
517 if ( m_pOleWrapClientSite
)
519 m_pOleWrapClientSite
->disconnectOleComponent();
520 m_pOleWrapClientSite
->Release();
521 m_pOleWrapClientSite
= NULL
;
524 if ( m_pImplAdviseSink
)
526 m_pImplAdviseSink
->disconnectOleComponent();
527 m_pImplAdviseSink
->Release();
528 m_pImplAdviseSink
= NULL
;
531 if ( m_pInterfaceContainer
)
533 lang::EventObject
aEvent( static_cast< ::cppu::OWeakObject
* >( this ) );
534 m_pInterfaceContainer
->disposeAndClear( aEvent
);
536 delete m_pInterfaceContainer
;
537 m_pInterfaceContainer
= NULL
;
540 if ( m_bOleInitialized
)
542 // since the disposing can happen not only from main thread but also from a clipboard
543 // the deinitialization might lead to a disaster, SO7 does not deinitialize OLE at all
544 // so currently the same approach is selected as workaround
545 // OleUninitialize();
546 m_bOleInitialized
= sal_False
;
549 m_bDisposed
= sal_True
;
552 //----------------------------------------------
553 void OleComponent::disconnectEmbeddedObject()
555 // must not be called from destructor of UNO OLE object!!!
556 osl::MutexGuard
aGuard( m_aMutex
);
557 m_pUnoOleObject
= NULL
;
560 //----------------------------------------------
561 void OleComponent::CreateNewIStorage_Impl()
563 // TODO: in future a global memory could be used instead of file.
565 // write the stream to the temporary file
566 ::rtl::OUString aTempURL
;
568 OSL_ENSURE( m_pUnoOleObject
, "Unexpected object absence!" );
569 if ( m_pUnoOleObject
)
570 aTempURL
= m_pUnoOleObject
->CreateTempURLEmpty_Impl();
572 aTempURL
= GetNewTempFileURL_Impl( m_xFactory
);
574 if ( !aTempURL
.getLength() )
575 throw uno::RuntimeException(); // TODO
577 // open an IStorage based on the temporary file
578 ::rtl::OUString aTempFilePath
;
579 if ( ::osl::FileBase::getSystemPathFromFileURL( aTempURL
, aTempFilePath
) != ::osl::FileBase::E_None
)
580 throw uno::RuntimeException(); // TODO: something dangerous happend
582 HRESULT hr
= StgCreateDocfile( reinterpret_cast<LPCWSTR
>(aTempFilePath
.getStr()), STGM_CREATE
| STGM_READWRITE
| STGM_TRANSACTED
| STGM_DELETEONRELEASE
, 0, &m_pNativeImpl
->m_pIStorage
);
583 if ( FAILED( hr
) || !m_pNativeImpl
->m_pIStorage
)
584 throw io::IOException(); // TODO: transport error code?
587 //----------------------------------------------
588 uno::Sequence
< datatransfer::DataFlavor
> OleComponentNative_Impl::GetFlavorsForAspects( sal_uInt32 nSupportedAspects
)
590 uno::Sequence
< datatransfer::DataFlavor
> aResult
;
591 for ( sal_uInt32 nAsp
= 1; nAsp
<= 8; nAsp
*= 2 )
592 if ( ( nSupportedAspects
& nAsp
) == nAsp
)
594 ::rtl::OUString aAspectSuffix
= GetFlavorSuffixFromAspect( nAsp
);
596 sal_Int32 nLength
= aResult
.getLength();
597 aResult
.realloc( nLength
+ m_aSupportedGraphFormats
.getLength() );
599 for ( sal_Int32 nInd
= 0; nInd
< m_aSupportedGraphFormats
.getLength(); nInd
++ )
601 aResult
[nLength
+ nInd
].MimeType
= m_aSupportedGraphFormats
[nInd
].MimeType
+ aAspectSuffix
;
602 aResult
[nLength
+ nInd
].HumanPresentableName
= m_aSupportedGraphFormats
[nInd
].HumanPresentableName
;
603 aResult
[nLength
+ nInd
].DataType
= m_aSupportedGraphFormats
[nInd
].DataType
;
610 //----------------------------------------------
611 void OleComponent::RetrieveObjectDataFlavors_Impl()
613 if ( !m_pNativeImpl
->m_pOleObject
)
614 throw embed::WrongStateException(); // TODO: the object is in wrong state
616 if ( !m_aDataFlavors
.getLength() )
618 ComSmart
< IDataObject
> pDataObject
;
619 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IDataObject
, (void**)&pDataObject
);
620 if ( SUCCEEDED( hr
) && pDataObject
)
622 ComSmart
< IEnumFORMATETC
> pFormatEnum
;
623 hr
= pDataObject
->EnumFormatEtc( DATADIR_GET
, &pFormatEnum
);
624 if ( SUCCEEDED( hr
) && pFormatEnum
)
626 FORMATETC pElem
[ MAX_ENUM_ELE
];
629 // if it is possible to retrieve at least one supported graphical format for an aspect
630 // this format can be converted to other supported formats
631 sal_uInt32 nSupportedAspects
= 0;
634 HRESULT hr2
= pFormatEnum
->Next( MAX_ENUM_ELE
, pElem
, &nNum
);
635 if( hr2
== S_OK
|| hr2
== S_FALSE
)
637 for( sal_uInt32 nInd
= 0; nInd
< FORMATS_NUM
; nInd
++ )
639 if ( pElem
[nInd
].cfFormat
== pFormatTemplates
[nInd
].cfFormat
640 && pElem
[nInd
].tymed
== pFormatTemplates
[nInd
].tymed
)
641 nSupportedAspects
|= pElem
[nInd
].dwAspect
;
647 while( nNum
== MAX_ENUM_ELE
);
649 m_aDataFlavors
= m_pNativeImpl
->GetFlavorsForAspects( nSupportedAspects
);
653 if ( !m_aDataFlavors
.getLength() )
656 // for any reason the object could not provide this information
657 // try to get access to the cached representation
662 //----------------------------------------------
663 sal_Bool
OleComponent::InitializeObject_Impl()
664 // There will be no static objects!
666 if ( !m_pNativeImpl
->m_pObj
)
669 // the linked object will be detected here
670 ComSmart
< IOleLink
> pOleLink
;
671 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IOleLink
, (void**)&pOleLink
);
672 OSL_ENSURE( m_pUnoOleObject
, "Unexpected object absence!" );
673 if ( m_pUnoOleObject
)
674 m_pUnoOleObject
->SetObjectIsLink_Impl( sal_Bool( pOleLink
!= NULL
) );
677 hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IViewObject2
, (void**)&m_pNativeImpl
->m_pViewObject2
);
678 if ( FAILED( hr
) || !m_pNativeImpl
->m_pViewObject2
)
682 // remove all the caches
683 IOleCache
* pIOleCache
= NULL
;
684 if ( SUCCEEDED( m_pNativeImpl
->m_pObj
->QueryInterface( IID_IOleCache
, (void**)&pIOleCache
) ) && pIOleCache
)
686 IEnumSTATDATA
* pEnumSD
= NULL
;
687 HRESULT hr2
= pIOleCache
->EnumCache( &pEnumSD
);
689 if ( SUCCEEDED( hr2
) && pEnumSD
)
694 while( SUCCEEDED( pEnumSD
->Next( 1, &aSD
, &nNum
) ) && nNum
== 1 )
695 hr2
= pIOleCache
->Uncache( aSD
.dwConnection
);
698 // No IDataObject implementation, caching must be used instead
700 FORMATETC aFormat
= { 0, 0, DVASPECT_CONTENT
, -1, TYMED_MFPICT
};
701 hr2
= pIOleCache
->Cache( &aFormat
, ADVFCACHE_ONSAVE
, &nConn
);
703 pIOleCache
->Release();
707 hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IOleObject
, (void**)&m_pNativeImpl
->m_pOleObject
);
708 if ( FAILED( hr
) || !m_pNativeImpl
->m_pOleObject
)
709 return sal_False
; // Static objects are not supported, they should be inserted as graphics
711 m_pNativeImpl
->m_pOleObject
->GetMiscStatus( DVASPECT_CONTENT
, ( DWORD
* )&m_nOLEMiscFlags
);
712 // TODO: use other misc flags also
713 // the object should have drawable aspect even in case it supports only iconic representation
714 // if ( m_nOLEMiscFlags & OLEMISC_ONLYICONIC )
716 m_pNativeImpl
->m_pOleObject
->SetClientSite( m_pOleWrapClientSite
);
718 // the only need in this registration is workaround for close notification
719 m_pNativeImpl
->m_pOleObject
->Advise( m_pImplAdviseSink
, ( DWORD
* )&m_nAdvConn
);
720 m_pNativeImpl
->m_pViewObject2
->SetAdvise( DVASPECT_CONTENT
, 0, m_pImplAdviseSink
);
722 OleSetContainedObject( m_pNativeImpl
->m_pOleObject
, TRUE
);
727 //----------------------------------------------
728 void OleComponent::LoadEmbeddedObject( const ::rtl::OUString
& aTempURL
)
730 if ( !aTempURL
.getLength() )
731 throw lang::IllegalArgumentException(); // TODO
733 if ( m_pNativeImpl
->m_pIStorage
)
734 throw io::IOException(); // TODO the object is already initialized or wrong initialization is done
736 // open an IStorage based on the temporary file
737 HRESULT hr
= OpenIStorageFromURL_Impl( aTempURL
, &m_pNativeImpl
->m_pIStorage
);
739 if ( FAILED( hr
) || !m_pNativeImpl
->m_pIStorage
)
740 throw io::IOException(); // TODO: transport error code?
742 hr
= OleLoad( m_pNativeImpl
->m_pIStorage
, IID_IUnknown
, NULL
, (void**)&m_pNativeImpl
->m_pObj
);
743 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
745 throw uno::RuntimeException();
748 if ( !InitializeObject_Impl() )
749 throw uno::RuntimeException(); // TODO
752 //----------------------------------------------
753 void OleComponent::CreateObjectFromClipboard()
755 if ( m_pNativeImpl
->m_pIStorage
)
756 throw io::IOException(); // TODO:the object is already initialized
758 CreateNewIStorage_Impl();
759 if ( !m_pNativeImpl
->m_pIStorage
)
760 throw uno::RuntimeException(); // TODO
762 IDataObject
* pDO
= NULL
;
763 HRESULT hr
= OleGetClipboard( &pDO
);
764 if( SUCCEEDED( hr
) && pDO
)
766 hr
= OleQueryCreateFromData( pDO
);
767 if( S_OK
== GetScode( hr
) )
769 hr
= OleCreateFromData( pDO
,
771 OLERENDER_DRAW
, // OLERENDER_FORMAT
774 m_pNativeImpl
->m_pIStorage
,
775 (void**)&m_pNativeImpl
->m_pObj
);
779 // Static objects are not supported
784 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
785 throw uno::RuntimeException();
787 if ( !InitializeObject_Impl() )
788 throw uno::RuntimeException(); // TODO
791 //----------------------------------------------
792 void OleComponent::CreateNewEmbeddedObject( const uno::Sequence
< sal_Int8
>& aSeqCLSID
)
796 if ( !GetClassIDFromSequence_Impl( aSeqCLSID
, aClsID
) )
797 throw lang::IllegalArgumentException(); // TODO
799 if ( m_pNativeImpl
->m_pIStorage
)
800 throw io::IOException(); // TODO:the object is already initialized
802 CreateNewIStorage_Impl();
803 if ( !m_pNativeImpl
->m_pIStorage
)
804 throw uno::RuntimeException(); // TODO
806 // FORMATETC aFormat = { CF_METAFILEPICT, NULL, nAspect, -1, TYMED_MFPICT }; // for OLE..._DRAW should be NULL
808 HRESULT hr
= OleCreate( aClsID
,
810 OLERENDER_DRAW
, // OLERENDER_FORMAT
813 m_pNativeImpl
->m_pIStorage
,
814 (void**)&m_pNativeImpl
->m_pObj
);
816 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
817 throw uno::RuntimeException(); // TODO
819 if ( !InitializeObject_Impl() )
820 throw uno::RuntimeException(); // TODO
822 // TODO: getExtent???
825 //----------------------------------------------
826 void OleComponent::CreateObjectFromData( const uno::Reference
< datatransfer::XTransferable
>& )
827 // Static objects are not supported, they should be inserted as graphics
829 // TODO: May be this call is useless since there are no static objects
830 // and nonstatic objects will be created based on OLEstorage ( stream ).
833 // OleQueryCreateFromData...
836 //----------------------------------------------
837 void OleComponent::CreateObjectFromFile( const ::rtl::OUString
& aFileURL
)
839 if ( m_pNativeImpl
->m_pIStorage
)
840 throw io::IOException(); // TODO:the object is already initialized
842 CreateNewIStorage_Impl();
843 if ( !m_pNativeImpl
->m_pIStorage
)
844 throw uno::RuntimeException(); // TODO:
846 ::rtl::OUString aFilePath
;
847 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL
, aFilePath
) != ::osl::FileBase::E_None
)
848 throw uno::RuntimeException(); // TODO: something dangerous happend
850 HRESULT hr
= OleCreateFromFile( CLSID_NULL
,
851 reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
853 OLERENDER_DRAW
, // OLERENDER_FORMAT
856 m_pNativeImpl
->m_pIStorage
,
857 (void**)&m_pNativeImpl
->m_pObj
);
859 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
860 throw uno::RuntimeException(); // TODO
862 if ( !InitializeObject_Impl() )
863 throw uno::RuntimeException(); // TODO
866 //----------------------------------------------
867 void OleComponent::CreateLinkFromFile( const ::rtl::OUString
& aFileURL
)
869 if ( m_pNativeImpl
->m_pIStorage
)
870 throw io::IOException(); // TODO:the object is already initialized
872 CreateNewIStorage_Impl();
873 if ( !m_pNativeImpl
->m_pIStorage
)
874 throw uno::RuntimeException(); // TODO:
876 ::rtl::OUString aFilePath
;
877 if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL
, aFilePath
) != ::osl::FileBase::E_None
)
878 throw uno::RuntimeException(); // TODO: something dangerous happend
880 HRESULT hr
= OleCreateLinkToFile( reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
882 OLERENDER_DRAW
, // OLERENDER_FORMAT
885 m_pNativeImpl
->m_pIStorage
,
886 (void**)&m_pNativeImpl
->m_pObj
);
888 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
889 throw uno::RuntimeException(); // TODO
891 if ( !InitializeObject_Impl() )
892 throw uno::RuntimeException(); // TODO
895 //----------------------------------------------
896 void OleComponent::InitEmbeddedCopyOfLink( OleComponent
* pOleLinkComponent
)
898 if ( !pOleLinkComponent
|| !pOleLinkComponent
->m_pNativeImpl
->m_pObj
)
899 throw lang::IllegalArgumentException(); // TODO
901 if ( m_pNativeImpl
->m_pIStorage
)
902 throw io::IOException(); // TODO:the object is already initialized
904 ComSmart
< IDataObject
> pDataObject
;
905 HRESULT hr
= pOleLinkComponent
->m_pNativeImpl
->m_pObj
->QueryInterface( IID_IDataObject
, (void**)&pDataObject
);
906 if ( SUCCEEDED( hr
) && pDataObject
&& SUCCEEDED( OleQueryCreateFromData( pDataObject
) ) )
908 // the object must be already disconnected from the temporary URL
909 CreateNewIStorage_Impl();
910 if ( !m_pNativeImpl
->m_pIStorage
)
911 throw uno::RuntimeException(); // TODO:
913 hr
= OleCreateFromData( pDataObject
,
918 m_pNativeImpl
->m_pIStorage
,
919 (void**)&m_pNativeImpl
->m_pObj
);
922 if ( !m_pNativeImpl
->m_pObj
)
924 ComSmart
< IOleLink
> pOleLink
;
925 hr
= pOleLinkComponent
->m_pNativeImpl
->m_pObj
->QueryInterface( IID_IOleLink
, (void**)&pOleLink
);
926 if ( FAILED( hr
) || !pOleLink
)
927 throw io::IOException(); // TODO: the object doesn't support IOleLink
929 ComSmart
< IMoniker
> pMoniker
;
930 hr
= pOleLink
->GetSourceMoniker( &pMoniker
);
931 if ( FAILED( hr
) || !pMoniker
)
932 throw io::IOException(); // TODO: can not retrieve moniker
934 // In case of file moniker life is easy : )
936 hr
= pMoniker
->IsSystemMoniker( &aMonType
);
937 if ( SUCCEEDED( hr
) && aMonType
== MKSYS_FILEMONIKER
)
939 ComSmart
< IMalloc
> pMalloc
;
940 CoGetMalloc( 1, &pMalloc
); // if fails there will be a memory leak
941 OSL_ENSURE( pMalloc
, "CoGetMalloc() failed!" );
943 LPOLESTR pOleStr
= NULL
;
944 hr
= pOleLink
->GetSourceDisplayName( &pOleStr
);
945 if ( SUCCEEDED( hr
) && pOleStr
)
947 ::rtl::OUString
aFilePath( ( sal_Unicode
* )pOleStr
);
949 pMalloc
->Free( ( void* )pOleStr
);
951 hr
= OleCreateFromFile( CLSID_NULL
,
952 reinterpret_cast<LPCWSTR
>(aFilePath
.getStr()),
954 OLERENDER_DRAW
, // OLERENDER_FORMAT
957 m_pNativeImpl
->m_pIStorage
,
958 (void**)&m_pNativeImpl
->m_pObj
);
962 // in case of other moniker types the only way is to get storage
963 if ( !m_pNativeImpl
->m_pObj
)
965 ComSmart
< IBindCtx
> pBindCtx
;
966 hr
= CreateBindCtx( 0, ( LPBC FAR
* )&pBindCtx
);
967 if ( SUCCEEDED( hr
) && pBindCtx
)
969 ComSmart
< IStorage
> pObjectStorage
;
970 hr
= pMoniker
->BindToStorage( pBindCtx
, NULL
, IID_IStorage
, (void**)&pObjectStorage
);
971 if ( SUCCEEDED( hr
) && pObjectStorage
)
973 hr
= pObjectStorage
->CopyTo( 0, NULL
, NULL
, m_pNativeImpl
->m_pIStorage
);
974 if ( SUCCEEDED( hr
) )
975 hr
= OleLoad( m_pNativeImpl
->m_pIStorage
, IID_IUnknown
, NULL
, (void**)&m_pNativeImpl
->m_pObj
);
981 // If object could not be created the only way is to use graphical representation
982 if ( FAILED( hr
) || !m_pNativeImpl
->m_pObj
)
983 throw uno::RuntimeException(); // TODO
985 if ( !InitializeObject_Impl() )
986 throw uno::RuntimeException(); // TODO
989 //----------------------------------------------
990 void OleComponent::RunObject()
992 OSL_ENSURE( m_pNativeImpl
->m_pOleObject
, "The pointer can not be set to NULL here!\n" );
993 if ( !m_pNativeImpl
->m_pOleObject
)
994 throw embed::WrongStateException(); // TODO: the object is in wrong state
996 if ( !OleIsRunning( m_pNativeImpl
->m_pOleObject
) )
1001 hr
= OleRun( m_pNativeImpl
->m_pObj
);
1011 if ( hr
== REGDB_E_CLASSNOTREG
)
1012 throw embed::UnreachableStateException(); // the object server is not installed
1014 throw io::IOException();
1019 //----------------------------------------------
1020 awt::Size
OleComponent::CalculateWithFactor( const awt::Size
& aSize
,
1021 const awt::Size
& aMultiplier
,
1022 const awt::Size
& aDivisor
)
1026 sal_Int64 nWidth
= (sal_Int64
)aSize
.Width
* (sal_Int64
)aMultiplier
.Width
/ (sal_Int64
)aDivisor
.Width
;
1027 sal_Int64 nHeight
= (sal_Int64
)aSize
.Height
* (sal_Int64
)aMultiplier
.Height
/ (sal_Int64
)aDivisor
.Height
;
1028 OSL_ENSURE( nWidth
< SAL_MAX_INT32
&& nWidth
> SAL_MIN_INT32
1029 && nHeight
< SAL_MAX_INT32
&& nHeight
> SAL_MIN_INT32
,
1030 "Unacceptable result size!" );
1032 aResult
.Width
= (sal_Int32
)nWidth
;
1033 aResult
.Height
= (sal_Int32
)nHeight
;
1038 //----------------------------------------------
1039 void OleComponent::CloseObject()
1041 if ( m_pNativeImpl
->m_pOleObject
&& OleIsRunning( m_pNativeImpl
->m_pOleObject
) )
1042 m_pNativeImpl
->m_pOleObject
->Close( OLECLOSE_NOSAVE
); // must be saved before
1045 //----------------------------------------------
1046 uno::Sequence
< embed::VerbDescriptor
> OleComponent::GetVerbList()
1048 if ( !m_pNativeImpl
->m_pOleObject
)
1049 throw embed::WrongStateException(); // TODO: the object is in wrong state
1051 if( !m_aVerbList
.getLength() )
1053 ComSmart
< IEnumOLEVERB
> pEnum
;
1054 if( SUCCEEDED( m_pNativeImpl
->m_pOleObject
->EnumVerbs( &pEnum
) ) )
1056 OLEVERB szEle
[ MAX_ENUM_ELE
];
1058 sal_Int32 nSeqSize
= 0;
1062 HRESULT hr
= pEnum
->Next( MAX_ENUM_ELE
, szEle
, &nNum
);
1063 if( hr
== S_OK
|| hr
== S_FALSE
)
1065 m_aVerbList
.realloc( nSeqSize
+= nNum
);
1066 for( sal_uInt32 nInd
= 0; nInd
< nNum
; nInd
++ )
1068 m_aVerbList
[nSeqSize
-nNum
+nInd
].VerbID
= szEle
[ nInd
].lVerb
;
1069 m_aVerbList
[nSeqSize
-nNum
+nInd
].VerbName
= WinAccToVcl_Impl( reinterpret_cast<const sal_Unicode
*>(szEle
[ nInd
].lpszVerbName
) );
1070 m_aVerbList
[nSeqSize
-nNum
+nInd
].VerbFlags
= szEle
[ nInd
].fuFlags
;
1071 m_aVerbList
[nSeqSize
-nNum
+nInd
].VerbAttributes
= szEle
[ nInd
].grfAttribs
;
1077 while( nNum
== MAX_ENUM_ELE
);
1084 //----------------------------------------------
1085 void OleComponent::ExecuteVerb( sal_Int32 nVerbID
)
1087 if ( !m_pNativeImpl
->m_pOleObject
)
1088 throw embed::WrongStateException(); // TODO
1090 HRESULT hr
= OleRun( m_pNativeImpl
->m_pOleObject
);
1092 throw io::IOException(); // TODO: a specific exception that transport error code can be thrown here
1094 // TODO: probably extents should be set here and stored in aRect
1095 // TODO: probably the parent window also should be set
1096 hr
= m_pNativeImpl
->m_pOleObject
->DoVerb( nVerbID
, NULL
, m_pOleWrapClientSite
, 0, NULL
, NULL
);
1099 throw io::IOException(); // TODO
1101 // TODO/LATER: the real names should be used here
1102 m_pNativeImpl
->m_pOleObject
->SetHostNames( L
"app name", L
"untitled" );
1105 //----------------------------------------------
1106 void OleComponent::SetHostName( const ::rtl::OUString
&,
1107 const ::rtl::OUString
& )
1109 if ( !m_pNativeImpl
->m_pOleObject
)
1110 throw embed::WrongStateException(); // TODO: the object is in wrong state
1112 // TODO: use aContName and aEmbDocName in m_pNativeImpl->m_pOleObject->SetHostNames()
1115 //----------------------------------------------
1116 void OleComponent::SetExtent( const awt::Size
& aVisAreaSize
, sal_Int64 nAspect
)
1118 if ( !m_pNativeImpl
->m_pOleObject
)
1119 throw embed::WrongStateException(); // TODO: the object is in wrong state
1121 DWORD nMSAspect
= ( DWORD
)nAspect
; // first 32 bits are for MS aspects
1123 SIZEL aSize
= { aVisAreaSize
.Width
, aVisAreaSize
.Height
};
1124 HRESULT hr
= m_pNativeImpl
->m_pOleObject
->SetExtent( nMSAspect
, &aSize
);
1128 // TODO/LATER: is it correct? In future user code probably should be ready for the exception.
1129 // if the object is running but not activated, RPC_E_SERVER_DIED error code is returned by OLE package
1130 // in this case just do nothing
1131 // Also Visio returns E_FAIL on resize if it is in running state
1132 // if ( hr != RPC_E_SERVER_DIED )
1133 throw io::IOException(); // TODO
1137 //----------------------------------------------
1138 awt::Size
OleComponent::GetExtent( sal_Int64 nAspect
)
1140 if ( !m_pNativeImpl
->m_pOleObject
)
1141 throw embed::WrongStateException(); // TODO: the object is in wrong state
1143 DWORD nMSAspect
= ( DWORD
)nAspect
; // first 32 bits are for MS aspects
1145 sal_Bool bGotSize
= sal_False
;
1147 if ( nMSAspect
== DVASPECT_CONTENT
)
1149 // Try to get the size from the replacement image first
1150 ComSmart
< IDataObject
> pDataObject
;
1151 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IDataObject
, (void**)&pDataObject
);
1152 if ( SUCCEEDED( hr
) || pDataObject
)
1155 FORMATETC aFormat
= pFormatTemplates
[1]; // use windows metafile format
1156 aFormat
.dwAspect
= nMSAspect
;
1158 hr
= pDataObject
->GetData( &aFormat
, &aMedium
);
1159 if ( SUCCEEDED( hr
) && aMedium
.tymed
== TYMED_MFPICT
) // Win Metafile
1161 METAFILEPICT
* pMF
= ( METAFILEPICT
* )GlobalLock( aMedium
.hMetaFilePict
);
1164 // the object uses 0.01 mm as unit, so the metafile size should be converted to object unit
1165 sal_Int64 nMult
= 1;
1189 case MM_ANISOTROPIC
:
1195 sal_Int64 nX
= ( (sal_Int64
)abs( pMF
->xExt
) ) * nMult
/ nDiv
;
1196 sal_Int64 nY
= ( (sal_Int64
)abs( pMF
->yExt
) ) * nMult
/ nDiv
;
1197 if ( nX
< SAL_MAX_INT32
&& nY
< SAL_MAX_INT32
)
1199 aSize
.Width
= ( sal_Int32
)nX
;
1200 aSize
.Height
= ( sal_Int32
)nY
;
1201 bGotSize
= sal_True
;
1204 OSL_FAIL( "Unexpected size is provided!" );
1211 throw lang::IllegalArgumentException();
1216 //----------------------------------------------
1217 awt::Size
OleComponent::GetCachedExtent( sal_Int64 nAspect
)
1219 if ( !m_pNativeImpl
->m_pOleObject
)
1220 throw embed::WrongStateException(); // TODO: the object is in wrong state
1222 DWORD nMSAspect
= ( DWORD
)nAspect
; // first 32 bits are for MS aspects
1225 HRESULT hr
= m_pNativeImpl
->m_pViewObject2
->GetExtent( nMSAspect
, -1, NULL
, &aSize
);
1229 // TODO/LATER: is it correct?
1230 // if there is no appropriate cache for the aspect, OLE_E_BLANK error code is returned
1231 // if ( hr == OLE_E_BLANK )
1232 // throw lang::IllegalArgumentException();
1234 // throw io::IOException(); // TODO
1236 throw lang::IllegalArgumentException();
1239 return awt::Size( aSize
.cx
, aSize
.cy
);
1242 //----------------------------------------------
1243 awt::Size
OleComponent::GetReccomendedExtent( sal_Int64 nAspect
)
1245 if ( !m_pNativeImpl
->m_pOleObject
)
1246 throw embed::WrongStateException(); // TODO: the object is in wrong state
1248 DWORD nMSAspect
= ( DWORD
)nAspect
; // first 32 bits are for MS aspects
1250 HRESULT hr
= m_pNativeImpl
->m_pOleObject
->GetExtent( nMSAspect
, &aSize
);
1252 throw lang::IllegalArgumentException();
1254 return awt::Size( aSize
.cx
, aSize
.cy
);
1257 //----------------------------------------------
1258 sal_Int64
OleComponent::GetMiscStatus( sal_Int64 nAspect
)
1260 if ( !m_pNativeImpl
->m_pOleObject
)
1261 throw embed::WrongStateException(); // TODO: the object is in wrong state
1264 m_pNativeImpl
->m_pOleObject
->GetMiscStatus( ( DWORD
)nAspect
, ( DWORD
* )&nResult
);
1265 return ( sal_Int64
)nResult
; // first 32 bits are for MS flags
1268 //----------------------------------------------
1269 uno::Sequence
< sal_Int8
> OleComponent::GetCLSID()
1271 if ( !m_pNativeImpl
->m_pOleObject
)
1272 throw embed::WrongStateException(); // TODO: the object is in wrong state
1275 HRESULT hr
= m_pNativeImpl
->m_pOleObject
->GetUserClassID( &aCLSID
);
1277 throw io::IOException(); // TODO:
1279 return MimeConfigurationHelper::GetSequenceClassID( aCLSID
.Data1
, aCLSID
.Data2
, aCLSID
.Data3
,
1280 aCLSID
.Data4
[0], aCLSID
.Data4
[1],
1281 aCLSID
.Data4
[2], aCLSID
.Data4
[3],
1282 aCLSID
.Data4
[4], aCLSID
.Data4
[5],
1283 aCLSID
.Data4
[6], aCLSID
.Data4
[7] );
1286 //----------------------------------------------
1287 sal_Bool
OleComponent::IsDirty()
1289 if ( !m_pNativeImpl
->m_pOleObject
)
1290 throw embed::WrongStateException(); // TODO: the object is in wrong state
1292 if ( IsWorkaroundActive() )
1295 ComSmart
< IPersistStorage
> pPersistStorage
;
1296 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IPersistStorage
, (void**)&pPersistStorage
);
1297 if ( FAILED( hr
) || !pPersistStorage
)
1298 throw io::IOException(); // TODO
1300 hr
= pPersistStorage
->IsDirty();
1301 return ( hr
!= S_FALSE
);
1304 //----------------------------------------------
1305 void OleComponent::StoreOwnTmpIfNecessary()
1307 if ( !m_pNativeImpl
->m_pOleObject
)
1308 throw embed::WrongStateException(); // TODO: the object is in wrong state
1310 ComSmart
< IPersistStorage
> pPersistStorage
;
1311 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IPersistStorage
, (void**)&pPersistStorage
);
1312 if ( FAILED( hr
) || !pPersistStorage
)
1313 throw io::IOException(); // TODO
1315 if ( m_bWorkaroundActive
|| pPersistStorage
->IsDirty() != S_FALSE
)
1317 hr
= OleSave( pPersistStorage
, m_pNativeImpl
->m_pIStorage
, TRUE
);
1320 // Till now was required only for AcrobatReader7.0.8
1322 hr
= m_pNativeImpl
->m_pOleObject
->GetUserClassID( &aCLSID
);
1324 throw io::IOException(); // TODO
1326 hr
= WriteClassStg( m_pNativeImpl
->m_pIStorage
, aCLSID
);
1328 throw io::IOException(); // TODO
1330 // the result of the following call is not checked because some objects, for example AcrobatReader7.0.8
1331 // return error even in case the saving was done correctly
1332 hr
= pPersistStorage
->Save( m_pNativeImpl
->m_pIStorage
, TRUE
);
1334 // another workaround for AcrobatReader7.0.8 object, this object might think that it is not changed
1335 // when it has been created from file, although it must be saved
1336 m_bWorkaroundActive
= sal_True
;
1339 hr
= m_pNativeImpl
->m_pIStorage
->Commit( STGC_DEFAULT
);
1341 throw io::IOException(); // TODO
1343 hr
= pPersistStorage
->SaveCompleted( NULL
);
1344 if ( FAILED( hr
) && hr
!= E_UNEXPECTED
)
1345 throw io::IOException(); // TODO
1350 //----------------------------------------------
1351 sal_Bool
OleComponent::SaveObject_Impl()
1353 sal_Bool bResult
= sal_False
;
1354 OleEmbeddedObject
* pLockObject
= NULL
;
1357 osl::MutexGuard
aGuard( m_aMutex
);
1358 if ( m_pUnoOleObject
)
1360 pLockObject
= m_pUnoOleObject
;
1361 pLockObject
->acquire();
1367 bResult
= pLockObject
->SaveObject_Impl();
1368 pLockObject
->release();
1374 //----------------------------------------------
1375 sal_Bool
OleComponent::OnShowWindow_Impl( bool bShow
)
1377 sal_Bool bResult
= sal_False
;
1378 OleEmbeddedObject
* pLockObject
= NULL
;
1381 osl::MutexGuard
aGuard( m_aMutex
);
1383 if ( m_pUnoOleObject
)
1385 pLockObject
= m_pUnoOleObject
;
1386 pLockObject
->acquire();
1392 bResult
= pLockObject
->OnShowWindow_Impl( bShow
);
1393 pLockObject
->release();
1399 //----------------------------------------------
1400 void OleComponent::OnViewChange_Impl( sal_uInt32 dwAspect
)
1402 // TODO: check if it is enough or may be saving notifications are required for Visio2000
1403 ::rtl::Reference
< OleEmbeddedObject
> xLockObject
;
1406 osl::MutexGuard
aGuard( m_aMutex
);
1407 if ( m_pUnoOleObject
)
1408 xLockObject
= m_pUnoOleObject
;
1411 if ( xLockObject
.is() )
1413 uno::Reference
< awt::XRequestCallback
> xRequestCallback(
1414 m_xFactory
->createInstance(
1415 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AsyncCallback") )),
1417 xRequestCallback
->addCallback( new MainThreadNotificationRequest( xLockObject
, OLECOMP_ONVIEWCHANGE
, dwAspect
), uno::Any() );
1421 //----------------------------------------------
1422 void OleComponent::OnClose_Impl()
1424 ::rtl::Reference
< OleEmbeddedObject
> xLockObject
;
1427 osl::MutexGuard
aGuard( m_aMutex
);
1428 if ( m_pUnoOleObject
)
1429 xLockObject
= m_pUnoOleObject
;
1432 if ( xLockObject
.is() )
1434 uno::Reference
< awt::XRequestCallback
> xRequestCallback(
1435 m_xFactory
->createInstance(
1436 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AsyncCallback") )),
1438 xRequestCallback
->addCallback( new MainThreadNotificationRequest( xLockObject
, OLECOMP_ONCLOSE
), uno::Any() );
1443 //----------------------------------------------
1444 void SAL_CALL
OleComponent::close( sal_Bool bDeliverOwnership
)
1445 throw ( util::CloseVetoException
,
1446 uno::RuntimeException
)
1448 ::osl::MutexGuard
aGuard( m_aMutex
);
1450 throw lang::DisposedException(); // TODO
1452 uno::Reference
< uno::XInterface
> xSelfHold( static_cast< ::cppu::OWeakObject
* >( this ) );
1453 lang::EventObject
aSource( static_cast< ::cppu::OWeakObject
* >( this ) );
1455 if ( m_pInterfaceContainer
)
1457 ::cppu::OInterfaceContainerHelper
* pContainer
=
1458 m_pInterfaceContainer
->getContainer( ::getCppuType( ( const uno::Reference
< util::XCloseListener
>* ) NULL
) );
1459 if ( pContainer
!= NULL
)
1461 ::cppu::OInterfaceIteratorHelper
pIterator( *pContainer
);
1462 while ( pIterator
.hasMoreElements() )
1466 ( (util::XCloseListener
* )pIterator
.next() )->queryClosing( aSource
, bDeliverOwnership
);
1468 catch( const uno::RuntimeException
& )
1475 pContainer
= m_pInterfaceContainer
->getContainer(
1476 ::getCppuType( ( const uno::Reference
< util::XCloseListener
>* ) NULL
) );
1477 if ( pContainer
!= NULL
)
1479 ::cppu::OInterfaceIteratorHelper
pCloseIterator( *pContainer
);
1480 while ( pCloseIterator
.hasMoreElements() )
1484 ( (util::XCloseListener
* )pCloseIterator
.next() )->notifyClosing( aSource
);
1486 catch( const uno::RuntimeException
& )
1488 pCloseIterator
.remove();
1497 //----------------------------------------------
1498 void SAL_CALL
OleComponent::addCloseListener( const uno::Reference
< util::XCloseListener
>& xListener
)
1499 throw ( uno::RuntimeException
)
1501 ::osl::MutexGuard
aGuard( m_aMutex
);
1503 throw lang::DisposedException(); // TODO
1505 if ( !m_pInterfaceContainer
)
1506 m_pInterfaceContainer
= new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex
);
1508 m_pInterfaceContainer
->addInterface( ::getCppuType( ( const uno::Reference
< util::XCloseListener
>* )0 ), xListener
);
1511 //----------------------------------------------
1512 void SAL_CALL
OleComponent::removeCloseListener( const uno::Reference
< util::XCloseListener
>& xListener
)
1513 throw ( uno::RuntimeException
)
1515 ::osl::MutexGuard
aGuard( m_aMutex
);
1517 throw lang::DisposedException(); // TODO
1519 if ( m_pInterfaceContainer
)
1520 m_pInterfaceContainer
->removeInterface( ::getCppuType( ( const uno::Reference
< util::XCloseListener
>* )0 ),
1525 //----------------------------------------------
1526 uno::Any SAL_CALL
OleComponent::getTransferData( const datatransfer::DataFlavor
& aFlavor
)
1527 throw ( datatransfer::UnsupportedFlavorException
,
1529 uno::RuntimeException
)
1531 ::osl::MutexGuard
aGuard( m_aMutex
);
1533 throw lang::DisposedException(); // TODO
1535 if ( !m_pNativeImpl
->m_pOleObject
)
1536 throw embed::WrongStateException(); // TODO: the object is in wrong state
1539 sal_Bool bSupportedFlavor
= sal_False
;
1541 if ( m_pNativeImpl
->GraphicalFlavor( aFlavor
) )
1543 DWORD nRequestedAspect
= GetAspectFromFlavor( aFlavor
);
1544 // if own icon is set and icon aspect is requested the own icon can be returned directly
1546 ComSmart
< IDataObject
> pDataObject
;
1547 HRESULT hr
= m_pNativeImpl
->m_pObj
->QueryInterface( IID_IDataObject
, (void**)&pDataObject
);
1548 if ( FAILED( hr
) || !pDataObject
)
1549 throw io::IOException(); // TODO: transport error code
1551 // The following optimization does not make much sence currently just because
1552 // only one aspect is supported, and only three formats for the aspect are supported
1553 // and moreover it is not guarantied that the once returned format will be supported further
1555 // TODO/LATER: bring the optimization back when other aspects are supported
1557 // FORMATETC* pFormatEtc = m_pNativeImpl->GetSupportedFormatForAspect( nRequestedAspect );
1558 // if ( pFormatEtc )
1560 // STGMEDIUM aMedium;
1561 // hr = pDataObject->GetData( pFormatEtc, &aMedium );
1562 // if ( SUCCEEDED( hr ) )
1563 // bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
1567 // the supported format of the application is still not found, find one
1568 for ( sal_Int32 nInd
= 0; nInd
< FORMATS_NUM
; nInd
++ )
1571 FORMATETC aFormat
= pFormatTemplates
[nInd
];
1572 aFormat
.dwAspect
= nRequestedAspect
;
1574 hr
= pDataObject
->GetData( &aFormat
, &aMedium
);
1575 if ( SUCCEEDED( hr
) )
1577 bSupportedFlavor
= m_pNativeImpl
->ConvertDataForFlavor( aMedium
, aFlavor
, aResult
);
1578 if ( bSupportedFlavor
)
1580 // TODO/LATER: bring the optimization back when other aspects are supported
1581 // m_pNativeImpl->AddSupportedFormat( aFormat );
1588 // If the replacement could not be retrieved, the cached representaion should be used
1589 // currently it is not necessary to retrieve it here, so it is implemented in the object itself
1591 // TODO: Investigate if there is already the format name
1592 // and whether this format is really required
1593 else if ( aFlavor
.DataType
== getCppuType( ( const uno::Reference
< io::XInputStream
>* ) 0 )
1594 && aFlavor
.MimeType
== "application/x-openoffice-contentstream" )
1596 // allow to retrieve stream-representation of the object persistence
1597 bSupportedFlavor
= sal_True
;
1598 uno::Reference
< io::XStream
> xTempFileStream(
1599 m_xFactory
->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) )),
1602 if ( !xTempFileStream
.is() )
1603 throw uno::RuntimeException(); // TODO
1605 uno::Reference
< io::XOutputStream
> xTempOutStream
= xTempFileStream
->getOutputStream();
1606 uno::Reference
< io::XInputStream
> xTempInStream
= xTempFileStream
->getInputStream();
1607 if ( xTempOutStream
.is() && xTempInStream
.is() )
1609 OSL_ENSURE( m_pUnoOleObject
, "Unexpected object absence!" );
1610 if ( !m_pUnoOleObject
)
1611 throw uno::RuntimeException();
1613 m_pUnoOleObject
->StoreObjectToStream( xTempOutStream
);
1615 xTempOutStream
->closeOutput();
1616 xTempOutStream
= uno::Reference
< io::XOutputStream
>();
1619 throw io::IOException(); // TODO:
1621 aResult
<<= xTempInStream
;
1624 if ( !bSupportedFlavor
)
1625 throw datatransfer::UnsupportedFlavorException();
1630 //----------------------------------------------
1631 uno::Sequence
< datatransfer::DataFlavor
> SAL_CALL
OleComponent::getTransferDataFlavors()
1632 throw ( uno::RuntimeException
)
1634 ::osl::MutexGuard
aGuard( m_aMutex
);
1636 throw lang::DisposedException(); // TODO
1638 if ( !m_pNativeImpl
->m_pOleObject
)
1639 throw embed::WrongStateException(); // TODO: the object is in wrong state
1641 RetrieveObjectDataFlavors_Impl();
1643 return m_aDataFlavors
;
1646 //----------------------------------------------
1647 sal_Bool SAL_CALL
OleComponent::isDataFlavorSupported( const datatransfer::DataFlavor
& aFlavor
)
1648 throw ( uno::RuntimeException
)
1650 ::osl::MutexGuard
aGuard( m_aMutex
);
1652 throw lang::DisposedException(); // TODO
1654 if ( !m_pNativeImpl
->m_pOleObject
)
1655 throw embed::WrongStateException(); // TODO: the object is in wrong state
1657 if ( !m_aDataFlavors
.getLength() )
1659 RetrieveObjectDataFlavors_Impl();
1662 for ( sal_Int32 nInd
= 0; nInd
< m_aDataFlavors
.getLength(); nInd
++ )
1663 if ( m_aDataFlavors
[nInd
].MimeType
.equals( aFlavor
.MimeType
) && m_aDataFlavors
[nInd
].DataType
== aFlavor
.DataType
)
1669 void SAL_CALL
OleComponent::dispose() throw (::com::sun::star::uno::RuntimeException
)
1675 catch ( const uno::Exception
& )
1680 void SAL_CALL
OleComponent::addEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
1681 throw ( uno::RuntimeException
)
1683 ::osl::MutexGuard
aGuard( m_aMutex
);
1685 throw lang::DisposedException(); // TODO
1687 if ( !m_pInterfaceContainer
)
1688 m_pInterfaceContainer
= new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex
);
1690 m_pInterfaceContainer
->addInterface( ::getCppuType( ( const uno::Reference
< lang::XEventListener
>* )0 ), xListener
);
1693 //----------------------------------------------
1694 void SAL_CALL
OleComponent::removeEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
1695 throw ( uno::RuntimeException
)
1697 ::osl::MutexGuard
aGuard( m_aMutex
);
1699 throw lang::DisposedException(); // TODO
1701 if ( m_pInterfaceContainer
)
1702 m_pInterfaceContainer
->removeInterface( ::getCppuType( ( const uno::Reference
< lang::XEventListener
>* )0 ),
1706 sal_Int64 SAL_CALL
OleComponent::getSomething( const ::com::sun::star::uno::Sequence
< sal_Int8
>& aIdentifier
) throw(::com::sun::star::uno::RuntimeException
)
1710 uno::Sequence
< sal_Int8
> aCLSID
= GetCLSID();
1711 if ( MimeConfigurationHelper::ClassIDsEqual( aIdentifier
, aCLSID
) )
1712 return (sal_Int64
) (IUnknown
*) m_pNativeImpl
->m_pObj
;
1714 // compatibility hack for old versions: CLSID was used in wrong order (SvGlobalName order)
1715 sal_Int32 nLength
= aIdentifier
.getLength();
1716 if ( nLength
== 16 )
1718 for ( sal_Int32 n
=8; n
<16; n
++ )
1719 if ( aIdentifier
[n
] != aCLSID
[n
] )
1721 if ( aIdentifier
[7] == aCLSID
[6] &&
1722 aIdentifier
[6] == aCLSID
[7] &&
1723 aIdentifier
[5] == aCLSID
[4] &&
1724 aIdentifier
[4] == aCLSID
[5] &&
1725 aIdentifier
[3] == aCLSID
[0] &&
1726 aIdentifier
[2] == aCLSID
[1] &&
1727 aIdentifier
[1] == aCLSID
[2] &&
1728 aIdentifier
[0] == aCLSID
[3] )
1729 return (sal_Int64
) (IUnknown
*) m_pNativeImpl
->m_pObj
;
1732 catch ( const uno::Exception
& )
1739 sal_Bool SAL_CALL
OleComponent::isModified() throw (::com::sun::star::uno::RuntimeException
)
1744 void SAL_CALL
OleComponent::setModified( sal_Bool bModified
)
1745 throw (::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::uno::RuntimeException
)
1747 m_bModified
= bModified
;
1749 if ( bModified
&& m_pInterfaceContainer
)
1751 ::cppu::OInterfaceContainerHelper
* pContainer
=
1752 m_pInterfaceContainer
->getContainer( ::getCppuType( ( const uno::Reference
< util::XModifyListener
>* ) NULL
) );
1753 if ( pContainer
!= NULL
)
1755 ::cppu::OInterfaceIteratorHelper
pIterator( *pContainer
);
1756 while ( pIterator
.hasMoreElements() )
1760 lang::EventObject
aEvent( (util::XModifiable
*) this );
1761 ((util::XModifyListener
*)pIterator
.next())->modified( aEvent
);
1763 catch( const uno::RuntimeException
& )
1772 void SAL_CALL
OleComponent::addModifyListener( const com::sun::star::uno::Reference
< com::sun::star::util::XModifyListener
>& xListener
) throw(::com::sun::star::uno::RuntimeException
)
1774 ::osl::MutexGuard
aGuard( m_aMutex
);
1776 throw lang::DisposedException(); // TODO
1778 if ( !m_pInterfaceContainer
)
1779 m_pInterfaceContainer
= new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex
);
1781 m_pInterfaceContainer
->addInterface( ::getCppuType( ( const uno::Reference
< util::XModifyListener
>* )0 ), xListener
);
1784 void SAL_CALL
OleComponent::removeModifyListener( const com::sun::star::uno::Reference
< com::sun::star::util::XModifyListener
>& xListener
) throw(::com::sun::star::uno::RuntimeException
)
1786 ::osl::MutexGuard
aGuard( m_aMutex
);
1788 throw lang::DisposedException(); // TODO
1790 if ( m_pInterfaceContainer
)
1791 m_pInterfaceContainer
->removeInterface( ::getCppuType( ( const uno::Reference
< util::XModifyListener
>* )0 ),
1795 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */