diff options
Diffstat (limited to 'embeddedobj/source/msole')
25 files changed, 9153 insertions, 0 deletions
diff --git a/embeddedobj/source/msole/advisesink.cxx b/embeddedobj/source/msole/advisesink.cxx new file mode 100644 index 000000000000..87025d2b0861 --- /dev/null +++ b/embeddedobj/source/msole/advisesink.cxx @@ -0,0 +1,134 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" + +#include <osl/diagnose.h> +#include <advisesink.hxx> +#include <olecomponent.hxx> + +#include <rtl/ref.hxx> + +OleWrapperAdviseSink::OleWrapperAdviseSink( OleComponent* pOleComp ) +: m_nRefCount( 0 ) +, m_pOleComp( pOleComp ) +{ + OSL_ENSURE( m_pOleComp, "No ole component is provided!\n" ); +} + +OleWrapperAdviseSink::~OleWrapperAdviseSink() +{ +} + +STDMETHODIMP OleWrapperAdviseSink::QueryInterface( REFIID riid , void** ppv ) +{ + *ppv=NULL; + + if ( riid == IID_IUnknown ) + *ppv = (IUnknown*)this; + + if ( riid == IID_IAdviseSink ) + *ppv = (IAdviseSink*)this; + + if ( *ppv != NULL ) + { + ((IUnknown*)*ppv)->AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) OleWrapperAdviseSink::AddRef() +{ + return osl_incrementInterlockedCount( &m_nRefCount); +} + +STDMETHODIMP_(ULONG) OleWrapperAdviseSink::Release() +{ + ULONG nReturn = --m_nRefCount; + if ( m_nRefCount == 0 ) + delete this; + + return nReturn; +} + +void OleWrapperAdviseSink::disconnectOleComponent() +{ + // must not be called from the descructor of OleComponent!!! + osl::MutexGuard aGuard( m_aMutex ); + m_pOleComp = NULL; +} + +STDMETHODIMP_(void) OleWrapperAdviseSink::OnDataChange(LPFORMATETC, LPSTGMEDIUM) +{ + // Unused for now ( no registration for IDataObject events ) +} + +STDMETHODIMP_(void) OleWrapperAdviseSink::OnViewChange(DWORD dwAspect, LONG) +{ + ::rtl::Reference< OleComponent > xLockComponent; + + { + osl::MutexGuard aGuard( m_aMutex ); + if ( m_pOleComp ) + xLockComponent = m_pOleComp; + } + + if ( xLockComponent.is() ) + xLockComponent->OnViewChange_Impl( dwAspect ); +} + +STDMETHODIMP_(void) OleWrapperAdviseSink::OnRename(LPMONIKER) +{ + // handled by default inprocess handler +} + +STDMETHODIMP_(void) OleWrapperAdviseSink::OnSave(void) +{ + // TODO: ??? + // The object knows about document saving already since it contolls it as ClienSite + // other interested listeners must be registered for the object +} + +STDMETHODIMP_(void) OleWrapperAdviseSink::OnClose(void) +{ + ::rtl::Reference< OleComponent > xLockComponent; + + { + osl::MutexGuard aGuard( m_aMutex ); + if ( m_pOleComp ) + xLockComponent = m_pOleComp; + } + + if ( xLockComponent.is() ) + xLockComponent->OnClose_Impl(); + + // TODO: sometimes it can be necessary to simulate OnShowWindow( False ) here +} + diff --git a/embeddedobj/source/msole/advisesink.hxx b/embeddedobj/source/msole/advisesink.hxx new file mode 100644 index 000000000000..4cdd5ac17910 --- /dev/null +++ b/embeddedobj/source/msole/advisesink.hxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <osl/interlck.h> +#include <osl/mutex.hxx> +#include <platform.h> + +class OleComponent; +class OleWrapperAdviseSink : public IAdviseSink +{ +protected: + osl::Mutex m_aMutex; + oslInterlockedCount m_nRefCount; + OleComponent* m_pOleComp; + +public: + OleWrapperAdviseSink( OleComponent* pOleComp ); + OleWrapperAdviseSink(void); + virtual ~OleWrapperAdviseSink(); + + void disconnectOleComponent(); + STDMETHODIMP QueryInterface(REFIID, void**); + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP_(ULONG) Release(void); + + STDMETHODIMP_(void) OnDataChange(LPFORMATETC, LPSTGMEDIUM); + STDMETHODIMP_(void) OnViewChange(DWORD, LONG); + STDMETHODIMP_(void) OnRename(LPMONIKER); + STDMETHODIMP_(void) OnSave(void); + STDMETHODIMP_(void) OnClose(void); +}; + diff --git a/embeddedobj/source/msole/closepreventer.cxx b/embeddedobj/source/msole/closepreventer.cxx new file mode 100644 index 000000000000..eb754434c050 --- /dev/null +++ b/embeddedobj/source/msole/closepreventer.cxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" + +#include "closepreventer.hxx" + +void SAL_CALL OClosePreventer::queryClosing( const ::com::sun::star::lang::EventObject&, sal_Bool ) + throw (::com::sun::star::util::CloseVetoException, ::com::sun::star::uno::RuntimeException) +{ + throw ::com::sun::star::util::CloseVetoException(); +} + +void SAL_CALL OClosePreventer::notifyClosing( const com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) +{ + // just a disaster + OSL_ENSURE( sal_False, "The object can not be prevented from closing!\n" ); +} + +void SAL_CALL OClosePreventer::disposing( const com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) +{ + // just a disaster + OSL_ENSURE( sal_False, "The object can not be prevented from closing!\n" ); +} + diff --git a/embeddedobj/source/msole/emboleobj.component b/embeddedobj/source/msole/emboleobj.component new file mode 100644 index 000000000000..96f8ed0d8d57 --- /dev/null +++ b/embeddedobj/source/msole/emboleobj.component @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.embed.OLEEmbeddedObjectFactory"> + <service name="com.sun.star.comp.embed.OLEEmbeddedObjectFactory"/> + <service name="com.sun.star.embed.OLEEmbeddedObjectFactory"/> + </implementation> +</component> diff --git a/embeddedobj/source/msole/emboleobj.windows.component b/embeddedobj/source/msole/emboleobj.windows.component new file mode 100644 index 000000000000..644a1d4f19a1 --- /dev/null +++ b/embeddedobj/source/msole/emboleobj.windows.component @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.embed.MSOLEObjectSystemCreator"> + <service name="com.sun.star.comp.embed.MSOLEObjectSystemCreator"/> + <service name="com.sun.star.embed.MSOLEObjectSystemCreator"/> + </implementation> + <implementation name="com.sun.star.comp.embed.OLEEmbeddedObjectFactory"> + <service name="com.sun.star.comp.embed.OLEEmbeddedObjectFactory"/> + <service name="com.sun.star.embed.OLEEmbeddedObjectFactory"/> + </implementation> +</component> diff --git a/embeddedobj/source/msole/exports.dxp b/embeddedobj/source/msole/exports.dxp new file mode 100644 index 000000000000..f0e1c69934bc --- /dev/null +++ b/embeddedobj/source/msole/exports.dxp @@ -0,0 +1,2 @@ +component_getImplementationEnvironment +component_getFactory diff --git a/embeddedobj/source/msole/graphconvert.cxx b/embeddedobj/source/msole/graphconvert.cxx new file mode 100644 index 000000000000..f538ea45d16e --- /dev/null +++ b/embeddedobj/source/msole/graphconvert.cxx @@ -0,0 +1,133 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <tools/link.hxx> +#include <vos/mutex.hxx> +#include <unotools/streamwrap.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/seqstream.hxx> +#include <tools/stream.hxx> + +#include "mtnotification.hxx" +#include "oleembobj.hxx" + + +using namespace ::com::sun::star; + + +sal_Bool ConvertBufferToFormat( void* pBuf, + sal_uInt32 nBufSize, + const ::rtl::OUString& aMimeType, + uno::Any& aResult ) +{ + // produces sequence with data in requested format and returns it in aResult + if ( pBuf ) + { + uno::Sequence < sal_Int8 > aData( (sal_Int8*)pBuf, nBufSize ); + uno::Reference < io::XInputStream > xIn = new comphelper::SequenceInputStream( aData ); + try + { + uno::Reference < graphic::XGraphicProvider > xGraphicProvider( comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.graphic.GraphicProvider") ), uno::UNO_QUERY ); + if( xGraphicProvider.is() ) + { + uno::Sequence< beans::PropertyValue > aMediaProperties( 1 ); + aMediaProperties[0].Name = ::rtl::OUString::createFromAscii( "InputStream" ); + aMediaProperties[0].Value <<= xIn; + uno::Reference< graphic::XGraphic > xGraphic( xGraphicProvider->queryGraphic( aMediaProperties ) ); + if( xGraphic.is() ) + { + SvMemoryStream aNewStream( 65535, 65535 ); +// uno::Reference < io::XOutputStream > xOut = new utl::OOutputStreamHelper( aNewStream.GetLockBytes() ); + uno::Reference < io::XStream > xOut = new utl::OStreamWrapper( aNewStream ); + uno::Sequence< beans::PropertyValue > aOutMediaProperties( 2 ); + aOutMediaProperties[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" ); + aOutMediaProperties[0].Value <<= xOut; + aOutMediaProperties[1].Name = ::rtl::OUString::createFromAscii( "MimeType" ); + aOutMediaProperties[1].Value <<= aMimeType; + + xGraphicProvider->storeGraphic( xGraphic, aOutMediaProperties ); + aResult <<= uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aNewStream.GetData() ), aNewStream.Seek( STREAM_SEEK_TO_END ) ); + return sal_True; + } + } + } + catch (uno::Exception&) + {} + } + + return sal_False; +} + +// ===================================================================== +// MainThreadNotificationRequest +// ===================================================================== +MainThreadNotificationRequest::MainThreadNotificationRequest( const ::rtl::Reference< OleEmbeddedObject >& xObj, sal_uInt16 nNotificationType, sal_uInt32 nAspect ) +: m_pObject( xObj.get() ) +, m_xObject( static_cast< embed::XEmbeddedObject* >( xObj.get() ) ) +, m_nNotificationType( nNotificationType ) +, m_nAspect( nAspect ) +{} + +void SAL_CALL MainThreadNotificationRequest::notify (const uno::Any& ) throw (uno::RuntimeException) +{ + if ( m_pObject ) + { + try + { + uno::Reference< uno::XInterface > xLock = m_xObject.get(); + if ( xLock.is() ) + { + // this is the main thread, the solar mutex must be locked + if ( m_nNotificationType == OLECOMP_ONCLOSE ) + m_pObject->OnClosed_Impl(); + else if ( m_nAspect == embed::Aspects::MSOLE_CONTENT ) + m_pObject->OnViewChanged_Impl(); + else if ( m_nAspect == embed::Aspects::MSOLE_ICON ) + m_pObject->OnIconChanged_Impl(); + } + } + catch( uno::Exception& ) + { + // ignore all the errors + } + } +} + +MainThreadNotificationRequest::~MainThreadNotificationRequest() +{ +} diff --git a/embeddedobj/source/msole/makefile.mk b/embeddedobj/source/msole/makefile.mk new file mode 100644 index 000000000000..f40e231bc2dd --- /dev/null +++ b/embeddedobj/source/msole/makefile.mk @@ -0,0 +1,143 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=embeddedobj +TARGET=emboleobj + + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# .IF "$(DISABLE_ATL)"=="" + +LIBTARGET=NO +USE_DEFFILE=YES + +# --- Files -------------------------------------------------------- + +SHL1TARGET= $(TARGET) + +SHL1IMPLIB= i$(TARGET) + +SLOFILES = \ + $(SLO)$/closepreventer.obj\ + $(SLO)$/oleregister.obj\ + $(SLO)$/xolefactory.obj\ + $(SLO)$/olepersist.obj\ + $(SLO)$/oleembed.obj\ + $(SLO)$/olevisual.obj\ + $(SLO)$/olemisc.obj\ + $(SLO)$/ownview.obj + +EXCEPTIONSFILES= \ + $(SLO)$/closepreventer.obj\ + $(SLO)$/oleregister.obj\ + $(SLO)$/xolefactory.obj\ + $(SLO)$/olepersist.obj\ + $(SLO)$/oleembed.obj\ + $(SLO)$/olevisual.obj\ + $(SLO)$/olemisc.obj\ + $(SLO)$/ownview.obj + +.IF "$(GUI)"=="WNT" + +SLOFILES += \ + $(SLO)$/graphconvert.obj\ + $(SLO)$/olecomponent.obj\ + $(SLO)$/olewrapclient.obj\ + $(SLO)$/xdialogcreator.obj\ + $(SLO)$/advisesink.obj + +EXCEPTIONSFILES += \ + $(SLO)$/graphconvert.obj\ + $(SLO)$/olecomponent.obj\ + $(SLO)$/olewrapclient.obj\ + $(SLO)$/xdialogcreator.obj\ + $(SLO)$/advisesink.obj + +.ENDIF + +SHL1OBJS= $(SLOFILES) + +SHL1STDLIBS=\ + $(UNOTOOLSLIB)\ + $(SALLIB)\ + $(VOSLIB)\ + $(CPPULIB)\ + $(CPPUHELPERLIB)\ + $(COMPHELPERLIB)\ + $(TOOLSLIB) + + +.IF "$(GUI)"=="WNT" +.IF "$(COM)"=="GCC" +EMBOBJLIB=-lembobj +.ELSE +EMBOBJLIB=iembobj.lib +.ENDIF + +SHL1STDLIBS+=\ + $(EMBOBJLIB)\ + $(OLE32LIB)\ + $(GDI32LIB)\ + $(UUIDLIB)\ + $(OLEAUT32LIB) + +DEF1EXPORTFILE= exports.dxp +.ELIF "$(GUI)"=="OS2" + +SHL1STDLIBS+=\ + iembobj.lib + +DEF1EXPORTFILE= exports.dxp + +.ENDIF + + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME= $(SHL1TARGET) + +# .ENDIF +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/emboleobj.component + +.IF "$(OS)" == "WNT" +my_platform = .windows +.END + +$(MISC)/emboleobj.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + emboleobj.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt emboleobj$(my_platform).component diff --git a/embeddedobj/source/msole/mtnotification.hxx b/embeddedobj/source/msole/mtnotification.hxx new file mode 100644 index 000000000000..2ceebe9f5098 --- /dev/null +++ b/embeddedobj/source/msole/mtnotification.hxx @@ -0,0 +1,55 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/awt/XCallback.hpp> +#include <cppuhelper/implbase1.hxx> + +#include <rtl/ref.hxx> + +class OleEmbeddedObject; + +#define OLECOMP_ONVIEWCHANGE 1 +#define OLECOMP_ONCLOSE 2 + +class MainThreadNotificationRequest : public cppu::WeakImplHelper1< com::sun::star::awt::XCallback > +{ + OleEmbeddedObject* m_pObject; + ::com::sun::star::uno::WeakReference< ::com::sun::star::embed::XEmbeddedObject > m_xObject; + + sal_uInt16 m_nNotificationType; + sal_uInt32 m_nAspect; + +public: + virtual void SAL_CALL notify (const com::sun::star::uno::Any& rUserData) + throw (com::sun::star::uno::RuntimeException); + MainThreadNotificationRequest( const ::rtl::Reference< OleEmbeddedObject >& xObj, sal_uInt16 nNotificationType, sal_uInt32 nAspect = 0 ); + ~MainThreadNotificationRequest(); +}; + + diff --git a/embeddedobj/source/msole/olecomponent.cxx b/embeddedobj/source/msole/olecomponent.cxx new file mode 100644 index 000000000000..c5c0368f7bf8 --- /dev/null +++ b/embeddedobj/source/msole/olecomponent.cxx @@ -0,0 +1,1801 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/embed/WrongStateException.hpp> +#include <com/sun/star/embed/UnreachableStateException.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/awt/XRequestCallback.hpp> + +#include <platform.h> +#include <cppuhelper/interfacecontainer.h> +#include <comphelper/mimeconfighelper.hxx> +#include <comphelper/storagehelper.hxx> +#include <osl/file.hxx> +#include <rtl/ref.hxx> + +#include <olecomponent.hxx> +#include <olewrapclient.hxx> +#include <advisesink.hxx> +#include <oleembobj.hxx> +#include <mtnotification.hxx> + +using namespace ::com::sun::star; +using namespace ::comphelper; +#define MAX_ENUM_ELE 20 +#define FORMATS_NUM 3 + +// ============ class ComSmart ===================== +namespace { + +template< class T > class ComSmart +{ + T* m_pInterface; + + void OwnRelease() + { + if ( m_pInterface ) + { + T* pInterface = m_pInterface; + m_pInterface = NULL; + pInterface->Release(); + } + } + +public: + ComSmart() + : m_pInterface( NULL ) + {} + + ComSmart( const ComSmart<T>& rObj ) + : m_pInterface( rObj.m_pInterface ) + { + if ( m_pInterface != NULL ) + m_pInterface->AddRef(); + } + + ComSmart( T* pInterface ) + : m_pInterface( pInterface ) + { + if ( m_pInterface != NULL ) + m_pInterface->AddRef(); + } + + ~ComSmart() + { + OwnRelease(); + } + + ComSmart& operator=( const ComSmart<T>& rObj ) + { + OwnRelease(); + + m_pInterface = rObj.m_pInterface; + + if ( m_pInterface != NULL ) + m_pInterface->AddRef(); + + return *this; + } + + ComSmart<T>& operator=( T* pInterface ) + { + OwnRelease(); + + m_pInterface = pInterface; + + if ( m_pInterface != NULL ) + m_pInterface->AddRef(); + + return *this; + } + + operator T*() const + { + return m_pInterface; + } + + T& operator*() const + { + return *m_pInterface; + } + + T** operator&() + { + OwnRelease(); + + m_pInterface = NULL; + + return &m_pInterface; + } + + T* operator->() const + { + return m_pInterface; + } + + BOOL operator==( const ComSmart<T>& rObj ) const + { + return ( m_pInterface == rObj.m_pInterface ); + } + + BOOL operator!=( const ComSmart<T>& rObj ) const + { + return ( m_pInterface != rObj.m_pInterface ); + } + + BOOL operator==( const T* pInterface ) const + { + return ( m_pInterface == pInterface ); + } + + BOOL operator!=( const T* pInterface ) const + { + return ( m_pInterface != pInterface ); + } +}; + +} + +// ============ class ComSmart ===================== + +sal_Bool ConvertBufferToFormat( void* pBuf, + sal_uInt32 nBufSize, + const ::rtl::OUString& aFormatShortName, + uno::Any& aResult ); + +::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException ); + +typedef ::std::vector< FORMATETC* > FormatEtcList; + +FORMATETC pFormatTemplates[FORMATS_NUM] = { + { CF_ENHMETAFILE, NULL, 0, -1, TYMED_ENHMF }, + { CF_METAFILEPICT, NULL, 0, -1, TYMED_MFPICT }, + { CF_BITMAP, NULL, 0, -1, TYMED_GDI } }; + + +struct OleComponentNative_Impl { + ComSmart< IUnknown > m_pObj; + ComSmart< IOleObject > m_pOleObject; + ComSmart< IViewObject2 > m_pViewObject2; + ComSmart< IStorage > m_pIStorage; + FormatEtcList m_aFormatsList; + uno::Sequence< datatransfer::DataFlavor > m_aSupportedGraphFormats; + + OleComponentNative_Impl() + { + // TODO: Extend format list + m_aSupportedGraphFormats.realloc( 5 ); + + m_aSupportedGraphFormats[0] = datatransfer::DataFlavor( + ::rtl::OUString::createFromAscii( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ), + ::rtl::OUString::createFromAscii( "Windows Enhanced Metafile" ), + getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); + + m_aSupportedGraphFormats[1] = datatransfer::DataFlavor( + ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), + ::rtl::OUString::createFromAscii( "Windows Metafile" ), + getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); + + m_aSupportedGraphFormats[2] = datatransfer::DataFlavor( + ::rtl::OUString::createFromAscii( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ), + ::rtl::OUString::createFromAscii( "Bitmap" ), + getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); + + m_aSupportedGraphFormats[3] = datatransfer::DataFlavor( + ::rtl::OUString::createFromAscii( "image/png" ), + ::rtl::OUString::createFromAscii( "PNG" ), + getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); + + m_aSupportedGraphFormats[0] = datatransfer::DataFlavor( + ::rtl::OUString::createFromAscii( "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" ), + ::rtl::OUString::createFromAscii( "GDIMetafile" ), + getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ); + } + + void AddSupportedFormat( const FORMATETC& aFormatEtc ); + + FORMATETC* GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect ); + + sal_Bool ConvertDataForFlavor( const STGMEDIUM& aMedium, + const datatransfer::DataFlavor& aFlavor, + uno::Any& aResult ); + + sal_Bool GraphicalFlavor( const datatransfer::DataFlavor& aFlavor ); + + uno::Sequence< datatransfer::DataFlavor > GetFlavorsForAspects( sal_uInt32 nSupportedAspects ); +}; + +//---------------------------------------------- +DWORD GetAspectFromFlavor( const datatransfer::DataFlavor& aFlavor ) +{ + if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=THUMBNAIL" ) ) != -1 ) + return DVASPECT_THUMBNAIL; + else if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=ICON" ) ) != -1 ) + return DVASPECT_ICON; + else if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=DOCPRINT" ) ) != -1 ) + return DVASPECT_DOCPRINT; + else + return DVASPECT_CONTENT; +} + +//---------------------------------------------- +::rtl::OUString GetFlavorSuffixFromAspect( DWORD nAsp ) +{ + ::rtl::OUString aResult; + + if ( nAsp == DVASPECT_THUMBNAIL ) + aResult = ::rtl::OUString::createFromAscii( ";Aspect=THUMBNAIL" ); + else if ( nAsp == DVASPECT_ICON ) + aResult = ::rtl::OUString::createFromAscii( ";Aspect=ICON" ); + else if ( nAsp == DVASPECT_DOCPRINT ) + aResult = ::rtl::OUString::createFromAscii( ";Aspect=DOCPRINT" ); + + // no suffix for DVASPECT_CONTENT + + return aResult; +} + +//---------------------------------------------- +HRESULT OpenIStorageFromURL_Impl( const ::rtl::OUString& aURL, IStorage** ppIStorage ) +{ + OSL_ENSURE( ppIStorage, "The pointer must not be empty!" ); + + ::rtl::OUString aFilePath; + if ( !ppIStorage || ::osl::FileBase::getSystemPathFromFileURL( aURL, aFilePath ) != ::osl::FileBase::E_None ) + throw uno::RuntimeException(); // TODO: something dangerous happend + + return StgOpenStorage( reinterpret_cast<LPCWSTR>(aFilePath.getStr()), + NULL, + STGM_READWRITE | STGM_TRANSACTED, // | STGM_DELETEONRELEASE, + NULL, + 0, + ppIStorage ); +} + +//---------------------------------------------- +sal_Bool OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM& aMedium, + const datatransfer::DataFlavor& aFlavor, + uno::Any& aResult ) +{ + sal_Bool bAnyIsReady = sal_False; + + // try to convert data from Medium format to specified Flavor format + if ( aFlavor.DataType == getCppuType( ( const uno::Sequence< sal_Int8 >* ) 0 ) ) + { + // first the GDI-metafile must be generated + + unsigned char* pBuf = NULL; + sal_uInt32 nBufSize = 0; + ::rtl::OUString aFormat; + + if ( aMedium.tymed == TYMED_MFPICT ) // Win Metafile + { + aFormat = ::rtl::OUString::createFromAscii("image/x-wmf"); + METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict ); + if ( pMF ) + { + nBufSize = GetMetaFileBitsEx( pMF->hMF, 0, NULL ) + 22; + pBuf = new unsigned char[nBufSize]; + + + // TODO/LATER: the unit size must be calculated correctly + *( (long* )pBuf ) = 0x9ac6cdd7L; + *( (short* )( pBuf+6 )) = ( SHORT ) 0; + *( (short* )( pBuf+8 )) = ( SHORT ) 0; + *( (short* )( pBuf+10 )) = ( SHORT ) pMF->xExt; + *( (short* )( pBuf+12 )) = ( SHORT ) pMF->yExt; + *( (short* )( pBuf+14 )) = ( USHORT ) 2540; + + + if ( nBufSize && nBufSize == GetMetaFileBitsEx( pMF->hMF, nBufSize - 22, pBuf + 22 ) ) + { + if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"", 57 ) ) + { + aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize ); + bAnyIsReady = sal_True; + } + } + + GlobalUnlock( aMedium.hMetaFilePict ); + } + } + else if ( aMedium.tymed == TYMED_ENHMF ) // Enh Metafile + { + aFormat = ::rtl::OUString::createFromAscii("image/x-emf"); + nBufSize = GetEnhMetaFileBits( aMedium.hEnhMetaFile, 0, NULL ); + pBuf = new unsigned char[nBufSize]; + if ( nBufSize && nBufSize == GetEnhMetaFileBits( aMedium.hEnhMetaFile, nBufSize, pBuf ) ) + { + if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"", 57 ) ) + { + aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize ); + bAnyIsReady = sal_True; + } + } + } + else if ( aMedium.tymed == TYMED_GDI ) // Bitmap + { + aFormat = ::rtl::OUString::createFromAscii("image/x-MS-bmp"); + nBufSize = GetBitmapBits( aMedium.hBitmap, 0, NULL ); + pBuf = new unsigned char[nBufSize]; + if ( nBufSize && nBufSize == sal::static_int_cast< ULONG >( GetBitmapBits( aMedium.hBitmap, nBufSize, pBuf ) ) ) + { + if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"", 54 ) ) + { + aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize ); + bAnyIsReady = sal_True; + } + } + } + + if ( pBuf && !bAnyIsReady ) + { + for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ ) + if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType ) + && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType + && aFlavor.DataType == getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) + { + bAnyIsReady = ConvertBufferToFormat( ( void* )pBuf, nBufSize, aFormat, aResult ); + break; + } + } + + delete[] pBuf; + } + + return bAnyIsReady; +} + +//---------------------------------------------- +sal_Bool OleComponentNative_Impl::GraphicalFlavor( const datatransfer::DataFlavor& aFlavor ) +{ + // Actually all the required graphical formats must be supported + for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ ) + if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType ) + && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType ) + return sal_True; + + return sal_False; +} + +//---------------------------------------------- +sal_Bool GetClassIDFromSequence_Impl( uno::Sequence< sal_Int8 > aSeq, CLSID& aResult ) +{ + if ( aSeq.getLength() == 16 ) + { + aResult.Data1 = ( ( ( ( ( ( sal_uInt8 )aSeq[0] << 8 ) + ( sal_uInt8 )aSeq[1] ) << 8 ) + ( sal_uInt8 )aSeq[2] ) << 8 ) + ( sal_uInt8 )aSeq[3]; + aResult.Data2 = ( ( sal_uInt8 )aSeq[4] << 8 ) + ( sal_uInt8 )aSeq[5]; + aResult.Data3 = ( ( sal_uInt8 )aSeq[6] << 8 ) + ( sal_uInt8 )aSeq[7]; + for( int nInd = 0; nInd < 8; nInd++ ) + aResult.Data4[nInd] = ( sal_uInt8 )aSeq[nInd+8]; + + return sal_True; + } + + return sal_False; +} + +//---------------------------------------------- +::rtl::OUString WinAccToVcl_Impl( const sal_Unicode* pStr ) +{ + ::rtl::OUString aResult; + + if( pStr ) + { + while ( *pStr ) + { + if ( *pStr == '&' ) + { + aResult += ::rtl::OUString::createFromAscii( "~" ); + while( *( ++pStr ) == '&' ); + } + else + { + aResult += ::rtl::OUString( pStr, 1 ); + pStr++; + } + } + } + + return aResult; +} + +//---------------------------------------------- +OleComponent::OleComponent( const uno::Reference< lang::XMultiServiceFactory >& xFactory, OleEmbeddedObject* pUnoOleObject ) +: m_pInterfaceContainer( NULL ) +, m_bDisposed( sal_False ) +, m_bModified( sal_False ) +, m_pNativeImpl( new OleComponentNative_Impl() ) +, m_xFactory( xFactory ) +, m_pOleWrapClientSite( NULL ) +, m_pImplAdviseSink( NULL ) +, m_pUnoOleObject( pUnoOleObject ) +, m_nOLEMiscFlags( 0 ) +, m_nAdvConn( 0 ) +, m_bOleInitialized( sal_False ) +, m_bWorkaroundActive( sal_False ) +{ + OSL_ENSURE( m_pUnoOleObject, "No owner object is provided!" ); + + HRESULT hr = OleInitialize( NULL ); + OSL_ENSURE( hr == S_OK || hr == S_FALSE, "The ole can not be successfuly initialized\n" ); + if ( hr == S_OK || hr == S_FALSE ) + m_bOleInitialized = sal_True; + + m_pOleWrapClientSite = new OleWrapperClientSite( ( OleComponent* )this ); + m_pOleWrapClientSite->AddRef(); + + m_pImplAdviseSink = new OleWrapperAdviseSink( ( OleComponent* )this ); + m_pImplAdviseSink->AddRef(); + +} + +//---------------------------------------------- +OleComponent::~OleComponent() +{ + OSL_ENSURE( !m_pOleWrapClientSite && !m_pImplAdviseSink && !m_pInterfaceContainer && !m_bOleInitialized, + "The object was not closed successfully! DISASTER is possible!" ); + + if ( m_pOleWrapClientSite || m_pImplAdviseSink || m_pInterfaceContainer || m_bOleInitialized ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_refCount++; + try { + Dispose(); + } catch( uno::Exception& ) {} + } + + for ( FormatEtcList::iterator aIter = m_pNativeImpl->m_aFormatsList.begin(); + aIter != m_pNativeImpl->m_aFormatsList.end(); + aIter++ ) + { + delete (*aIter); + (*aIter) = NULL; + } + m_pNativeImpl->m_aFormatsList.clear(); + + delete m_pNativeImpl; +} + +//---------------------------------------------- +void OleComponentNative_Impl::AddSupportedFormat( const FORMATETC& aFormatEtc ) +{ + FORMATETC* pFormatToInsert = new FORMATETC( aFormatEtc ); + m_aFormatsList.push_back( pFormatToInsert ); +} + +//---------------------------------------------- +FORMATETC* OleComponentNative_Impl::GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect ) +{ + for ( FormatEtcList::iterator aIter = m_aFormatsList.begin(); + aIter != m_aFormatsList.end(); + aIter++ ) + if ( (*aIter) && (*aIter)->dwAspect == nRequestedAspect ) + return (*aIter); + + return NULL; +} + +//---------------------------------------------- +void OleComponent::Dispose() +{ + // the mutex must be locked before this method is called + if ( m_bDisposed ) + return; + + CloseObject(); + + if ( m_pOleWrapClientSite ) + { + m_pOleWrapClientSite->disconnectOleComponent(); + m_pOleWrapClientSite->Release(); + m_pOleWrapClientSite = NULL; + } + + if ( m_pImplAdviseSink ) + { + m_pImplAdviseSink->disconnectOleComponent(); + m_pImplAdviseSink->Release(); + m_pImplAdviseSink = NULL; + } + + if ( m_pInterfaceContainer ) + { + lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >( this ) ); + m_pInterfaceContainer->disposeAndClear( aEvent ); + + delete m_pInterfaceContainer; + m_pInterfaceContainer = NULL; + } + + if ( m_bOleInitialized ) + { + // since the disposing can happen not only from main thread but also from a clipboard + // the deinitialization might lead to a disaster, SO7 does not deinitialize OLE at all + // so currently the same approach is selected as workaround + // OleUninitialize(); + m_bOleInitialized = sal_False; + } + + m_bDisposed = sal_True; +} + +//---------------------------------------------- +void OleComponent::disconnectEmbeddedObject() +{ + // must not be called from destructor of UNO OLE object!!! + osl::MutexGuard aGuard( m_aMutex ); + m_pUnoOleObject = NULL; +} + +//---------------------------------------------- +void OleComponent::CreateNewIStorage_Impl() +{ + // TODO: in future a global memory could be used instead of file. + + // write the stream to the temporary file + ::rtl::OUString aTempURL; + + OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" ); + if ( m_pUnoOleObject ) + aTempURL = m_pUnoOleObject->CreateTempURLEmpty_Impl(); + else + aTempURL = GetNewTempFileURL_Impl( m_xFactory ); + + if ( !aTempURL.getLength() ) + throw uno::RuntimeException(); // TODO + + // open an IStorage based on the temporary file + ::rtl::OUString aTempFilePath; + if ( ::osl::FileBase::getSystemPathFromFileURL( aTempURL, aTempFilePath ) != ::osl::FileBase::E_None ) + throw uno::RuntimeException(); // TODO: something dangerous happend + + HRESULT hr = StgCreateDocfile( reinterpret_cast<LPCWSTR>(aTempFilePath.getStr()), STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED | STGM_DELETEONRELEASE, 0, &m_pNativeImpl->m_pIStorage ); + if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage ) + throw io::IOException(); // TODO: transport error code? +} + +//---------------------------------------------- +uno::Sequence< datatransfer::DataFlavor > OleComponentNative_Impl::GetFlavorsForAspects( sal_uInt32 nSupportedAspects ) +{ + uno::Sequence< datatransfer::DataFlavor > aResult; + for ( sal_uInt32 nAsp = 1; nAsp <= 8; nAsp *= 2 ) + if ( ( nSupportedAspects & nAsp ) == nAsp ) + { + ::rtl::OUString aAspectSuffix = GetFlavorSuffixFromAspect( nAsp ); + + sal_Int32 nLength = aResult.getLength(); + aResult.realloc( nLength + m_aSupportedGraphFormats.getLength() ); + + for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ ) + { + aResult[nLength + nInd].MimeType = m_aSupportedGraphFormats[nInd].MimeType + aAspectSuffix; + aResult[nLength + nInd].HumanPresentableName = m_aSupportedGraphFormats[nInd].HumanPresentableName; + aResult[nLength + nInd].DataType = m_aSupportedGraphFormats[nInd].DataType; + } + } + + return aResult; +} + +//---------------------------------------------- +void OleComponent::RetrieveObjectDataFlavors_Impl() +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + if ( !m_aDataFlavors.getLength() ) + { + ComSmart< IDataObject > pDataObject; + HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject ); + if ( SUCCEEDED( hr ) && pDataObject ) + { + ComSmart< IEnumFORMATETC > pFormatEnum; + hr = pDataObject->EnumFormatEtc( DATADIR_GET, &pFormatEnum ); + if ( SUCCEEDED( hr ) && pFormatEnum ) + { + FORMATETC pElem[ MAX_ENUM_ELE ]; + ULONG nNum = 0; + + // if it is possible to retrieve at least one supported graphical format for an aspect + // this format can be converted to other supported formats + sal_uInt32 nSupportedAspects = 0; + do + { + HRESULT hr = pFormatEnum->Next( MAX_ENUM_ELE, pElem, &nNum ); + if( hr == S_OK || hr == S_FALSE ) + { + for( sal_uInt32 nInd = 0; nInd < FORMATS_NUM; nInd++ ) + { + if ( pElem[nInd].cfFormat == pFormatTemplates[nInd].cfFormat + && pElem[nInd].tymed == pFormatTemplates[nInd].tymed ) + nSupportedAspects |= pElem[nInd].dwAspect; + } + } + else + break; + } + while( nNum == MAX_ENUM_ELE ); + + m_aDataFlavors = m_pNativeImpl->GetFlavorsForAspects( nSupportedAspects ); + } + } + + if ( !m_aDataFlavors.getLength() ) + { + // TODO: + // for any reason the object could not provide this information + // try to get access to the cached representation + } + } +} + +//---------------------------------------------- +sal_Bool OleComponent::InitializeObject_Impl() +// There will be no static objects! +{ + if ( !m_pNativeImpl->m_pObj ) + return sal_False; + + // the linked object will be detected here + ComSmart< IOleLink > pOleLink; + HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink ); + OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" ); + if ( m_pUnoOleObject ) + m_pUnoOleObject->SetObjectIsLink_Impl( sal_Bool( pOleLink != NULL ) ); + + + hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IViewObject2, (void**)&m_pNativeImpl->m_pViewObject2 ); + if ( FAILED( hr ) || !m_pNativeImpl->m_pViewObject2 ) + return sal_False; + + // not realy needed for now, since object is updated on saving + // m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink ); + + // remove all the caches + IOleCache* pIOleCache = NULL; + if ( SUCCEEDED( m_pNativeImpl->m_pObj->QueryInterface( IID_IOleCache, (void**)&pIOleCache ) ) && pIOleCache ) + { + IEnumSTATDATA* pEnumSD = NULL; + HRESULT hr = pIOleCache->EnumCache( &pEnumSD ); + + if ( SUCCEEDED( hr ) && pEnumSD ) + { + pEnumSD->Reset(); + STATDATA aSD; + DWORD nNum; + while( SUCCEEDED( pEnumSD->Next( 1, &aSD, &nNum ) ) && nNum == 1 ) + hr = pIOleCache->Uncache( aSD.dwConnection ); + } + + // No IDataObject implementation, caching must be used instead + DWORD nConn; + FORMATETC aFormat = { 0, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT }; + hr = pIOleCache->Cache( &aFormat, ADVFCACHE_ONSAVE, &nConn ); + + pIOleCache->Release(); + pIOleCache = NULL; + } + + hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleObject, (void**)&m_pNativeImpl->m_pOleObject ); + if ( FAILED( hr ) || !m_pNativeImpl->m_pOleObject ) + return sal_False; // Static objects are not supported, they should be inserted as graphics + + m_pNativeImpl->m_pOleObject->GetMiscStatus( DVASPECT_CONTENT, ( DWORD* )&m_nOLEMiscFlags ); + // TODO: use other misc flags also + // the object should have drawable aspect even in case it supports only iconic representation + // if ( m_nOLEMiscFlags & OLEMISC_ONLYICONIC ) + + m_pNativeImpl->m_pOleObject->SetClientSite( m_pOleWrapClientSite ); + + // the only need in this registration is workaround for close notification + m_pNativeImpl->m_pOleObject->Advise( m_pImplAdviseSink, ( DWORD* )&m_nAdvConn ); + m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink ); + + OleSetContainedObject( m_pNativeImpl->m_pOleObject, TRUE ); + + return sal_True; +} + +//---------------------------------------------- +void OleComponent::LoadEmbeddedObject( const ::rtl::OUString& aTempURL ) +{ + if ( !aTempURL.getLength() ) + throw lang::IllegalArgumentException(); // TODO + + if ( m_pNativeImpl->m_pIStorage ) + throw io::IOException(); // TODO the object is already initialized or wrong initialization is done + + // open an IStorage based on the temporary file + HRESULT hr = OpenIStorageFromURL_Impl( aTempURL, &m_pNativeImpl->m_pIStorage ); + + if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage ) + throw io::IOException(); // TODO: transport error code? + + hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj ); + if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) + { + // STATSTG aStat; + // m_pNativeImpl->m_pIStorage->Stat( &aStat, STATFLAG_NONAME ); + throw uno::RuntimeException(); + } + + if ( !InitializeObject_Impl() ) + throw uno::RuntimeException(); // TODO +} + +//---------------------------------------------- +void OleComponent::CreateObjectFromClipboard() +{ + if ( m_pNativeImpl->m_pIStorage ) + throw io::IOException(); // TODO:the object is already initialized + + CreateNewIStorage_Impl(); + if ( !m_pNativeImpl->m_pIStorage ) + throw uno::RuntimeException(); // TODO + + IDataObject * pDO = NULL; + HRESULT hr = OleGetClipboard( &pDO ); + if( SUCCEEDED( hr ) && pDO ) + { + hr = OleQueryCreateFromData( pDO ); + if( S_OK == GetScode( hr ) ) + { + hr = OleCreateFromData( pDO, + IID_IUnknown, + OLERENDER_DRAW, // OLERENDER_FORMAT + NULL, // &aFormat, + NULL, + m_pNativeImpl->m_pIStorage, + (void**)&m_pNativeImpl->m_pObj ); + } + else + { + // Static objects are not supported + pDO->Release(); + } + } + + if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) + throw uno::RuntimeException(); + + if ( !InitializeObject_Impl() ) + throw uno::RuntimeException(); // TODO +} + +//---------------------------------------------- +void OleComponent::CreateNewEmbeddedObject( const uno::Sequence< sal_Int8 >& aSeqCLSID ) +{ + CLSID aClsID; + + if ( !GetClassIDFromSequence_Impl( aSeqCLSID, aClsID ) ) + throw lang::IllegalArgumentException(); // TODO + + if ( m_pNativeImpl->m_pIStorage ) + throw io::IOException(); // TODO:the object is already initialized + + CreateNewIStorage_Impl(); + if ( !m_pNativeImpl->m_pIStorage ) + throw uno::RuntimeException(); // TODO + + // FORMATETC aFormat = { CF_METAFILEPICT, NULL, nAspect, -1, TYMED_MFPICT }; // for OLE..._DRAW should be NULL + + HRESULT hr = OleCreate( aClsID, + IID_IUnknown, + OLERENDER_DRAW, // OLERENDER_FORMAT + NULL, // &aFormat, + NULL, + m_pNativeImpl->m_pIStorage, + (void**)&m_pNativeImpl->m_pObj ); + + if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) + throw uno::RuntimeException(); // TODO + + if ( !InitializeObject_Impl() ) + throw uno::RuntimeException(); // TODO + + // TODO: getExtent??? +} + +//---------------------------------------------- +void OleComponent::CreateObjectFromData( const uno::Reference< datatransfer::XTransferable >& ) +// Static objects are not supported, they should be inserted as graphics +{ + // TODO: May be this call is useless since there are no static objects + // and nonstatic objects will be created based on OLEstorage ( stream ). + // ??? + + // OleQueryCreateFromData... +} + +//---------------------------------------------- +void OleComponent::CreateObjectFromFile( const ::rtl::OUString& aFileURL ) +{ + if ( m_pNativeImpl->m_pIStorage ) + throw io::IOException(); // TODO:the object is already initialized + + CreateNewIStorage_Impl(); + if ( !m_pNativeImpl->m_pIStorage ) + throw uno::RuntimeException(); // TODO: + + ::rtl::OUString aFilePath; + if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None ) + throw uno::RuntimeException(); // TODO: something dangerous happend + + HRESULT hr = OleCreateFromFile( CLSID_NULL, + reinterpret_cast<LPCWSTR>(aFilePath.getStr()), + IID_IUnknown, + OLERENDER_DRAW, // OLERENDER_FORMAT + NULL, + NULL, + m_pNativeImpl->m_pIStorage, + (void**)&m_pNativeImpl->m_pObj ); + + if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) + throw uno::RuntimeException(); // TODO + + if ( !InitializeObject_Impl() ) + throw uno::RuntimeException(); // TODO +} + +//---------------------------------------------- +void OleComponent::CreateLinkFromFile( const ::rtl::OUString& aFileURL ) +{ + if ( m_pNativeImpl->m_pIStorage ) + throw io::IOException(); // TODO:the object is already initialized + + CreateNewIStorage_Impl(); + if ( !m_pNativeImpl->m_pIStorage ) + throw uno::RuntimeException(); // TODO: + + ::rtl::OUString aFilePath; + if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None ) + throw uno::RuntimeException(); // TODO: something dangerous happend + + HRESULT hr = OleCreateLinkToFile( reinterpret_cast<LPCWSTR>(aFilePath.getStr()), + IID_IUnknown, + OLERENDER_DRAW, // OLERENDER_FORMAT + NULL, + NULL, + m_pNativeImpl->m_pIStorage, + (void**)&m_pNativeImpl->m_pObj ); + + if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) + throw uno::RuntimeException(); // TODO + + if ( !InitializeObject_Impl() ) + throw uno::RuntimeException(); // TODO +} + +//---------------------------------------------- +void OleComponent::InitEmbeddedCopyOfLink( OleComponent* pOleLinkComponent ) +{ + if ( !pOleLinkComponent || !pOleLinkComponent->m_pNativeImpl->m_pObj ) + throw lang::IllegalArgumentException(); // TODO + + if ( m_pNativeImpl->m_pIStorage ) + throw io::IOException(); // TODO:the object is already initialized + + ComSmart< IDataObject > pDataObject; + HRESULT hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject ); + if ( SUCCEEDED( hr ) && pDataObject && SUCCEEDED( OleQueryCreateFromData( pDataObject ) ) ) + { + // the object must be already disconnected from the temporary URL + CreateNewIStorage_Impl(); + if ( !m_pNativeImpl->m_pIStorage ) + throw uno::RuntimeException(); // TODO: + + hr = OleCreateFromData( pDataObject, + IID_IUnknown, + OLERENDER_DRAW, + NULL, + NULL, + m_pNativeImpl->m_pIStorage, + (void**)&m_pNativeImpl->m_pObj ); + } + + if ( !m_pNativeImpl->m_pObj ) + { + ComSmart< IOleLink > pOleLink; + hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink ); + if ( FAILED( hr ) || !pOleLink ) + throw io::IOException(); // TODO: the object doesn't support IOleLink + + ComSmart< IMoniker > pMoniker; + hr = pOleLink->GetSourceMoniker( &pMoniker ); + if ( FAILED( hr ) || !pMoniker ) + throw io::IOException(); // TODO: can not retrieve moniker + + // In case of file moniker life is easy : ) + DWORD aMonType = 0; + hr = pMoniker->IsSystemMoniker( &aMonType ); + if ( SUCCEEDED( hr ) && aMonType == MKSYS_FILEMONIKER ) + { + ComSmart< IMalloc > pMalloc; + CoGetMalloc( 1, &pMalloc ); // if fails there will be a memory leak + OSL_ENSURE( pMalloc, "CoGetMalloc() failed!" ); + + LPOLESTR pOleStr = NULL; + hr = pOleLink->GetSourceDisplayName( &pOleStr ); + if ( SUCCEEDED( hr ) && pOleStr ) + { + ::rtl::OUString aFilePath( ( sal_Unicode* )pOleStr ); + if ( pMalloc ) + pMalloc->Free( ( void* )pOleStr ); + + hr = OleCreateFromFile( CLSID_NULL, + reinterpret_cast<LPCWSTR>(aFilePath.getStr()), + IID_IUnknown, + OLERENDER_DRAW, // OLERENDER_FORMAT + NULL, + NULL, + m_pNativeImpl->m_pIStorage, + (void**)&m_pNativeImpl->m_pObj ); + } + } + + // in case of other moniker types the only way is to get storage + if ( !m_pNativeImpl->m_pObj ) + { + ComSmart< IBindCtx > pBindCtx; + hr = CreateBindCtx( 0, ( LPBC FAR* )&pBindCtx ); + if ( SUCCEEDED( hr ) && pBindCtx ) + { + ComSmart< IStorage > pObjectStorage; + hr = pMoniker->BindToStorage( pBindCtx, NULL, IID_IStorage, (void**)&pObjectStorage ); + if ( SUCCEEDED( hr ) && pObjectStorage ) + { + hr = pObjectStorage->CopyTo( 0, NULL, NULL, m_pNativeImpl->m_pIStorage ); + if ( SUCCEEDED( hr ) ) + hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj ); + } + } + } + } + + // If object could not be created the only way is to use graphical representation + if ( FAILED( hr ) || !m_pNativeImpl->m_pObj ) + throw uno::RuntimeException(); // TODO + + if ( !InitializeObject_Impl() ) + throw uno::RuntimeException(); // TODO +} + +//---------------------------------------------- +void OleComponent::RunObject() +{ + OSL_ENSURE( m_pNativeImpl->m_pOleObject, "The pointer can not be set to NULL here!\n" ); + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + if ( !OleIsRunning( m_pNativeImpl->m_pOleObject ) ) + { + HRESULT hr = S_OK; + try + { + hr = OleRun( m_pNativeImpl->m_pObj ); + } + catch( ... ) + { + int i = 0; + i++; + } + + if ( FAILED( hr ) ) + { + if ( hr == REGDB_E_CLASSNOTREG ) + throw embed::UnreachableStateException(); // the object server is not installed + else + throw io::IOException(); + } + } +} + +//---------------------------------------------- +awt::Size OleComponent::CalculateWithFactor( const awt::Size& aSize, + const awt::Size& aMultiplier, + const awt::Size& aDivisor ) +{ + awt::Size aResult; + + sal_Int64 nWidth = (sal_Int64)aSize.Width * (sal_Int64)aMultiplier.Width / (sal_Int64)aDivisor.Width; + sal_Int64 nHeight = (sal_Int64)aSize.Height * (sal_Int64)aMultiplier.Height / (sal_Int64)aDivisor.Height; + OSL_ENSURE( nWidth < SAL_MAX_INT32 && nWidth > SAL_MIN_INT32 + && nHeight < SAL_MAX_INT32 && nHeight > SAL_MIN_INT32, + "Unacceptable result size!" ); + + aResult.Width = (sal_Int32)nWidth; + aResult.Height = (sal_Int32)nHeight; + + return aResult; +} + +//---------------------------------------------- +void OleComponent::CloseObject() +{ + if ( m_pNativeImpl->m_pOleObject && OleIsRunning( m_pNativeImpl->m_pOleObject ) ) + m_pNativeImpl->m_pOleObject->Close( OLECLOSE_NOSAVE ); // must be saved before +} + +//---------------------------------------------- +uno::Sequence< embed::VerbDescriptor > OleComponent::GetVerbList() +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + if( !m_aVerbList.getLength() ) + { + ComSmart< IEnumOLEVERB > pEnum; + if( SUCCEEDED( m_pNativeImpl->m_pOleObject->EnumVerbs( &pEnum ) ) ) + { + OLEVERB szEle[ MAX_ENUM_ELE ]; + ULONG nNum = 0; + sal_Int32 nSeqSize = 0; + + do + { + HRESULT hr = pEnum->Next( MAX_ENUM_ELE, szEle, &nNum ); + if( hr == S_OK || hr == S_FALSE ) + { + m_aVerbList.realloc( nSeqSize += nNum ); + for( sal_uInt32 nInd = 0; nInd < nNum; nInd++ ) + { + m_aVerbList[nSeqSize-nNum+nInd].VerbID = szEle[ nInd ].lVerb; + m_aVerbList[nSeqSize-nNum+nInd].VerbName = WinAccToVcl_Impl( reinterpret_cast<const sal_Unicode*>(szEle[ nInd ].lpszVerbName) ); + m_aVerbList[nSeqSize-nNum+nInd].VerbFlags = szEle[ nInd ].fuFlags; + m_aVerbList[nSeqSize-nNum+nInd].VerbAttributes = szEle[ nInd ].grfAttribs; + } + } + else + break; + } + while( nNum == MAX_ENUM_ELE ); + } + } + + return m_aVerbList; +} + +//---------------------------------------------- +void OleComponent::ExecuteVerb( sal_Int32 nVerbID ) +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO + + HRESULT hr = OleRun( m_pNativeImpl->m_pOleObject ); + if ( FAILED( hr ) ) + throw io::IOException(); // TODO: a specific exception that transport error code can be thrown here + + // TODO: probably extents should be set here and stored in aRect + // TODO: probably the parent window also should be set + hr = m_pNativeImpl->m_pOleObject->DoVerb( nVerbID, NULL, m_pOleWrapClientSite, 0, NULL, NULL ); + + if ( FAILED( hr ) ) + throw io::IOException(); // TODO + + // TODO/LATER: the real names should be used here + m_pNativeImpl->m_pOleObject->SetHostNames( L"app name", L"untitled" ); +} + +//---------------------------------------------- +void OleComponent::SetHostName( const ::rtl::OUString&, + const ::rtl::OUString& ) +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + // TODO: use aContName and aEmbDocName in m_pNativeImpl->m_pOleObject->SetHostNames() +} + +//---------------------------------------------- +void OleComponent::SetExtent( const awt::Size& aVisAreaSize, sal_Int64 nAspect ) +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects + + SIZEL aSize = { aVisAreaSize.Width, aVisAreaSize.Height }; + HRESULT hr = m_pNativeImpl->m_pOleObject->SetExtent( nMSAspect, &aSize ); + + if ( FAILED( hr ) ) + { + // TODO/LATER: is it correct? In future user code probably should be ready for the exception. + // if the object is running but not activated, RPC_E_SERVER_DIED error code is returned by OLE package + // in this case just do nothing + // Also Visio returns E_FAIL on resize if it is in running state + // if ( hr != RPC_E_SERVER_DIED ) + throw io::IOException(); // TODO + } +} + +//---------------------------------------------- +awt::Size OleComponent::GetExtent( sal_Int64 nAspect ) +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects + awt::Size aSize; + sal_Bool bGotSize = sal_False; + + if ( nMSAspect == DVASPECT_CONTENT ) + { + // Try to get the size from the replacement image first + ComSmart< IDataObject > pDataObject; + HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject ); + if ( SUCCEEDED( hr ) || pDataObject ) + { + STGMEDIUM aMedium; + FORMATETC aFormat = pFormatTemplates[1]; // use windows metafile format + aFormat.dwAspect = nMSAspect; + + hr = pDataObject->GetData( &aFormat, &aMedium ); + if ( SUCCEEDED( hr ) && aMedium.tymed == TYMED_MFPICT ) // Win Metafile + { + METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict ); + if ( pMF ) + { + // the object uses 0.01 mm as unit, so the metafile size should be converted to object unit + sal_Int64 nMult = 1; + sal_Int64 nDiv = 1; + switch( pMF->mm ) + { + case MM_HIENGLISH: + nMult = 254; + nDiv = 100; + break; + + case MM_LOENGLISH: + nMult = 254; + nDiv = 10; + break; + + case MM_LOMETRIC: + nMult = 10; + break; + + case MM_TWIPS: + nMult = 254; + nDiv = 144; + break; + + case MM_ISOTROPIC: + case MM_ANISOTROPIC: + case MM_HIMETRIC: + // do nothing + break; + } + + sal_Int64 nX = ( (sal_Int64)abs( pMF->xExt ) ) * nMult / nDiv; + sal_Int64 nY = ( (sal_Int64)abs( pMF->yExt ) ) * nMult / nDiv; + if ( nX < SAL_MAX_INT32 && nY < SAL_MAX_INT32 ) + { + aSize.Width = ( sal_Int32 )nX; + aSize.Height = ( sal_Int32 )nY; + bGotSize = sal_True; + } + else + OSL_ENSURE( sal_False, "Unexpected size is provided!" ); + } + } + } + } + + if ( !bGotSize ) + throw lang::IllegalArgumentException(); + + return aSize; +} + +//---------------------------------------------- +awt::Size OleComponent::GetCachedExtent( sal_Int64 nAspect ) +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects + SIZEL aSize; + + HRESULT hr = m_pNativeImpl->m_pViewObject2->GetExtent( nMSAspect, -1, NULL, &aSize ); + + if ( FAILED( hr ) ) + { + // TODO/LATER: is it correct? + // if there is no appropriate cache for the aspect, OLE_E_BLANK error code is returned + // if ( hr == OLE_E_BLANK ) + // throw lang::IllegalArgumentException(); + //else + // throw io::IOException(); // TODO + + throw lang::IllegalArgumentException(); + } + + return awt::Size( aSize.cx, aSize.cy ); +} + +//---------------------------------------------- +awt::Size OleComponent::GetReccomendedExtent( sal_Int64 nAspect ) +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects + SIZEL aSize; + HRESULT hr = m_pNativeImpl->m_pOleObject->GetExtent( nMSAspect, &aSize ); + if ( FAILED( hr ) ) + throw lang::IllegalArgumentException(); + + return awt::Size( aSize.cx, aSize.cy ); +} + +//---------------------------------------------- +sal_Int64 OleComponent::GetMiscStatus( sal_Int64 nAspect ) +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + sal_uInt32 nResult; + m_pNativeImpl->m_pOleObject->GetMiscStatus( ( DWORD )nAspect, ( DWORD* )&nResult ); + return ( sal_Int64 )nResult; // first 32 bits are for MS flags +} + +//---------------------------------------------- +uno::Sequence< sal_Int8 > OleComponent::GetCLSID() +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + GUID aCLSID; + HRESULT hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID ); + if ( FAILED( hr ) ) + throw io::IOException(); // TODO: + + return MimeConfigurationHelper::GetSequenceClassID( aCLSID.Data1, aCLSID.Data2, aCLSID.Data3, + aCLSID.Data4[0], aCLSID.Data4[1], + aCLSID.Data4[2], aCLSID.Data4[3], + aCLSID.Data4[4], aCLSID.Data4[5], + aCLSID.Data4[6], aCLSID.Data4[7] ); +} + +//---------------------------------------------- +sal_Bool OleComponent::IsDirty() +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + if ( IsWorkaroundActive() ) + return sal_True; + + ComSmart< IPersistStorage > pPersistStorage; + HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage ); + if ( FAILED( hr ) || !pPersistStorage ) + throw io::IOException(); // TODO + + hr = pPersistStorage->IsDirty(); + return ( hr != S_FALSE ); +} + +//---------------------------------------------- +void OleComponent::StoreOwnTmpIfNecessary() +{ + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + ComSmart< IPersistStorage > pPersistStorage; + HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage ); + if ( FAILED( hr ) || !pPersistStorage ) + throw io::IOException(); // TODO + + if ( m_bWorkaroundActive || pPersistStorage->IsDirty() != S_FALSE ) + { + hr = OleSave( pPersistStorage, m_pNativeImpl->m_pIStorage, TRUE ); + if ( FAILED( hr ) ) + { + // Till now was required only for AcrobatReader7.0.8 + GUID aCLSID; + hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID ); + if ( FAILED( hr ) ) + throw io::IOException(); // TODO + + hr = WriteClassStg( m_pNativeImpl->m_pIStorage, aCLSID ); + if ( FAILED( hr ) ) + throw io::IOException(); // TODO + + // the result of the following call is not checked because some objects, for example AcrobatReader7.0.8 + // return error even in case the saving was done correctly + hr = pPersistStorage->Save( m_pNativeImpl->m_pIStorage, TRUE ); + + // another workaround for AcrobatReader7.0.8 object, this object might think that it is not changed + // when it has been created from file, although it must be saved + m_bWorkaroundActive = sal_True; + } + + hr = m_pNativeImpl->m_pIStorage->Commit( STGC_DEFAULT ); + if ( FAILED( hr ) ) + throw io::IOException(); // TODO + + hr = pPersistStorage->SaveCompleted( NULL ); + if ( FAILED( hr ) && hr != E_UNEXPECTED ) + throw io::IOException(); // TODO + + // STATSTG aStat; + // m_pNativeImpl->m_pIStorage->Stat( &aStat, STATFLAG_NONAME ); + } +} + +//---------------------------------------------- +sal_Bool OleComponent::SaveObject_Impl() +{ + sal_Bool bResult = sal_False; + OleEmbeddedObject* pLockObject = NULL; + + { + osl::MutexGuard aGuard( m_aMutex ); + if ( m_pUnoOleObject ) + { + pLockObject = m_pUnoOleObject; + pLockObject->acquire(); + } + } + + if ( pLockObject ) + { + bResult = pLockObject->SaveObject_Impl(); + pLockObject->release(); + } + + return bResult; +} + +//---------------------------------------------- +sal_Bool OleComponent::OnShowWindow_Impl( bool bShow ) +{ + sal_Bool bResult = sal_False; + OleEmbeddedObject* pLockObject = NULL; + + { + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pUnoOleObject ) + { + pLockObject = m_pUnoOleObject; + pLockObject->acquire(); + } + } + + if ( pLockObject ) + { + bResult = pLockObject->OnShowWindow_Impl( bShow ); + pLockObject->release(); + } + + return bResult; +} + +//---------------------------------------------- +void OleComponent::OnViewChange_Impl( sal_uInt32 dwAspect ) +{ + // TODO: check if it is enough or may be saving notifications are required for Visio2000 + ::rtl::Reference< OleEmbeddedObject > xLockObject; + + { + osl::MutexGuard aGuard( m_aMutex ); + if ( m_pUnoOleObject ) + xLockObject = m_pUnoOleObject; + } + + if ( xLockObject.is() ) + { + uno::Reference < awt::XRequestCallback > xRequestCallback( + m_xFactory->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.awt.AsyncCallback") ), + uno::UNO_QUERY ); + xRequestCallback->addCallback( new MainThreadNotificationRequest( xLockObject, OLECOMP_ONVIEWCHANGE, dwAspect ), uno::Any() ); + } +} + +//---------------------------------------------- +void OleComponent::OnClose_Impl() +{ + ::rtl::Reference< OleEmbeddedObject > xLockObject; + + { + osl::MutexGuard aGuard( m_aMutex ); + if ( m_pUnoOleObject ) + xLockObject = m_pUnoOleObject; + } + + if ( xLockObject.is() ) + { + uno::Reference < awt::XRequestCallback > xRequestCallback( + m_xFactory->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.awt.AsyncCallback") ), + uno::UNO_QUERY ); + xRequestCallback->addCallback( new MainThreadNotificationRequest( xLockObject, OLECOMP_ONCLOSE ), uno::Any() ); + } +} + +// XCloseable +//---------------------------------------------- +void SAL_CALL OleComponent::close( sal_Bool bDeliverOwnership ) + throw ( util::CloseVetoException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) ); + lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) ); + + if ( m_pInterfaceContainer ) + { + ::cppu::OInterfaceContainerHelper* pContainer = + m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) ); + if ( pContainer != NULL ) + { + ::cppu::OInterfaceIteratorHelper pIterator( *pContainer ); + while ( pIterator.hasMoreElements() ) + { + try + { + ( (util::XCloseListener* )pIterator.next() )->queryClosing( aSource, bDeliverOwnership ); + } + catch( uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } + + pContainer = m_pInterfaceContainer->getContainer( + ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) ); + if ( pContainer != NULL ) + { + ::cppu::OInterfaceIteratorHelper pCloseIterator( *pContainer ); + while ( pCloseIterator.hasMoreElements() ) + { + try + { + ( (util::XCloseListener* )pCloseIterator.next() )->notifyClosing( aSource ); + } + catch( uno::RuntimeException& ) + { + pCloseIterator.remove(); + } + } + } + } + + Dispose(); +} + +//---------------------------------------------- +void SAL_CALL OleComponent::addCloseListener( const uno::Reference< util::XCloseListener >& xListener ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pInterfaceContainer ) + m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); + + m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ), xListener ); +} + +//---------------------------------------------- +void SAL_CALL OleComponent::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_pInterfaceContainer ) + m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ), + xListener ); +} + +// XTransferable +//---------------------------------------------- +uno::Any SAL_CALL OleComponent::getTransferData( const datatransfer::DataFlavor& aFlavor ) + throw ( datatransfer::UnsupportedFlavorException, + io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + uno::Any aResult; + sal_Bool bSupportedFlavor = sal_False; + + if ( m_pNativeImpl->GraphicalFlavor( aFlavor ) ) + { + DWORD nRequestedAspect = GetAspectFromFlavor( aFlavor ); + // if own icon is set and icon aspect is requested the own icon can be returned directly + + ComSmart< IDataObject > pDataObject; + HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject ); + if ( FAILED( hr ) || !pDataObject ) + throw io::IOException(); // TODO: transport error code + + // The following optimization does not make much sence currently just because + // only one aspect is supported, and only three formats for the aspect are supported + // and moreover it is not guarantied that the once returned format will be supported further + // example - i52106 + // TODO/LATER: bring the optimization back when other aspects are supported + + // FORMATETC* pFormatEtc = m_pNativeImpl->GetSupportedFormatForAspect( nRequestedAspect ); + // if ( pFormatEtc ) + // { + // STGMEDIUM aMedium; + // hr = pDataObject->GetData( pFormatEtc, &aMedium ); + // if ( SUCCEEDED( hr ) ) + // bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult ); + // } + // else + { + // the supported format of the application is still not found, find one + for ( sal_Int32 nInd = 0; nInd < FORMATS_NUM; nInd++ ) + { + STGMEDIUM aMedium; + FORMATETC aFormat = pFormatTemplates[nInd]; + aFormat.dwAspect = nRequestedAspect; + + hr = pDataObject->GetData( &aFormat, &aMedium ); + if ( SUCCEEDED( hr ) ) + { + bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult ); + if ( bSupportedFlavor ) + { + // TODO/LATER: bring the optimization back when other aspects are supported + // m_pNativeImpl->AddSupportedFormat( aFormat ); + break; + } + } + } + } + + // If the replacement could not be retrieved, the cached representaion should be used + // currently it is not necessary to retrieve it here, so it is implemented in the object itself + } + // TODO: Investigate if there is already the format name + // and whether this format is really required + else if ( aFlavor.DataType == getCppuType( ( const uno::Reference< io::XInputStream >* ) 0 ) + && aFlavor.MimeType.equalsAscii( "application/x-openoffice-contentstream" ) ) + { + // allow to retrieve stream-representation of the object persistence + bSupportedFlavor = sal_True; + uno::Reference < io::XStream > xTempFileStream( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY ); + + if ( !xTempFileStream.is() ) + throw uno::RuntimeException(); // TODO + + uno::Reference< io::XOutputStream > xTempOutStream = xTempFileStream->getOutputStream(); + uno::Reference< io::XInputStream > xTempInStream = xTempFileStream->getInputStream(); + if ( xTempOutStream.is() && xTempInStream.is() ) + { + OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" ); + if ( !m_pUnoOleObject ) + throw uno::RuntimeException(); + + m_pUnoOleObject->StoreObjectToStream( xTempOutStream ); + + xTempOutStream->closeOutput(); + xTempOutStream = uno::Reference< io::XOutputStream >(); + } + else + throw io::IOException(); // TODO: + + aResult <<= xTempInStream; + } + + if ( !bSupportedFlavor ) + throw datatransfer::UnsupportedFlavorException(); + + return aResult; +} + +//---------------------------------------------- +uno::Sequence< datatransfer::DataFlavor > SAL_CALL OleComponent::getTransferDataFlavors() + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + RetrieveObjectDataFlavors_Impl(); + + return m_aDataFlavors; +} + +//---------------------------------------------- +sal_Bool SAL_CALL OleComponent::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pNativeImpl->m_pOleObject ) + throw embed::WrongStateException(); // TODO: the object is in wrong state + + if ( !m_aDataFlavors.getLength() ) + { + RetrieveObjectDataFlavors_Impl(); + } + + for ( sal_Int32 nInd = 0; nInd < m_aDataFlavors.getLength(); nInd++ ) + if ( m_aDataFlavors[nInd].MimeType.equals( aFlavor.MimeType ) && m_aDataFlavors[nInd].DataType == aFlavor.DataType ) + return sal_True; + + return sal_False; +} + +void SAL_CALL OleComponent::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + try + { + close( sal_True ); + } + catch ( uno::Exception& ) + { + } +} + +void SAL_CALL OleComponent::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pInterfaceContainer ) + m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); + + m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ), xListener ); +} + +//---------------------------------------------- +void SAL_CALL OleComponent::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_pInterfaceContainer ) + m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ), + xListener ); +} + +sal_Int64 SAL_CALL OleComponent::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException) +{ + try + { + uno::Sequence < sal_Int8 > aCLSID = GetCLSID(); + if ( MimeConfigurationHelper::ClassIDsEqual( aIdentifier, aCLSID ) ) + return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj; + + // compatibility hack for old versions: CLSID was used in wrong order (SvGlobalName order) + sal_Int32 nLength = aIdentifier.getLength(); + if ( nLength == 16 ) + { + for ( sal_Int32 n=8; n<16; n++ ) + if ( aIdentifier[n] != aCLSID[n] ) + return 0; + if ( aIdentifier[7] == aCLSID[6] && + aIdentifier[6] == aCLSID[7] && + aIdentifier[5] == aCLSID[4] && + aIdentifier[4] == aCLSID[5] && + aIdentifier[3] == aCLSID[0] && + aIdentifier[2] == aCLSID[1] && + aIdentifier[1] == aCLSID[2] && + aIdentifier[0] == aCLSID[3] ) + return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj; + } + } + catch ( uno::Exception& ) + { + } + + return 0; +} + +sal_Bool SAL_CALL OleComponent::isModified() throw (::com::sun::star::uno::RuntimeException) +{ + return m_bModified; +} + +void SAL_CALL OleComponent::setModified( sal_Bool bModified ) + throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException) +{ + m_bModified = bModified; + + if ( bModified && m_pInterfaceContainer ) + { + ::cppu::OInterfaceContainerHelper* pContainer = + m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XModifyListener >* ) NULL ) ); + if ( pContainer != NULL ) + { + ::cppu::OInterfaceIteratorHelper pIterator( *pContainer ); + while ( pIterator.hasMoreElements() ) + { + try + { + lang::EventObject aEvent( (util::XModifiable*) this ); + ((util::XModifyListener*)pIterator.next())->modified( aEvent ); + } + catch( uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } + } +} + +void SAL_CALL OleComponent::addModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener ) throw(::com::sun::star::uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pInterfaceContainer ) + m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); + + m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ), xListener ); +} + +void SAL_CALL OleComponent::removeModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener) throw(::com::sun::star::uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_pInterfaceContainer ) + m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ), + xListener ); +} + diff --git a/embeddedobj/source/msole/olecomponent.hxx b/embeddedobj/source/msole/olecomponent.hxx new file mode 100644 index 000000000000..d2121313be5b --- /dev/null +++ b/embeddedobj/source/msole/olecomponent.hxx @@ -0,0 +1,194 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _INC_OLECOMPONENT_HXX_ +#define _INC_OLECOMPONENT_HXX_ + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/embed/XOptimizedStorage.hpp> +#include <com/sun/star/embed/VerbDescriptor.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <cppuhelper/implbase5.hxx> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/util/XModifyListener.hpp> + +#include <vector> + + +namespace com { namespace sun { namespace star { +}}} + +namespace cppu { + class OMultiTypeInterfaceContainerHelper; +} + +class OleWrapperClientSite; +class OleWrapperAdviseSink; +class OleEmbeddedObject; +struct OleComponentNative_Impl; + +class OleComponent : public ::cppu::WeakImplHelper5< ::com::sun::star::util::XCloseable, ::com::sun::star::lang::XComponent, + ::com::sun::star::lang::XUnoTunnel, ::com::sun::star::util::XModifiable, + ::com::sun::star::datatransfer::XTransferable > +{ + ::osl::Mutex m_aMutex; + ::cppu::OMultiTypeInterfaceContainerHelper* m_pInterfaceContainer; + + sal_Bool m_bDisposed; + sal_Bool m_bModified; + OleComponentNative_Impl* m_pNativeImpl; + + OleEmbeddedObject* m_pUnoOleObject; + OleWrapperClientSite* m_pOleWrapClientSite; + OleWrapperAdviseSink* m_pImplAdviseSink; + + sal_Int32 m_nOLEMiscFlags; + sal_Int32 m_nAdvConn; + + ::com::sun::star::uno::Sequence< ::com::sun::star::embed::VerbDescriptor > m_aVerbList; + ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > m_aDataFlavors; + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory; + + sal_Bool m_bOleInitialized; + + // specifies whether the workaround for some rare embedded objects is activated ( f.e. AcrobatReader 7.0.8 object ) + // such objects report the dirty state wrongly sometimes and do not allow to store them any time + sal_Bool m_bWorkaroundActive; + + + sal_Bool InitializeObject_Impl(); + + void CreateNewIStorage_Impl(); + + void RetrieveObjectDataFlavors_Impl(); + + void Dispose(); + + +public: + OleComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& m_xFactory, + OleEmbeddedObject* pOleObj ); + + virtual ~OleComponent(); + + OleComponent* createEmbeddedCopyOfLink(); + + void disconnectEmbeddedObject(); + + static ::com::sun::star::awt::Size CalculateWithFactor( const ::com::sun::star::awt::Size& aSize, + const ::com::sun::star::awt::Size& aMultiplier, + const ::com::sun::star::awt::Size& aDivisor ); + + ::com::sun::star::awt::Size CalculateTheRealSize( const ::com::sun::star::awt::Size& aContSize, sal_Bool bUpdate ); + + // ==== Initialization ================================================== + void LoadEmbeddedObject( const ::rtl::OUString& aTempURL ); + + void CreateObjectFromClipboard(); + + void CreateNewEmbeddedObject( const ::com::sun::star::uno::Sequence< sal_Int8 >& aSeqCLSID ); + + void CreateObjectFromData( + const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& xTransfer ); + + void CreateObjectFromFile( const ::rtl::OUString& aFileName ); + + void CreateLinkFromFile( const ::rtl::OUString& aFileName ); + + void InitEmbeddedCopyOfLink( OleComponent* pOleLinkComponent ); + + // ====================================================================== + + void RunObject(); // switch OLE object to running state + + void CloseObject(); // switch OLE object to loaded state + + ::com::sun::star::uno::Sequence< ::com::sun::star::embed::VerbDescriptor > GetVerbList(); + + void ExecuteVerb( sal_Int32 nVerbID ); + + void SetHostName( const ::rtl::OUString& aContName, const ::rtl::OUString& aEmbDocName ); + + void SetExtent( const ::com::sun::star::awt::Size& aVisAreaSize, sal_Int64 nAspect ); + + ::com::sun::star::awt::Size GetExtent( sal_Int64 nAspect ); + ::com::sun::star::awt::Size GetCachedExtent( sal_Int64 nAspect ); + ::com::sun::star::awt::Size GetReccomendedExtent( sal_Int64 nAspect ); + + sal_Int64 GetMiscStatus( sal_Int64 nAspect ); + + ::com::sun::star::uno::Sequence< sal_Int8 > GetCLSID(); + + sal_Bool IsWorkaroundActive() { return m_bWorkaroundActive; } + + sal_Bool IsDirty(); + + void StoreOwnTmpIfNecessary(); + + sal_Bool SaveObject_Impl(); + sal_Bool OnShowWindow_Impl( bool bShow ); + void OnViewChange_Impl( sal_uInt32 dwAspect ); + void OnClose_Impl(); + + // XCloseable + virtual void SAL_CALL close( sal_Bool DeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addCloseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeCloseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); + + // XTransferable + virtual ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw (::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw (::com::sun::star::uno::RuntimeException); + + // XComponent + virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addEventListener(const com::sun::star::uno::Reference < com::sun::star::lang::XEventListener >& aListener) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener(const com::sun::star::uno::Reference < com::sun::star::lang::XEventListener >& aListener) throw (::com::sun::star::uno::RuntimeException); + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException) ; + + // XModifiable + virtual sal_Bool SAL_CALL isModified() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setModified( sal_Bool bModified ) + throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener) throw(::com::sun::star::uno::RuntimeException); +}; + +#endif + diff --git a/embeddedobj/source/msole/oleembed.cxx b/embeddedobj/source/msole/oleembed.cxx new file mode 100644 index 000000000000..78ad2c2e5885 --- /dev/null +++ b/embeddedobj/source/msole/oleembed.cxx @@ -0,0 +1,1131 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" + +#include <oleembobj.hxx> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/EmbedVerbs.hpp> +#include <com/sun/star/embed/EntryInitModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/EmbedUpdateModes.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/embed/NeedsRunningStateException.hpp> +#include <com/sun/star/embed/StateChangeInProgressException.hpp> +#include <com/sun/star/embed/EmbedMisc.hpp> +#include <com/sun/star/embed/XEmbedObjectCreator.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XLoadable.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/system/SystemShellExecuteFlags.hpp> + +#include <rtl/logfile.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <comphelper/mimeconfighelper.hxx> +#include <comphelper/storagehelper.hxx> + + +#include <targetstatecontrol.hxx> + +#include <olecomponent.hxx> + +#include "ownview.hxx" + +using namespace ::com::sun::star; + +#ifdef WNT +//---------------------------------------------- +void OleEmbeddedObject::SwitchComponentToRunningState_Impl() +{ + if ( m_pOleComponent ) + { + try + { + m_pOleComponent->RunObject(); + } + catch( embed::UnreachableStateException& ) + { + GetRidOfComponent(); + throw; + } + catch( embed::WrongStateException& ) + { + GetRidOfComponent(); + throw; + } + } + else + { + throw embed::UnreachableStateException(); + } +} + +//---------------------------------------------- +uno::Sequence< sal_Int32 > OleEmbeddedObject::GetReachableStatesList_Impl( + const uno::Sequence< embed::VerbDescriptor >& aVerbList ) +{ + uno::Sequence< sal_Int32 > aStates(2); + aStates[0] = embed::EmbedStates::LOADED; + aStates[1] = embed::EmbedStates::RUNNING; + for ( sal_Int32 nInd = 0; nInd < aVerbList.getLength(); nInd++ ) + if ( aVerbList[nInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_OPEN ) + { + aStates.realloc(3); + aStates[2] = embed::EmbedStates::ACTIVE; + } + + return aStates; +} + +//---------------------------------------------- +uno::Sequence< sal_Int32 > OleEmbeddedObject::GetIntermediateVerbsSequence_Impl( sal_Int32 nNewState ) +{ + OSL_ENSURE( m_nObjectState != embed::EmbedStates::LOADED, "Loaded object is switched to running state without verbs using!" ); + + // actually there will be only one verb + if ( m_nObjectState == embed::EmbedStates::RUNNING && nNewState == embed::EmbedStates::ACTIVE ) + { + uno::Sequence< sal_Int32 > aVerbs( 1 ); + aVerbs[0] = embed::EmbedVerbs::MS_OLEVERB_OPEN; + } + + return uno::Sequence< sal_Int32 >(); +} +#endif +//---------------------------------------------- +void OleEmbeddedObject::MoveListeners() +{ + if ( m_pInterfaceContainer ) + { + // move state change listeners + { + ::cppu::OInterfaceContainerHelper* pStateChangeContainer = + m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< embed::XStateChangeListener >*) NULL ) ); + if ( pStateChangeContainer != NULL ) + { + uno::Reference< embed::XStateChangeBroadcaster > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + ::cppu::OInterfaceIteratorHelper pIterator( *pStateChangeContainer ); + while ( pIterator.hasMoreElements() ) + { + try + { + xWrappedObject->addStateChangeListener( (embed::XStateChangeListener*)pIterator.next() ); + } + catch( uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } + } + } + + // move event listeners + { + ::cppu::OInterfaceContainerHelper* pEventContainer = + m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< document::XEventListener >*) NULL ) ); + if ( pEventContainer != NULL ) + { + uno::Reference< document::XEventBroadcaster > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + ::cppu::OInterfaceIteratorHelper pIterator( *pEventContainer ); + while ( pIterator.hasMoreElements() ) + { + try + { + xWrappedObject->addEventListener( (document::XEventListener*)pIterator.next() ); + } + catch( uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } + } + } + + // move close listeners + { + ::cppu::OInterfaceContainerHelper* pCloseContainer = + m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >*) NULL ) ); + if ( pCloseContainer != NULL ) + { + uno::Reference< util::XCloseBroadcaster > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + ::cppu::OInterfaceIteratorHelper pIterator( *pCloseContainer ); + while ( pIterator.hasMoreElements() ) + { + try + { + xWrappedObject->addCloseListener( (util::XCloseListener*)pIterator.next() ); + } + catch( uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } + } + } + + delete m_pInterfaceContainer; + m_pInterfaceContainer = NULL; + } +} + +//---------------------------------------------- +uno::Reference< embed::XStorage > OleEmbeddedObject::CreateTemporarySubstorage( ::rtl::OUString& o_aStorageName ) +{ + uno::Reference< embed::XStorage > xResult; + + for ( sal_Int32 nInd = 0; nInd < 32000 && !xResult.is(); nInd++ ) + { + ::rtl::OUString aName = ::rtl::OUString::valueOf( nInd ); + aName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TMPSTOR" ) ); + aName += m_aEntryName; + if ( !m_xParentStorage->hasByName( aName ) ) + { + xResult = m_xParentStorage->openStorageElement( aName, embed::ElementModes::READWRITE ); + o_aStorageName = aName; + } + } + + if ( !xResult.is() ) + { + o_aStorageName = ::rtl::OUString(); + throw uno::RuntimeException(); + } + + return xResult; +} + +//---------------------------------------------- +::rtl::OUString OleEmbeddedObject::MoveToTemporarySubstream() +{ + ::rtl::OUString aResult; + for ( sal_Int32 nInd = 0; nInd < 32000 && !aResult.getLength(); nInd++ ) + { + ::rtl::OUString aName = ::rtl::OUString::valueOf( nInd ); + aName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TMPSTREAM" ) ); + aName += m_aEntryName; + if ( !m_xParentStorage->hasByName( aName ) ) + { + m_xParentStorage->renameElement( m_aEntryName, aName ); + aResult = aName; + } + } + + if ( !aResult.getLength() ) + throw uno::RuntimeException(); + + return aResult; +} + +//---------------------------------------------- +sal_Bool OleEmbeddedObject::TryToConvertToOOo() +{ + sal_Bool bResult = sal_False; + + ::rtl::OUString aStorageName; + ::rtl::OUString aTmpStreamName; + sal_Int32 nStep = 0; + + if ( m_pOleComponent || m_bReadOnly ) + return sal_False; + + try + { + changeState( embed::EmbedStates::LOADED ); + + // the stream must be seekable + uno::Reference< io::XSeekable > xSeekable( m_xObjectStream, uno::UNO_QUERY_THROW ); + xSeekable->seek( 0 ); + ::rtl::OUString aFilterName = OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xFactory, ::rtl::OUString(), m_xObjectStream->getInputStream() ); + + // use the solution only for OOXML format currently + if ( aFilterName.getLength() + && ( aFilterName.equals( ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM( "Calc MS Excel 2007 XML" ) ) ) + || aFilterName.equals( ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM( "Impress MS PowerPoint 2007 XML" ) ) ) + || aFilterName.equals( ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM( "MS Word 2007 XML" ) ) ) ) ) + { + uno::Reference< container::XNameAccess > xFilterFactory( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), + uno::UNO_QUERY_THROW ); + + ::rtl::OUString aDocServiceName; + uno::Any aFilterAnyData = xFilterFactory->getByName( aFilterName ); + uno::Sequence< beans::PropertyValue > aFilterData; + if ( aFilterAnyData >>= aFilterData ) + { + for ( sal_Int32 nInd = 0; nInd < aFilterData.getLength(); nInd++ ) + if ( aFilterData[nInd].Name.equalsAscii( "DocumentService" ) ) + aFilterData[nInd].Value >>= aDocServiceName; + } + + if ( aDocServiceName.getLength() ) + { + // create the model + uno::Sequence< uno::Any > aArguments(1); + aArguments[0] <<= beans::NamedValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EmbeddedObject" ) ), uno::makeAny( (sal_Bool)sal_True )); + + uno::Reference< util::XCloseable > xDocument( m_xFactory->createInstanceWithArguments( aDocServiceName, aArguments ), uno::UNO_QUERY_THROW ); + uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY_THROW ); + uno::Reference< document::XStorageBasedDocument > xStorDoc( xDocument, uno::UNO_QUERY_THROW ); + + // let the model behave as embedded one + uno::Reference< frame::XModel > xModel( xDocument, uno::UNO_QUERY_THROW ); + uno::Sequence< beans::PropertyValue > aSeq( 1 ); + aSeq[0].Name = ::rtl::OUString::createFromAscii( "SetEmbedded" ); + aSeq[0].Value <<= sal_True; + xModel->attachResource( ::rtl::OUString(), aSeq ); + + // load the model from the stream + uno::Sequence< beans::PropertyValue > aArgs( 5 ); + aArgs[0].Name = ::rtl::OUString::createFromAscii( "HierarchicalDocumentName" ); + aArgs[0].Value <<= m_aEntryName; + aArgs[1].Name = ::rtl::OUString::createFromAscii( "ReadOnly" ); + aArgs[1].Value <<= sal_True; + aArgs[2].Name = ::rtl::OUString::createFromAscii( "FilterName" ); + aArgs[2].Value <<= aFilterName; + aArgs[3].Name = ::rtl::OUString::createFromAscii( "URL" ); + aArgs[3].Value <<= ::rtl::OUString::createFromAscii( "private:stream" ); + aArgs[4].Name = ::rtl::OUString::createFromAscii( "InputStream" ); + aArgs[4].Value <<= m_xObjectStream->getInputStream(); + + xSeekable->seek( 0 ); + xLoadable->load( aArgs ); + + // the model is successfuly loaded, create a new storage and store the model to the storage + uno::Reference< embed::XStorage > xTmpStorage = CreateTemporarySubstorage( aStorageName ); + xStorDoc->storeToStorage( xTmpStorage, uno::Sequence< beans::PropertyValue >() ); + xDocument->close( sal_True ); + uno::Reference< beans::XPropertySet > xStorProps( xTmpStorage, uno::UNO_QUERY_THROW ); + ::rtl::OUString aMediaType; + xStorProps->getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) ) >>= aMediaType; + xTmpStorage->dispose(); + + // look for the related embedded object factory + ::comphelper::MimeConfigurationHelper aConfigHelper( m_xFactory ); + ::rtl::OUString aEmbedFactory; + if ( aMediaType.getLength() ) + aEmbedFactory = aConfigHelper.GetFactoryNameByMediaType( aMediaType ); + + if ( !aEmbedFactory.getLength() ) + throw uno::RuntimeException(); + + uno::Reference< uno::XInterface > xFact = m_xFactory->createInstance( aEmbedFactory ); + + uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY_THROW ); + + // now the object should be adjusted to become the wrapper + nStep = 1; + uno::Reference< lang::XComponent > xComp( m_xObjectStream, uno::UNO_QUERY_THROW ); + xComp->dispose(); + m_xObjectStream = uno::Reference< io::XStream >(); + m_nObjectState = -1; + + nStep = 2; + aTmpStreamName = MoveToTemporarySubstream(); + + nStep = 3; + m_xParentStorage->renameElement( aStorageName, m_aEntryName ); + + nStep = 4; + m_xWrappedObject.set( xEmbCreator->createInstanceInitFromEntry( m_xParentStorage, m_aEntryName, uno::Sequence< beans::PropertyValue >(), uno::Sequence< beans::PropertyValue >() ), uno::UNO_QUERY_THROW ); + + bResult = sal_True; // the change is no more revertable + try + { + m_xParentStorage->removeElement( aTmpStreamName ); + } + catch( uno::Exception& ) + { + // the success of the removing is not so important + } + } + } + } + catch( uno::Exception& ) + { + // repair the object if necessary + switch( nStep ) + { + case 4: + case 3: + if ( aTmpStreamName.getLength() && aTmpStreamName != m_aEntryName ) + try + { + if ( m_xParentStorage->hasByName( m_aEntryName ) ) + m_xParentStorage->removeElement( m_aEntryName ); + m_xParentStorage->renameElement( aTmpStreamName, m_aEntryName ); + } + catch ( uno::Exception& ) + { + try { + close( sal_True ); + } catch( uno::Exception& ) {} + + m_xParentStorage->dispose(); // ??? the storage has information loss, it should be closed without commiting! + throw uno::RuntimeException(); // the repairing is not possible + } + case 2: + try + { + m_xObjectStream = m_xParentStorage->openStreamElement( m_aEntryName, m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE ); + m_nObjectState = embed::EmbedStates::LOADED; + } + catch( uno::Exception& ) + { + try { + close( sal_True ); + } catch( uno::Exception& ) {} + + throw uno::RuntimeException(); // the repairing is not possible + } + // no break as designed! + + case 1: + case 0: + if ( aStorageName.getLength() ) + try { + m_xParentStorage->removeElement( aStorageName ); + } catch( uno::Exception& ) { OSL_ASSERT( "Can not remove temporary storage!" ); } + break; + } + } + + if ( bResult ) + { + // the conversion was done successfuly, now the additional initializations should happen + + MoveListeners(); + m_xWrappedObject->setClientSite( m_xClientSite ); + if ( m_xParent.is() ) + { + uno::Reference< container::XChild > xChild( m_xWrappedObject, uno::UNO_QUERY ); + if ( xChild.is() ) + xChild->setParent( m_xParent ); + } + + } + + return bResult; +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::changeState( sal_Int32 nNewState ) + throw ( embed::UnreachableStateException, + embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::changeState" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->changeState( nNewState ); + return; + } + // end wrapping related part ==================== + + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object has no persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + // in case the object is already in requested state + if ( m_nObjectState == nNewState ) + return; + +#ifdef WNT + if ( m_pOleComponent ) + { + if ( m_nTargetState != -1 ) + { + // means that the object is currently trying to reach the target state + throw embed::StateChangeInProgressException( ::rtl::OUString(), + uno::Reference< uno::XInterface >(), + m_nTargetState ); + } + + TargetStateControl_Impl aControl( m_nTargetState, nNewState ); + + // TODO: additional verbs can be a problem, since nobody knows how the object + // will behave after activation + + sal_Int32 nOldState = m_nObjectState; + aGuard.clear(); + StateChangeNotification_Impl( sal_True, nOldState, nNewState ); + aGuard.reset(); + + try + { + if ( nNewState == embed::EmbedStates::LOADED ) + { + // This means just closing of the current object + // If component can not be closed the object stays in loaded state + // and it holds reference to "incomplete" component + // If the object is switched to running state later + // the component will become "complete" + + // the loaded state must be set before, because of notifications! + m_nObjectState = nNewState; + + { + VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); + m_pOleComponent->CloseObject(); + } + + // GetRidOfComponent(); + aGuard.clear(); + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + aGuard.reset(); + } + else if ( nNewState == embed::EmbedStates::RUNNING || nNewState == embed::EmbedStates::ACTIVE ) + { + if ( m_nObjectState == embed::EmbedStates::LOADED ) + { + // if the target object is in loaded state and a different state is specified + // as a new one the object first must be switched to running state. + + // the component can exist already in nonrunning state + // it can be created during loading to detect type of object + CreateOleComponentAndLoad_Impl( m_pOleComponent ); + + SwitchComponentToRunningState_Impl(); + m_nObjectState = embed::EmbedStates::RUNNING; + aGuard.clear(); + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + aGuard.reset(); + + if ( m_pOleComponent && m_bHasSizeToSet ) + { + aGuard.clear(); + try { + m_pOleComponent->SetExtent( m_aSizeToSet, m_nAspectToSet ); + m_bHasSizeToSet = sal_False; + } + catch( uno::Exception& ) {} + aGuard.reset(); + } + + if ( m_nObjectState == nNewState ) + return; + } + + // so now the object is either switched from Active to Running state or vise versa + // the notification about object state change will be done asynchronously + if ( m_nObjectState == embed::EmbedStates::RUNNING && nNewState == embed::EmbedStates::ACTIVE ) + { + // execute OPEN verb, if object does not reach active state it is an object's problem + aGuard.clear(); + m_pOleComponent->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN ); + aGuard.reset(); + + // some objects do not allow to set the size even in running state + if ( m_pOleComponent && m_bHasSizeToSet ) + { + aGuard.clear(); + try { + m_pOleComponent->SetExtent( m_aSizeToSet, m_nAspectToSet ); + m_bHasSizeToSet = sal_False; + } + catch( uno::Exception& ) {} + aGuard.reset(); + } + + m_nObjectState = nNewState; + } + else if ( m_nObjectState == embed::EmbedStates::ACTIVE && nNewState == embed::EmbedStates::RUNNING ) + { + aGuard.clear(); + m_pOleComponent->CloseObject(); + m_pOleComponent->RunObject(); // Should not fail, the object already was active + aGuard.reset(); + m_nObjectState = nNewState; + } + else + { + throw embed::UnreachableStateException(); + } + } + else + throw embed::UnreachableStateException(); + } + catch( uno::Exception& ) + { + aGuard.clear(); + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + throw; + } + } + else +#endif + { + throw embed::UnreachableStateException(); + } +} + +//---------------------------------------------- +uno::Sequence< sal_Int32 > SAL_CALL OleEmbeddedObject::getReachableStates() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::getReachableStates" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getReachableStates(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object has no persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + +#ifdef WNT + if ( m_pOleComponent ) + { + if ( m_nObjectState == embed::EmbedStates::LOADED ) + { + // the list of supported verbs can be retrieved only when object is in running state + throw embed::NeedsRunningStateException(); // TODO: + } + + // the list of states can only be guessed based on standard verbs, + // since there is no way to detect what additional verbs do + return GetReachableStatesList_Impl( m_pOleComponent->GetVerbList() ); + } + else +#endif + { + return uno::Sequence< sal_Int32 >(); + } +} + +//---------------------------------------------- +sal_Int32 SAL_CALL OleEmbeddedObject::getCurrentState() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getCurrentState(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object has no persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + // TODO: Shouldn't we ask object? ( I guess no ) + return m_nObjectState; +} + +namespace +{ + bool lcl_CopyStream(uno::Reference<io::XInputStream> xIn, uno::Reference<io::XOutputStream> xOut) + { + const sal_Int32 nChunkSize = 4096; + uno::Sequence< sal_Int8 > aData(nChunkSize); + sal_Int32 nTotalRead = 0; + sal_Int32 nRead; + do + { + nRead = xIn->readBytes(aData, nChunkSize); + nTotalRead += nRead; + xOut->writeBytes(aData); + } while (nRead == nChunkSize); + return nTotalRead != 0; + } + + //Dump the objects content to a tempfile, just the "CONTENTS" stream if + //there is one for non-compound documents, otherwise the whole content. + // + //On success a file is returned which must be removed by the caller + rtl::OUString lcl_ExtractObject(::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory, + ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream > xObjectStream) + { + rtl::OUString sUrl; + + // the solution is only active for Unix systems +#ifndef WNT + uno::Reference <beans::XPropertySet> xNativeTempFile( + xFactory->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.TempFile"))), uno::UNO_QUERY_THROW); + uno::Reference < io::XStream > xStream(xNativeTempFile, uno::UNO_QUERY_THROW); + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xObjectStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + uno::Reference< container::XNameContainer > xNameContainer( + xFactory->createInstanceWithArguments( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.OLESimpleStorage")), + aArgs ), uno::UNO_QUERY_THROW ); + + uno::Reference< io::XStream > xCONTENTS; + xNameContainer->getByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CONTENTS"))) >>= xCONTENTS; + + sal_Bool bCopied = xCONTENTS.is() && lcl_CopyStream(xCONTENTS->getInputStream(), xStream->getOutputStream()); + + uno::Reference< io::XSeekable > xSeekableStor(xObjectStream, uno::UNO_QUERY); + if (xSeekableStor.is()) + xSeekableStor->seek(0); + + if (!bCopied) + bCopied = lcl_CopyStream(xObjectStream->getInputStream(), xStream->getOutputStream()); + + if (bCopied) + { + xNativeTempFile->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RemoveFile")), + uno::makeAny(sal_False)); + uno::Any aUrl = xNativeTempFile->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Uri"))); + aUrl >>= sUrl; + + xNativeTempFile = uno::Reference<beans::XPropertySet>(); + + uno::Reference<ucb::XSimpleFileAccess> xSimpleFileAccess( + xFactory->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SimpleFileAccess"))), + uno::UNO_QUERY_THROW); + + xSimpleFileAccess->setReadOnly(sUrl, sal_True); + } + else + { + xNativeTempFile->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RemoveFile")), + uno::makeAny(sal_True)); + } +#endif + return sUrl; + } +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::doVerb( sal_Int32 nVerbID ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + embed::UnreachableStateException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::doVerb" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->doVerb( nVerbID ); + return; + } + // end wrapping related part ==================== + + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object has no persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + +#ifdef WNT + if ( m_pOleComponent ) + { + sal_Int32 nOldState = m_nObjectState; + + // TODO/LATER detect target state here and do a notification + // StateChangeNotification_Impl( sal_True, nOldState, nNewState ); + if ( m_nObjectState == embed::EmbedStates::LOADED ) + { + // if the target object is in loaded state + // it must be switched to running state to execute verb + aGuard.clear(); + changeState( embed::EmbedStates::RUNNING ); + aGuard.reset(); + } + + try { + if ( !m_pOleComponent ) + throw uno::RuntimeException(); + + // ==== the STAMPIT related solution ============================= + m_aVerbExecutionController.StartControlExecution(); + // =============================================================== + + m_pOleComponent->ExecuteVerb( nVerbID ); + + // ==== the STAMPIT related solution ============================= + sal_Bool bModifiedOnExecution = m_aVerbExecutionController.EndControlExecution_WasModified(); + + // this workaround is implemented for STAMPIT object + // if object was modified during verb execution it is saved here + if ( bModifiedOnExecution && m_pOleComponent->IsDirty() ) + SaveObject_Impl(); + // =============================================================== + } + catch( uno::Exception& ) + { + // ==== the STAMPIT related solution ============================= + m_aVerbExecutionController.EndControlExecution_WasModified(); + // =============================================================== + + aGuard.clear(); + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + throw; + } + + // the following notification will be done asynchronously + // StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + } + else +#endif + { + if ( nVerbID == -9 ) + { + // the workaround verb to show the object in case no server is available + + // if it is possible, the object will be converted to OOo format + if ( !m_bTriedConversion ) + { + m_bTriedConversion = sal_True; + if ( TryToConvertToOOo() ) + { + changeState( embed::EmbedStates::UI_ACTIVE ); + return; + } + } + + if ( !m_pOwnView && m_xObjectStream.is() ) + { + try { + uno::Reference< io::XSeekable > xSeekable( m_xObjectStream, uno::UNO_QUERY ); + if ( xSeekable.is() ) + xSeekable->seek( 0 ); + + m_pOwnView = new OwnView_Impl( m_xFactory, m_xObjectStream->getInputStream() ); + m_pOwnView->acquire(); + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + } + } + + if ( !m_pOwnView || !m_pOwnView->Open() ) + { + //Make a RO copy and see if the OS can find something to at + //least display the content for us + if (!m_aTempDumpURL.getLength()) + m_aTempDumpURL = lcl_ExtractObject(m_xFactory, m_xObjectStream); + + if (m_aTempDumpURL.getLength()) + { + uno::Reference< ::com::sun::star::system::XSystemShellExecute > xSystemShellExecute( m_xFactory->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.system.SystemShellExecute"))), + uno::UNO_QUERY_THROW); + xSystemShellExecute->execute(m_aTempDumpURL, ::rtl::OUString(), ::com::sun::star::system::SystemShellExecuteFlags::DEFAULTS); + } + else + throw embed::UnreachableStateException(); + } + } + else + { + + throw embed::UnreachableStateException(); + } + } +} + +//---------------------------------------------- +uno::Sequence< embed::VerbDescriptor > SAL_CALL OleEmbeddedObject::getSupportedVerbs() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::getSupportedVerb" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getSupportedVerbs(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object has no persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); +#ifdef WNT + if ( m_pOleComponent ) + { + // registry could be used in this case + // if ( m_nObjectState == embed::EmbedStates::LOADED ) + // { + // // the list of supported verbs can be retrieved only when object is in running state + // throw embed::NeedsRunningStateException(); // TODO: + // } + + return m_pOleComponent->GetVerbList(); + } + else +#endif + { + return uno::Sequence< embed::VerbDescriptor >(); + } +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::setClientSite( + const uno::Reference< embed::XEmbeddedClient >& xClient ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setClientSite( xClient ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_xClientSite != xClient) + { + if ( m_nObjectState != embed::EmbedStates::LOADED && m_nObjectState != embed::EmbedStates::RUNNING ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The client site can not be set currently!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + m_xClientSite = xClient; + } +} + +//---------------------------------------------- +uno::Reference< embed::XEmbeddedClient > SAL_CALL OleEmbeddedObject::getClientSite() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getClientSite(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object has no persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + return m_xClientSite; +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::update() + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->update(); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object has no persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( m_nUpdateMode == embed::EmbedUpdateModes::EXPLICIT_UPDATE ) + { + // TODO: update view representation + } + else + { + // the object must be up to date + OSL_ENSURE( m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE, "Unknown update mode!\n" ); + } +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::setUpdateMode( sal_Int32 nMode ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setUpdateMode( nMode ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object has no persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + OSL_ENSURE( nMode == embed::EmbedUpdateModes::ALWAYS_UPDATE + || nMode == embed::EmbedUpdateModes::EXPLICIT_UPDATE, + "Unknown update mode!\n" ); + m_nUpdateMode = nMode; +} + +//---------------------------------------------- +sal_Int64 SAL_CALL OleEmbeddedObject::getStatus( sal_Int64 + nAspect +) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getStatus( nAspect ); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object must be in running state!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + sal_Int64 nResult = 0; + +#ifdef WNT + if ( m_bGotStatus && m_nStatusAspect == nAspect ) + nResult = m_nStatus; + else if ( m_pOleComponent ) + { + // OLE should allow to get status even in loaded state + // if ( m_nObjectState == embed::EmbedStates::LOADED ) + // changeState( m_nObjectState == embed::EmbedStates::RUNNING ); + + m_nStatus = m_pOleComponent->GetMiscStatus( nAspect ); + m_nStatusAspect = nAspect; + m_bGotStatus = sal_True; + nResult = m_nStatus; + } +#endif + + // this implementation needs size to be provided after object loading/creating to work in optimal way + return ( nResult | embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ); +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::setContainerName( const ::rtl::OUString& sName ) + throw ( uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setContainerName( sName ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + m_aContainerName = sName; +} + + diff --git a/embeddedobj/source/msole/olemisc.cxx b/embeddedobj/source/msole/olemisc.cxx new file mode 100644 index 000000000000..adf07e1f522e --- /dev/null +++ b/embeddedobj/source/msole/olemisc.cxx @@ -0,0 +1,704 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" +#include <com/sun/star/embed/EmbedUpdateModes.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/DisposedException.hpp> + +#include <cppuhelper/interfacecontainer.h> + +#include <oleembobj.hxx> +#include <olecomponent.hxx> + +#include "ownview.hxx" + +using namespace ::com::sun::star; + +sal_Bool KillFile_Impl( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory ); + + +//------------------------------------------------------ +OleEmbeddedObject::OleEmbeddedObject( const uno::Reference< lang::XMultiServiceFactory >& xFactory, + const uno::Sequence< sal_Int8 >& aClassID, + const ::rtl::OUString& aClassName ) +: m_pOleComponent( NULL ) +, m_pInterfaceContainer( NULL ) +, m_bReadOnly( sal_False ) +, m_bDisposed( sal_False ) +, m_nObjectState( -1 ) +, m_nTargetState( -1 ) +, m_nUpdateMode ( embed::EmbedUpdateModes::ALWAYS_UPDATE ) +, m_xFactory( xFactory ) +, m_aClassID( aClassID ) +, m_aClassName( aClassName ) +, m_bWaitSaveCompleted( sal_False ) +, m_bNewVisReplInStream( sal_True ) +, m_bStoreLoaded( sal_False ) +, m_bVisReplInitialized( sal_False ) +, m_bVisReplInStream( sal_False ) +, m_bStoreVisRepl( sal_False ) +, m_bIsLink( sal_False ) +, m_bHasCachedSize( sal_False ) +, m_nCachedAspect( 0 ) +, m_bHasSizeToSet( sal_False ) +, m_nAspectToSet( 0 ) +, m_bGotStatus( sal_False ) +, m_nStatus( 0 ) +, m_nStatusAspect( 0 ) +, m_pOwnView( NULL ) +, m_bFromClipboard( sal_False ) +, m_bTriedConversion( sal_False ) +{ +} + +//------------------------------------------------------ +// In case of loading from persistent entry the classID of the object +// will be retrieved from the entry, during construction it is unknown +OleEmbeddedObject::OleEmbeddedObject( const uno::Reference< lang::XMultiServiceFactory >& xFactory, sal_Bool bLink ) +: m_pOleComponent( NULL ) +, m_pInterfaceContainer( NULL ) +, m_bReadOnly( sal_False ) +, m_bDisposed( sal_False ) +, m_nObjectState( -1 ) +, m_nTargetState( -1 ) +, m_nUpdateMode( embed::EmbedUpdateModes::ALWAYS_UPDATE ) +, m_xFactory( xFactory ) +, m_bWaitSaveCompleted( sal_False ) +, m_bNewVisReplInStream( sal_True ) +, m_bStoreLoaded( sal_False ) +, m_bVisReplInitialized( sal_False ) +, m_bVisReplInStream( sal_False ) +, m_bStoreVisRepl( sal_False ) +, m_bIsLink( bLink ) +, m_bHasCachedSize( sal_False ) +, m_nCachedAspect( 0 ) +, m_bHasSizeToSet( sal_False ) +, m_nAspectToSet( 0 ) +, m_bGotStatus( sal_False ) +, m_nStatus( 0 ) +, m_nStatusAspect( 0 ) +, m_pOwnView( NULL ) +, m_bFromClipboard( sal_False ) +, m_bTriedConversion( sal_False ) +{ +} +#ifdef WNT +//------------------------------------------------------ +// this constructor let object be initialized from clipboard +OleEmbeddedObject::OleEmbeddedObject( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +: m_pOleComponent( NULL ) +, m_pInterfaceContainer( NULL ) +, m_bReadOnly( sal_False ) +, m_bDisposed( sal_False ) +, m_nObjectState( -1 ) +, m_nTargetState( -1 ) +, m_nUpdateMode( embed::EmbedUpdateModes::ALWAYS_UPDATE ) +, m_xFactory( xFactory ) +, m_bWaitSaveCompleted( sal_False ) +, m_bNewVisReplInStream( sal_True ) +, m_bStoreLoaded( sal_False ) +, m_bVisReplInitialized( sal_False ) +, m_bVisReplInStream( sal_False ) +, m_bStoreVisRepl( sal_False ) +, m_bIsLink( sal_False ) +, m_bHasCachedSize( sal_False ) +, m_nCachedAspect( 0 ) +, m_bHasSizeToSet( sal_False ) +, m_nAspectToSet( 0 ) +, m_bGotStatus( sal_False ) +, m_nStatus( 0 ) +, m_nStatusAspect( 0 ) +, m_pOwnView( NULL ) +, m_bFromClipboard( sal_True ) +, m_bTriedConversion( sal_False ) +{ +} +#endif +//------------------------------------------------------ +OleEmbeddedObject::~OleEmbeddedObject() +{ + OSL_ENSURE( !m_pInterfaceContainer && !m_pOleComponent && !m_xObjectStream.is(), + "The object is not closed! DISASTER is possible!" ); + + if ( m_pOleComponent || m_pInterfaceContainer || m_xObjectStream.is() ) + { + // the component must be cleaned during closing + m_refCount++; // to avoid crash + try { + Dispose(); + } catch( uno::Exception& ) {} + } + + if ( m_aTempURL.getLength() ) + KillFile_Impl( m_aTempURL, m_xFactory ); + + if ( m_aTempDumpURL.getLength() ) + KillFile_Impl( m_aTempDumpURL, m_xFactory ); +} + +//------------------------------------------------------ +void OleEmbeddedObject::MakeEventListenerNotification_Impl( const ::rtl::OUString& aEventName ) +{ + if ( m_pInterfaceContainer ) + { + ::cppu::OInterfaceContainerHelper* pContainer = + m_pInterfaceContainer->getContainer( + ::getCppuType( ( const uno::Reference< document::XEventListener >*) NULL ) ); + if ( pContainer != NULL ) + { + document::EventObject aEvent( static_cast< ::cppu::OWeakObject* >( this ), aEventName ); + ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); + while (pIterator.hasMoreElements()) + { + try + { + ((document::XEventListener*)pIterator.next())->notifyEvent( aEvent ); + } + catch( uno::RuntimeException& ) + { + } + } + } + } +} +#ifdef WNT +//---------------------------------------------- +void OleEmbeddedObject::StateChangeNotification_Impl( sal_Bool bBeforeChange, sal_Int32 nOldState, sal_Int32 nNewState ) +{ + if ( m_pInterfaceContainer ) + { + ::cppu::OInterfaceContainerHelper* pContainer = m_pInterfaceContainer->getContainer( + ::getCppuType( ( const uno::Reference< embed::XStateChangeListener >*) NULL ) ); + if ( pContainer != NULL ) + { + lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) ); + ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); + + while (pIterator.hasMoreElements()) + { + if ( bBeforeChange ) + { + try + { + ((embed::XStateChangeListener*)pIterator.next())->changingState( aSource, nOldState, nNewState ); + } + catch( uno::Exception& ) + { + // even if the listener complains ignore it for now + } + } + else + { + try + { + ((embed::XStateChangeListener*)pIterator.next())->stateChanged( aSource, nOldState, nNewState ); + } + catch( uno::Exception& ) + { + // if anything happened it is problem of listener, ignore it + } + } + } + } + } +} +#endif +//------------------------------------------------------ +void OleEmbeddedObject::GetRidOfComponent() +{ +#ifdef WNT + if ( m_pOleComponent ) + { + if ( m_nObjectState != -1 && m_nObjectState != embed::EmbedStates::LOADED ) + SaveObject_Impl(); + + m_pOleComponent->removeCloseListener( m_xClosePreventer ); + try + { + m_pOleComponent->close( sal_False ); + } + catch( uno::Exception& ) + { + // TODO: there should be a special listener to wait for component closing + // and to notify object, may be object itself can be such a listener + m_pOleComponent->addCloseListener( m_xClosePreventer ); + throw; + } + + m_pOleComponent->disconnectEmbeddedObject(); + m_pOleComponent->release(); + m_pOleComponent = NULL; + } +#endif +} + +//------------------------------------------------------ +void OleEmbeddedObject::Dispose() +{ + if ( m_pInterfaceContainer ) + { + lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) ); + m_pInterfaceContainer->disposeAndClear( aSource ); + delete m_pInterfaceContainer; + m_pInterfaceContainer = NULL; + } + + if ( m_pOwnView ) + { + m_pOwnView->Close(); + m_pOwnView->release(); + m_pOwnView = NULL; + } + + if ( m_pOleComponent ) + try { + GetRidOfComponent(); + } catch( uno::Exception& ) + { + m_bDisposed = true; + throw; // TODO: there should be a special listener that will close object when + // component is finally closed + } + + if ( m_xObjectStream.is() ) + { + uno::Reference< lang::XComponent > xComp( m_xObjectStream, uno::UNO_QUERY ); + OSL_ENSURE( xComp.is(), "Storage stream doesn't support XComponent!\n" ); + + if ( xComp.is() ) + { + try { + xComp->dispose(); + } catch( uno::Exception& ) {} + } + m_xObjectStream = uno::Reference< io::XStream >(); + } + + m_xParentStorage = uno::Reference< embed::XStorage >(); + + m_bDisposed = true; +} + +//------------------------------------------------------ +uno::Sequence< sal_Int8 > SAL_CALL OleEmbeddedObject::getClassID() + throw ( uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getClassID(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + return m_aClassID; +} + +//------------------------------------------------------ +::rtl::OUString SAL_CALL OleEmbeddedObject::getClassName() + throw ( uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getClassName(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + return m_aClassName; +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::setClassInfo( + const uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName ) + throw ( lang::NoSupportException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setClassInfo( aClassID, aClassName ); + return; + } + // end wrapping related part ==================== + + // the object class info can not be changed explicitly + throw lang::NoSupportException(); //TODO: +} + +//------------------------------------------------------ +uno::Reference< util::XCloseable > SAL_CALL OleEmbeddedObject::getComponent() + throw ( uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getComponent(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) // || m_nObjectState == embed::EmbedStates::LOADED ) + { + // the object is still not running + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + // if ( m_bWaitSaveCompleted ) + // throw embed::WrongStateException( + // ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + // uno::Reference< uno::XInterface >( reinterpret_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( !m_pOleComponent ) + { + // TODO/LATER: Is it correct??? + return uno::Reference< util::XCloseable >(); + // throw uno::RuntimeException(); // TODO + } + + return uno::Reference< util::XCloseable >( static_cast< ::cppu::OWeakObject* >( m_pOleComponent ), uno::UNO_QUERY ); +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::addStateChangeListener( const uno::Reference< embed::XStateChangeListener >& xListener ) + throw ( uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XStateChangeBroadcaster > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->addStateChangeListener( xListener ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pInterfaceContainer ) + m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); + + m_pInterfaceContainer->addInterface( ::getCppuType( (const uno::Reference< embed::XStateChangeListener >*)0 ), + xListener ); +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::removeStateChangeListener( + const uno::Reference< embed::XStateChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XStateChangeBroadcaster > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->removeStateChangeListener( xListener ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_pInterfaceContainer ) + m_pInterfaceContainer->removeInterface( ::getCppuType( (const uno::Reference< embed::XStateChangeListener >*)0 ), + xListener ); +} + + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::close( sal_Bool bDeliverOwnership ) + throw ( util::CloseVetoException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->close( bDeliverOwnership ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) ); + lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) ); + + if ( m_pInterfaceContainer ) + { + ::cppu::OInterfaceContainerHelper* pContainer = + m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >*) NULL ) ); + if ( pContainer != NULL ) + { + ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); + while (pIterator.hasMoreElements()) + { + try + { + ((util::XCloseListener*)pIterator.next())->queryClosing( aSource, bDeliverOwnership ); + } + catch( uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } + + pContainer = m_pInterfaceContainer->getContainer( + ::getCppuType( ( const uno::Reference< util::XCloseListener >*) NULL ) ); + if ( pContainer != NULL ) + { + ::cppu::OInterfaceIteratorHelper pCloseIterator(*pContainer); + while (pCloseIterator.hasMoreElements()) + { + try + { + ((util::XCloseListener*)pCloseIterator.next())->notifyClosing( aSource ); + } + catch( uno::RuntimeException& ) + { + pCloseIterator.remove(); + } + } + } + } + + Dispose(); +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::addCloseListener( const uno::Reference< util::XCloseListener >& xListener ) + throw ( uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->addCloseListener( xListener ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pInterfaceContainer ) + m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); + + m_pInterfaceContainer->addInterface( ::getCppuType( (const uno::Reference< util::XCloseListener >*)0 ), xListener ); +} + +//---------------------------------------------- +void SAL_CALL OleEmbeddedObject::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener ) + throw (uno::RuntimeException) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->removeCloseListener( xListener ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_pInterfaceContainer ) + m_pInterfaceContainer->removeInterface( ::getCppuType( (const uno::Reference< util::XCloseListener >*)0 ), + xListener ); +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::addEventListener( const uno::Reference< document::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->addEventListener( xListener ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !m_pInterfaceContainer ) + m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex ); + + m_pInterfaceContainer->addInterface( ::getCppuType( (const uno::Reference< document::XEventListener >*)0 ), xListener ); +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::removeEventListener( + const uno::Reference< document::XEventListener >& xListener ) + throw ( uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->removeEventListener( xListener ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_pInterfaceContainer ) + m_pInterfaceContainer->removeInterface( ::getCppuType( (const uno::Reference< document::XEventListener >*)0 ), + xListener ); +} + +// XInplaceObject ( wrapper related implementation ) +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::setObjectRectangles( const awt::Rectangle& aPosRect, + const awt::Rectangle& aClipRect ) + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XInplaceObject > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setObjectRectangles( aPosRect, aClipRect ); + return; + } + // end wrapping related part ==================== + + throw embed::WrongStateException(); +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::enableModeless( sal_Bool bEnable ) + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XInplaceObject > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->enableModeless( bEnable ); + return; + } + // end wrapping related part ==================== + + throw embed::WrongStateException(); +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::translateAccelerators( + const uno::Sequence< awt::KeyEvent >& aKeys ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XInplaceObject > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->translateAccelerators( aKeys ); + return; + } + // end wrapping related part ==================== + + // throw embed::WrongStateException(); +} + +// XChild +//------------------------------------------------------ +com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL OleEmbeddedObject::getParent() throw (::com::sun::star::uno::RuntimeException) +{ + // begin wrapping related part ==================== + uno::Reference< container::XChild > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getParent(); + } + // end wrapping related part ==================== + + return m_xParent; +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::setParent( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface >& xParent ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException) +{ + // begin wrapping related part ==================== + uno::Reference< container::XChild > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setParent( xParent ); + return; + } + // end wrapping related part ==================== + + m_xParent = xParent; +} + diff --git a/embeddedobj/source/msole/olepersist.cxx b/embeddedobj/source/msole/olepersist.cxx new file mode 100644 index 000000000000..c6862a04891a --- /dev/null +++ b/embeddedobj/source/msole/olepersist.cxx @@ -0,0 +1,2201 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" + +#include <oleembobj.hxx> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/EmbedVerbs.hpp> +#include <com/sun/star/embed/EntryInitModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/EmbedUpdateModes.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/embed/XOptimizedStorage.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> + +#include <rtl/logfile.hxx> + +#include <comphelper/storagehelper.hxx> +#include <comphelper/mimeconfighelper.hxx> +#include <comphelper/classids.hxx> + + +#include <olecomponent.hxx> +#include <closepreventer.hxx> + +using namespace ::com::sun::star; +using namespace ::comphelper; + +//------------------------------------------------------------------------- +sal_Bool KillFile_Impl( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +{ + if ( !xFactory.is() ) + return sal_False; + + sal_Bool bRet = sal_False; + + try + { + uno::Reference < ucb::XSimpleFileAccess > xAccess( + xFactory->createInstance ( + ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), + uno::UNO_QUERY ); + + if ( xAccess.is() ) + { + xAccess->kill( aURL ); + bRet = sal_True; + } + } + catch( uno::Exception& ) + { + } + + return bRet; +} + +//---------------------------------------------- +::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +{ + OSL_ENSURE( xFactory.is(), "No factory is provided!\n" ); + + ::rtl::OUString aResult; + + uno::Reference < beans::XPropertySet > xTempFile( + xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY ); + + if ( !xTempFile.is() ) + throw uno::RuntimeException(); // TODO + + try { + xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) ); + uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); + aUrl >>= aResult; + } + catch ( uno::Exception& ) + { + } + + if ( !aResult.getLength() ) + throw uno::RuntimeException(); // TODO: can not create tempfile + + return aResult; +} + +//----------------------------------------------- +::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw ( io::IOException, + uno::RuntimeException ) +{ + OSL_ENSURE( xInStream.is() && xFactory.is(), "Wrong parameters are provided!\n" ); + + ::rtl::OUString aResult = GetNewTempFileURL_Impl( xFactory ); + + if ( aResult.getLength() ) + { + try { + uno::Reference < ucb::XSimpleFileAccess > xTempAccess( + xFactory->createInstance ( + ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), + uno::UNO_QUERY ); + + if ( !xTempAccess.is() ) + throw uno::RuntimeException(); // TODO: + + uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aResult ); + if ( xTempOutStream.is() ) + { + // copy stream contents to the file + ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream ); + xTempOutStream->closeOutput(); + xTempOutStream = uno::Reference< io::XOutputStream >(); + } + else + throw io::IOException(); // TODO: + } + catch( packages::WrongPasswordException& ) + { + KillFile_Impl( aResult, xFactory ); + throw io::IOException(); //TODO: + } + catch( io::IOException& ) + { + KillFile_Impl( aResult, xFactory ); + throw; + } + catch( uno::RuntimeException& ) + { + KillFile_Impl( aResult, xFactory ); + throw; + } + catch( uno::Exception& ) + { + KillFile_Impl( aResult, xFactory ); + aResult = ::rtl::OUString(); + } + } + + return aResult; +} +#ifdef WNT +::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< embed::XOptimizedStorage >& xParentStorage, const ::rtl::OUString& aEntryName, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) + throw( io::IOException, uno::RuntimeException ) +{ + ::rtl::OUString aResult; + + try + { + uno::Reference < beans::XPropertySet > xTempFile( + xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY ); + uno::Reference < io::XStream > xTempStream( xTempFile, uno::UNO_QUERY_THROW ); + + xParentStorage->copyStreamElementData( aEntryName, xTempStream ); + + xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) ); + uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); + aUrl >>= aResult; + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + } + + if ( !aResult.getLength() ) + throw io::IOException(); + + return aResult; +} + +//------------------------------------------------------ +void SetStreamMediaType_Impl( const uno::Reference< io::XStream >& xStream, const ::rtl::OUString& aMediaType ) +{ + uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY ); + if ( !xPropSet.is() ) + throw uno::RuntimeException(); // TODO: all the storage streams must support XPropertySet + + xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ), uno::makeAny( aMediaType ) ); +} +#endif +//------------------------------------------------------ +void LetCommonStoragePassBeUsed_Impl( const uno::Reference< io::XStream >& xStream ) +{ + uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY ); + if ( !xPropSet.is() ) + throw uno::RuntimeException(); // Only StorageStreams must be provided here, they must implement the interface + + xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ), + uno::makeAny( (sal_Bool)sal_True ) ); +} +#ifdef WNT +//------------------------------------------------------ +void VerbExecutionController::StartControlExecution() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + + // the class is used to detect STAMPIT object, that can never be active + if ( !m_bVerbExecutionInProgress && !m_bWasEverActive ) + { + m_bVerbExecutionInProgress = sal_True; + m_nVerbExecutionThreadIdentifier = osl_getThreadIdentifier( NULL ); + m_bChangedOnVerbExecution = sal_False; + } +} + +//------------------------------------------------------ +sal_Bool VerbExecutionController::EndControlExecution_WasModified() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + + sal_Bool bResult = sal_False; + if ( m_bVerbExecutionInProgress && m_nVerbExecutionThreadIdentifier == osl_getThreadIdentifier( NULL ) ) + { + bResult = m_bChangedOnVerbExecution; + m_bVerbExecutionInProgress = sal_False; + } + + return bResult; +} + +//------------------------------------------------------ +void VerbExecutionController::ModificationNotificationIsDone() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + + if ( m_bVerbExecutionInProgress && osl_getThreadIdentifier( NULL ) == m_nVerbExecutionThreadIdentifier ) + m_bChangedOnVerbExecution = sal_True; +} +#endif +//----------------------------------------------- +void VerbExecutionController::LockNotification() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + if ( m_nNotificationLock < SAL_MAX_INT32 ) + m_nNotificationLock++; +} + +//----------------------------------------------- +void VerbExecutionController::UnlockNotification() +{ + osl::MutexGuard aGuard( m_aVerbExecutionMutex ); + if ( m_nNotificationLock > 0 ) + m_nNotificationLock--; +} + +//----------------------------------------------- +uno::Reference< io::XStream > OleEmbeddedObject::GetNewFilledTempStream_Impl( const uno::Reference< io::XInputStream >& xInStream ) + throw( io::IOException ) +{ + OSL_ENSURE( xInStream.is(), "Wrong parameter is provided!\n" ); + + uno::Reference < io::XStream > xTempFile( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY_THROW ); + + uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream(); + if ( xTempOutStream.is() ) + { + ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream ); + xTempOutStream->flush(); + } + else + throw io::IOException(); // TODO: + + return xTempFile; +} + +//------------------------------------------------------ +uno::Reference< io::XStream > OleEmbeddedObject::TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream ) + throw ( uno::Exception ) +{ + // TODO/LATER: Actually this should be done by a centralized component ( may be a graphical filter ) + if ( !m_xFactory.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XInputStream > xInStream = xStream->getInputStream(); + if ( !xInStream.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW ); + xSeek->seek( 0 ); + + uno::Sequence< sal_Int8 > aData( 8 ); + sal_Int32 nRead = xInStream->readBytes( aData, 8 ); + xSeek->seek( 0 ); + + if ( ( nRead >= 2 && aData[0] == 'B' && aData[1] == 'M' ) + || ( nRead >= 4 && aData[0] == 1 && aData[1] == 0 && aData[2] == 9 && aData[3] == 0 ) ) + { + // it should be a bitmap or a Metafile + return xStream; + } + +// sal_Bool bSetSizeToRepl = sal_False; +// awt::Size aSizeToSet; + + sal_uInt32 nHeaderOffset = 0; + if ( ( nRead >= 8 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 ) + && ( aData[4] == 2 || aData[4] == 3 || aData[4] == 14 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 ) + { + nHeaderOffset = 40; + xSeek->seek( 8 ); + + // TargetDevice might be used in future, currently the cache has specified NULL + uno::Sequence< sal_Int8 > aHeadData( 4 ); + nRead = xInStream->readBytes( aHeadData, 4 ); + sal_uInt32 nLen = 0; + if ( nRead == 4 && aHeadData.getLength() == 4 ) + nLen = ( ( ( (sal_uInt32)aHeadData[3] * 0x100 + (sal_uInt32)aHeadData[2] ) * 0x100 ) + (sal_uInt32)aHeadData[1] ) * 0x100 + (sal_uInt32)aHeadData[0]; + if ( nLen > 4 ) + { + xInStream->skipBytes( nLen - 4 ); + nHeaderOffset += nLen - 4; + } + +// if ( aData[4] == 3 ) +// { +// try +// { +// +// aSizeToSet = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); +// aSizeToSet.Width /= 364; //2540; // let the size be in inches, as wmf requires +// aSizeToSet.Height /= 364; //2540; // let the size be in inches, as wmf requires +// bSetSizeToRepl = sal_True; +// } +// catch( uno::Exception& ) +// {} +// } + } + else if ( nRead > 4 ) + { + // check whether the first bytes represent the size + sal_uInt32 nSize = 0; + for ( sal_Int32 nInd = 3; nInd >= 0; nInd-- ) + nSize = ( nSize << 8 ) + (sal_uInt8)aData[nInd]; + + if ( nSize == xSeek->getLength() - 4 ) + nHeaderOffset = 4; + } + + if ( nHeaderOffset ) + { + // this is either a bitmap or a metafile clipboard format, retrieve the pure stream + uno::Reference < io::XStream > xResult( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY_THROW ); + uno::Reference < io::XSeekable > xResultSeek( xResult, uno::UNO_QUERY_THROW ); + uno::Reference < io::XOutputStream > xResultOut = xResult->getOutputStream(); + uno::Reference < io::XInputStream > xResultIn = xResult->getInputStream(); + if ( !xResultOut.is() || !xResultIn.is() ) + throw uno::RuntimeException(); + + // if it is windows metafile the size must be provided + // the solution is not used currently +// if ( bSetSizeToRepl && abs( aSizeToSet.Width ) < 0xFFFF && abs( aSizeToSet.Height ) < 0xFFFF ) +// { +// uno::Sequence< sal_Int8 > aHeader(22); +// sal_uInt8* pBuffer = (sal_uInt8*)aHeader.getArray(); +// +// // write 0x9ac6cdd7L +// pBuffer[0] = 0xd7; +// pBuffer[1] = 0xcd; +// pBuffer[2] = 0xc6; +// pBuffer[3] = 0x9a; +// +// // following data seems to have no value +// pBuffer[4] = 0; +// pBuffer[5] = 0; +// +// // must be set to 0 +// pBuffer[6] = 0; +// pBuffer[7] = 0; +// pBuffer[8] = 0; +// pBuffer[9] = 0; +// +// // width of the picture +// pBuffer[10] = abs( aSizeToSet.Width ) % 0x100; +// pBuffer[11] = ( abs( aSizeToSet.Width ) / 0x100 ) % 0x100; +// +// // height of the picture +// pBuffer[12] = abs( aSizeToSet.Height ) % 0x100; +// pBuffer[13] = ( abs( aSizeToSet.Height ) / 0x100 ) % 0x100; +// +// // write 2540 +// pBuffer[14] = 0x6c; //0xec; +// pBuffer[15] = 0x01; //0x09; +// +// // fill with 0 +// for ( sal_Int32 nInd = 16; nInd < 22; nInd++ ) +// pBuffer[nInd] = 0; +// +// xResultOut->writeBytes( aHeader ); +// } + + xSeek->seek( nHeaderOffset ); // header size for these formats + ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xResultOut ); + xResultOut->closeOutput(); + xResultSeek->seek( 0 ); + xSeek->seek( 0 ); + + return xResult; + } + + return uno::Reference< io::XStream >(); +} + +//------------------------------------------------------ +void OleEmbeddedObject::InsertVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream, + const uno::Reference< io::XStream >& xCachedVisualRepresentation ) + throw ( uno::Exception ) +{ + OSL_ENSURE( xTargetStream.is() && xCachedVisualRepresentation.is(), "Invalid argumants!\n" ); + + if ( !xTargetStream.is() || !xCachedVisualRepresentation.is() ) + throw uno::RuntimeException(); + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xTargetStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + + uno::Reference< container::XNameContainer > xNameContainer( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), + aArgs ), + uno::UNO_QUERY ); + + if ( !xNameContainer.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY_THROW ); + if ( xCachedSeek.is() ) + xCachedSeek->seek( 0 ); + + uno::Reference < io::XStream > xTempFile( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY_THROW ); + + uno::Reference< io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW ); + uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream(); + if ( xTempOutStream.is() ) + { + // the OlePres stream must have additional header + // TODO/LATER: might need to be extended in future ( actually makes sence only for SO7 format ) + uno::Reference< io::XInputStream > xInCacheStream = xCachedVisualRepresentation->getInputStream(); + if ( !xInCacheStream.is() ) + throw uno::RuntimeException(); + + // write 0xFFFFFFFF at the beginning + uno::Sequence< sal_Int8 > aData( 4 ); + *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF; + + xTempOutStream->writeBytes( aData ); + + // write clipboard format + uno::Sequence< sal_Int8 > aSigData( 2 ); + xInCacheStream->readBytes( aSigData, 2 ); + if ( aSigData.getLength() < 2 ) + throw io::IOException(); + + if ( aSigData[0] == 'B' && aSigData[1] == 'M' ) + { + // it's a bitmap + aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0; + } + else + { + // treat it as a metafile + aData[0] = 0x03; aData[1] = 0; aData[2] = 0; aData[3] = 0; + } + xTempOutStream->writeBytes( aData ); + + // write job related information + aData[0] = 0x04; aData[1] = 0; aData[2] = 0; aData[3] = 0; + xTempOutStream->writeBytes( aData ); + + // write aspect + aData[0] = 0x01; aData[1] = 0; aData[2] = 0; aData[3] = 0; + xTempOutStream->writeBytes( aData ); + + // write l-index + *( (sal_uInt32*)aData.getArray() ) = 0xFFFFFFFF; + xTempOutStream->writeBytes( aData ); + + // write adv. flags + aData[0] = 0x02; aData[1] = 0; aData[2] = 0; aData[3] = 0; + xTempOutStream->writeBytes( aData ); + + // write compression + *( (sal_uInt32*)aData.getArray() ) = 0x0; + xTempOutStream->writeBytes( aData ); + + // get the size + awt::Size aSize = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + sal_Int32 nIndex = 0; + + // write width + for ( nIndex = 0; nIndex < 4; nIndex++ ) + { + aData[nIndex] = (sal_Int8)( aSize.Width % 0x100 ); + aSize.Width /= 0x100; + } + xTempOutStream->writeBytes( aData ); + + // write height + for ( nIndex = 0; nIndex < 4; nIndex++ ) + { + aData[nIndex] = (sal_Int8)( aSize.Height % 0x100 ); + aSize.Height /= 0x100; + } + xTempOutStream->writeBytes( aData ); + + // write garbage, it will be overwritten by the size + xTempOutStream->writeBytes( aData ); + + // write first bytes that was used to detect the type + xTempOutStream->writeBytes( aSigData ); + + // write the rest of the stream + ::comphelper::OStorageHelper::CopyInputToOutput( xInCacheStream, xTempOutStream ); + + // write the size of the stream + sal_Int64 nLength = xTempSeek->getLength() - 40; + if ( nLength < 0 || nLength >= 0xFFFFFFFF ) + { + OSL_ENSURE( sal_False, "Length is not acceptable!" ); + return; + } + for ( sal_Int32 nInd = 0; nInd < 4; nInd++ ) + { + aData[nInd] = (sal_Int8)( ( (sal_uInt64) nLength ) % 0x100 ); + nLength /= 0x100; + } + xTempSeek->seek( 36 ); + xTempOutStream->writeBytes( aData ); + + xTempOutStream->flush(); + + xTempSeek->seek( 0 ); + if ( xCachedSeek.is() ) + xCachedSeek->seek( 0 ); + } + else + throw io::IOException(); // TODO: + + // insert the result file as replacement image + ::rtl::OUString aCacheName = ::rtl::OUString::createFromAscii( "\002OlePres000" ); + if ( xNameContainer->hasByName( aCacheName ) ) + xNameContainer->replaceByName( aCacheName, uno::makeAny( xTempFile ) ); + else + xNameContainer->insertByName( aCacheName, uno::makeAny( xTempFile ) ); + + uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY ); + if ( !xTransacted.is() ) + throw uno::RuntimeException(); + + xTransacted->commit(); +} + +//------------------------------------------------------ +void OleEmbeddedObject::RemoveVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream ) + throw ( uno::Exception ) +{ + OSL_ENSURE( xTargetStream.is(), "Invalid argumant!\n" ); + if ( !xTargetStream.is() ) + throw uno::RuntimeException(); + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xTargetStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + uno::Reference< container::XNameContainer > xNameContainer( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), + aArgs ), + uno::UNO_QUERY ); + + if ( !xNameContainer.is() ) + throw uno::RuntimeException(); + + for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ ) + { + ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" ); + aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); + if ( xNameContainer->hasByName( aStreamName ) ) + xNameContainer->removeByName( aStreamName ); + } + + uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY ); + if ( !xTransacted.is() ) + throw uno::RuntimeException(); + + xTransacted->commit(); +} + +//------------------------------------------------------ +void OleEmbeddedObject::SetVisReplInStream( sal_Bool bExists ) +{ + m_bVisReplInitialized = sal_True; + m_bVisReplInStream = bExists; +} + +//------------------------------------------------------ +sal_Bool OleEmbeddedObject::HasVisReplInStream() +{ + if ( !m_bVisReplInitialized ) + { + if ( m_xCachedVisualRepresentation.is() ) + SetVisReplInStream( sal_True ); + else + { + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::HasVisualReplInStream, analizing" ); + + uno::Reference< io::XInputStream > xStream; + + OSL_ENSURE( !m_pOleComponent || m_aTempURL.getLength(), "The temporary file must exist if there is a component!\n" ); + if ( m_aTempURL.getLength() ) + { + try + { + // open temporary file for reading + uno::Reference < ucb::XSimpleFileAccess > xTempAccess( + m_xFactory->createInstance ( + ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), + uno::UNO_QUERY ); + + if ( !xTempAccess.is() ) + throw uno::RuntimeException(); // TODO: + + xStream = xTempAccess->openFileRead( m_aTempURL ); + } + catch( uno::Exception& ) + {} + } + + if ( !xStream.is() ) + xStream = m_xObjectStream->getInputStream(); + + if ( xStream.is() ) + { + sal_Bool bExists = sal_False; + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + uno::Reference< container::XNameContainer > xNameContainer( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), + aArgs ), + uno::UNO_QUERY ); + + if ( xNameContainer.is() ) + { + for ( sal_uInt8 nInd = 0; nInd < 10 && !bExists; nInd++ ) + { + ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" ); + aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); + try + { + bExists = xNameContainer->hasByName( aStreamName ); + } + catch( uno::Exception& ) + {} + } + } + + SetVisReplInStream( bExists ); + } + } + } + + return m_bVisReplInStream; +} + +//------------------------------------------------------ +uno::Reference< io::XStream > OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation_Impl( + const uno::Reference< io::XStream >& xStream, + sal_Bool bAllowToRepair50 ) + throw () +{ + uno::Reference< io::XStream > xResult; + + if ( xStream.is() ) + { + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation, retrieving" ); + + uno::Reference< container::XNameContainer > xNameContainer; + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[0] <<= xStream; + aArgs[1] <<= (sal_Bool)sal_True; // do not create copy + try + { + xNameContainer = uno::Reference< container::XNameContainer >( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), + aArgs ), + uno::UNO_QUERY ); + } + catch( uno::Exception& ) + {} + + if ( xNameContainer.is() ) + { + for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ ) + { + ::rtl::OUString aStreamName = ::rtl::OUString::createFromAscii( "\002OlePres00" ); + aStreamName += ::rtl::OUString::valueOf( (sal_Int32)nInd ); + uno::Reference< io::XStream > xCachedCopyStream; + try + { + if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() ) + { + xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream ); + if ( xResult.is() ) + break; + } + } + catch( uno::Exception& ) + {} + + if ( nInd == 0 ) + { + // to be compatible with the old versions Ole10Native is checked after OlePress000 + aStreamName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\001Ole10Native" ) ); + try + { + if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() ) + { + xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream ); + if ( xResult.is() ) + break; + } + } + catch( uno::Exception& ) + {} + } + } + + try + { + if ( bAllowToRepair50 && !xResult.is() ) + { + ::rtl::OUString aOrigContName( RTL_CONSTASCII_USTRINGPARAM( "Ole-Object" ) ); + if ( xNameContainer->hasByName( aOrigContName ) ) + { + uno::Reference< embed::XClassifiedObject > xClassified( xNameContainer, uno::UNO_QUERY_THROW ); + uno::Sequence< sal_Int8 > aClassID; + if ( MimeConfigurationHelper::ClassIDsEqual( xClassified->getClassID(), MimeConfigurationHelper::GetSequenceClassID( SO3_OUT_CLASSID ) ) ) + { + // this is an OLE object wrongly stored in 5.0 format + // this object must be repaired since SO7 has done it + + uno::Reference< io::XOutputStream > xOutputStream = xStream->getOutputStream(); + uno::Reference< io::XTruncate > xTruncate( xOutputStream, uno::UNO_QUERY_THROW ); + + uno::Reference< io::XInputStream > xOrigInputStream; + if ( ( xNameContainer->getByName( aOrigContName ) >>= xOrigInputStream ) + && xOrigInputStream.is() ) + { + // the provided input stream must be based on temporary medium and must be independent + // from the stream the storage is based on + uno::Reference< io::XSeekable > xOrigSeekable( xOrigInputStream, uno::UNO_QUERY ); + if ( xOrigSeekable.is() ) + xOrigSeekable->seek( 0 ); + + uno::Reference< lang::XComponent > xNameContDisp( xNameContainer, uno::UNO_QUERY_THROW ); + xNameContDisp->dispose(); // free the original stream + + xTruncate->truncate(); + ::comphelper::OStorageHelper::CopyInputToOutput( xOrigInputStream, xOutputStream ); + xOutputStream->flush(); + + if ( xStream == m_xObjectStream ) + { + if ( m_aTempURL.getLength() ) + { + // this is the own stream, so the temporary URL must be cleaned if it exists + KillFile_Impl( m_aTempURL, m_xFactory ); + m_aTempURL = ::rtl::OUString(); + } + +#ifdef WNT + // retry to create the component after recovering + GetRidOfComponent(); + + try + { + CreateOleComponentAndLoad_Impl( NULL ); + m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction + } + catch( uno::Exception& ) + { + GetRidOfComponent(); + } +#endif + } + + xResult = TryToRetrieveCachedVisualRepresentation_Impl( xStream, sal_False ); + } + } + } + } + } + catch( uno::Exception& ) + {} + } + } + + return xResult; +} + +//------------------------------------------------------ +void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage, + const uno::Reference< io::XStream >& xNewObjectStream, + const ::rtl::OUString& aNewName ) +{ + if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) ) + { + OSL_ENSURE( xNewObjectStream == m_xObjectStream, "The streams must be the same!\n" ); + return; + } + + try { + uno::Reference< lang::XComponent > xComponent( m_xObjectStream, uno::UNO_QUERY ); + OSL_ENSURE( !m_xObjectStream.is() || xComponent.is(), "Wrong stream implementation!" ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( uno::Exception& ) + { + } + + m_xObjectStream = xNewObjectStream; + m_xParentStorage = xNewParentStorage; + m_aEntryName = aNewName; +} + +//------------------------------------------------------ +void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage, + const ::rtl::OUString& aNewName ) +{ + if ( xNewParentStorage == m_xParentStorage && aNewName.equals( m_aEntryName ) ) + return; + + sal_Int32 nStreamMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; + + uno::Reference< io::XStream > xNewOwnStream = xNewParentStorage->openStreamElement( aNewName, nStreamMode ); + OSL_ENSURE( xNewOwnStream.is(), "The method can not return empty reference!" ); + + SwitchOwnPersistence( xNewParentStorage, xNewOwnStream, aNewName ); +} + +#ifdef WNT +//---------------------------------------------- +sal_Bool OleEmbeddedObject::SaveObject_Impl() +{ + sal_Bool bResult = sal_False; + + if ( m_xClientSite.is() ) + { + try + { + m_xClientSite->saveObject(); + bResult = sal_True; + } + catch( uno::Exception& ) + { + } + } + + return bResult; +} + +//---------------------------------------------- +sal_Bool OleEmbeddedObject::OnShowWindow_Impl( sal_Bool bShow ) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + + sal_Bool bResult = sal_False; + + OSL_ENSURE( m_nObjectState != -1, "The object has no persistence!\n" ); + OSL_ENSURE( m_nObjectState != embed::EmbedStates::LOADED, "The object get OnShowWindow in loaded state!\n" ); + if ( m_nObjectState == -1 || m_nObjectState == embed::EmbedStates::LOADED ) + return sal_False; + + // the object is either activated or deactivated + sal_Int32 nOldState = m_nObjectState; + if ( bShow && m_nObjectState == embed::EmbedStates::RUNNING ) + { + m_nObjectState = embed::EmbedStates::ACTIVE; + m_aVerbExecutionController.ObjectIsActive(); + + aGuard.clear(); + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + } + else if ( !bShow && m_nObjectState == embed::EmbedStates::ACTIVE ) + { + m_nObjectState = embed::EmbedStates::RUNNING; + aGuard.clear(); + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + } + + if ( m_xClientSite.is() ) + { + try + { + m_xClientSite->visibilityChanged( bShow ); + bResult = sal_True; + } + catch( uno::Exception& ) + { + } + } + + return bResult; +} + +//------------------------------------------------------ +void OleEmbeddedObject::OnIconChanged_Impl() +{ + // TODO/LATER: currently this notification seems to be impossible + // MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnIconChanged" ) ); +} + +//------------------------------------------------------ +void OleEmbeddedObject::OnViewChanged_Impl() +{ + if ( m_bDisposed ) + throw lang::DisposedException(); + + // For performance reasons the notification currently is ignored, STAMPIT object is the exception, + // it can never be active and never call SaveObject, so it is the only way to detect that it is changed + + // ==== the STAMPIT related solution ============================= + // the following variable is used to detect whether the object was modified during verb execution + m_aVerbExecutionController.ModificationNotificationIsDone(); + + // The following things are controlled by VerbExecutionController: + // - if the verb execution is in progress and the view is changed the object will be stored + // after the execution, so there is no need to send the notification. + // - the STAMPIT object can never be active. + if ( m_aVerbExecutionController.CanDoNotification() + && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE ) + { + OSL_ENSURE( MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0x852ee1c9, 0x9058, 0x44ba, 0x8c,0x6c,0x0c,0x5f,0xc6,0x6b,0xdb,0x8d ) ) + || MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0xcf1b4491, 0xbea3, 0x4c9f, 0xa7,0x0f,0x22,0x1b,0x1e,0xca,0xef,0x3e ) ), + "Expected to be triggered for STAMPIT only! Please contact developers!\n" ); + + // The view is changed while the object is in running state, save the new object + m_xCachedVisualRepresentation = uno::Reference< io::XStream >(); + SaveObject_Impl(); + MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) ); + } + // =============================================================== +} + +//------------------------------------------------------ +void OleEmbeddedObject::OnClosed_Impl() +{ + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( m_nObjectState != embed::EmbedStates::LOADED ) + { + sal_Int32 nOldState = m_nObjectState; + m_nObjectState = embed::EmbedStates::LOADED; + StateChangeNotification_Impl( sal_False, nOldState, m_nObjectState ); + } +} + +//------------------------------------------------------ +::rtl::OUString OleEmbeddedObject::CreateTempURLEmpty_Impl() +{ + OSL_ENSURE( !m_aTempURL.getLength(), "The object has already the temporary file!" ); + m_aTempURL = GetNewTempFileURL_Impl( m_xFactory ); + + return m_aTempURL; +} + +//------------------------------------------------------ +::rtl::OUString OleEmbeddedObject::GetTempURL_Impl() +{ + if ( !m_aTempURL.getLength() ) + { + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::GetTempURL_Impl, tempfile creation" ); + + // if there is no temporary file, it will be created from the own entry + uno::Reference< embed::XOptimizedStorage > xOptParStorage( m_xParentStorage, uno::UNO_QUERY ); + if ( xOptParStorage.is() ) + { + m_aTempURL = GetNewFilledTempFile_Impl( xOptParStorage, m_aEntryName, m_xFactory ); + } + else if ( m_xObjectStream.is() ) + { + // load object from the stream + uno::Reference< io::XInputStream > xInStream = m_xObjectStream->getInputStream(); + if ( !xInStream.is() ) + throw io::IOException(); // TODO: access denied + + m_aTempURL = GetNewFilledTempFile_Impl( xInStream, m_xFactory ); + } + } + + return m_aTempURL; +} + +//------------------------------------------------------ +void OleEmbeddedObject::CreateOleComponent_Impl( OleComponent* pOleComponent ) +{ + if ( !m_pOleComponent ) + { + m_pOleComponent = pOleComponent ? pOleComponent : new OleComponent( m_xFactory, this ); + m_pOleComponent->acquire(); // TODO: needs holder? + + if ( !m_xClosePreventer.is() ) + m_xClosePreventer = uno::Reference< util::XCloseListener >( + static_cast< ::cppu::OWeakObject* >( new OClosePreventer ), + uno::UNO_QUERY ); + + m_pOleComponent->addCloseListener( m_xClosePreventer ); + } +} + +//------------------------------------------------------ +void OleEmbeddedObject::CreateOleComponentAndLoad_Impl( OleComponent* pOleComponent ) +{ + if ( !m_pOleComponent ) + { + if ( !m_xObjectStream.is() ) + throw uno::RuntimeException(); + + CreateOleComponent_Impl( pOleComponent ); + + // after the loading the object can appear as a link + // will be detected later by olecomponent + + GetTempURL_Impl(); + if ( !m_aTempURL.getLength() ) + throw uno::RuntimeException(); // TODO + + m_pOleComponent->LoadEmbeddedObject( m_aTempURL ); + } +} + +//------------------------------------------------------ +void OleEmbeddedObject::CreateOleComponentFromClipboard_Impl( OleComponent* pOleComponent ) +{ + if ( !m_pOleComponent ) + { + if ( !m_xObjectStream.is() ) + throw uno::RuntimeException(); + + CreateOleComponent_Impl( pOleComponent ); + + // after the loading the object can appear as a link + // will be detected later by olecomponent + m_pOleComponent->CreateObjectFromClipboard(); + } +} + +//------------------------------------------------------ +uno::Reference< io::XOutputStream > OleEmbeddedObject::GetStreamForSaving() +{ + if ( !m_xObjectStream.is() ) + throw uno::RuntimeException(); //TODO: + + uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream(); + if ( !xOutStream.is() ) + throw io::IOException(); //TODO: access denied + + uno::Reference< io::XTruncate > xTruncate( xOutStream, uno::UNO_QUERY ); + if ( !xTruncate.is() ) + throw uno::RuntimeException(); //TODO: + + xTruncate->truncate(); + + return xOutStream; +} + +//---------------------------------------------- +void OleEmbeddedObject::StoreObjectToStream( uno::Reference< io::XOutputStream > xOutStream ) + throw ( uno::Exception ) +{ + // this method should be used only on windows + if ( m_pOleComponent ) + m_pOleComponent->StoreOwnTmpIfNecessary(); + + // now all the changes should be in temporary location + if ( !m_aTempURL ) + throw uno::RuntimeException(); + + // open temporary file for reading + uno::Reference < ucb::XSimpleFileAccess > xTempAccess( + m_xFactory->createInstance ( + ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), + uno::UNO_QUERY ); + + if ( !xTempAccess.is() ) + throw uno::RuntimeException(); // TODO: + + uno::Reference< io::XInputStream > xTempInStream = xTempAccess->openFileRead( m_aTempURL ); + OSL_ENSURE( xTempInStream.is(), "The object's temporary file can not be reopened for reading!\n" ); + + // TODO: use bStoreVisReplace + + if ( xTempInStream.is() ) + { + // write all the contents to XOutStream + uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY ); + if ( !xTrunc.is() ) + throw uno::RuntimeException(); //TODO: + + xTrunc->truncate(); + + ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutStream ); + } + else + throw io::IOException(); // TODO: + + // TODO: should the view replacement be in the stream ??? + // probably it must be specified on storing +} +#endif +//------------------------------------------------------ +void OleEmbeddedObject::StoreToLocation_Impl( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& /*lArguments*/, + const uno::Sequence< beans::PropertyValue >& lObjArgs, + sal_Bool bSaveAs ) + throw ( uno::Exception ) +{ + // TODO: use lObjArgs + // TODO: exchange StoreVisualReplacement by SO file format version? + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" ); + + sal_Bool bVisReplIsStored = sal_False; + + sal_Bool bTryOptimization = sal_False; + sal_Bool bStoreVis = m_bStoreVisRepl; + uno::Reference< io::XStream > xCachedVisualRepresentation; + for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) + { + if ( lObjArgs[nInd].Name.equalsAscii( "StoreVisualReplacement" ) ) + lObjArgs[nInd].Value >>= bStoreVis; + else if ( lObjArgs[nInd].Name.equalsAscii( "VisualReplacement" ) ) + lObjArgs[nInd].Value >>= xCachedVisualRepresentation; + else if ( lObjArgs[nInd].Name.equalsAscii( "CanTryOptimization" ) ) + lObjArgs[nInd].Value >>= bTryOptimization; + } + + // ignore visual representation provided from outside if it should not be stored + if ( !bStoreVis ) + xCachedVisualRepresentation = uno::Reference< io::XStream >(); + + if ( bStoreVis && !HasVisReplInStream() && !xCachedVisualRepresentation.is() ) + throw io::IOException(); // TODO: there is no cached visual representation and nothing is provided from outside + + // if the representation is provided from outside it should be copied to a local stream + sal_Bool bNeedLocalCache = xCachedVisualRepresentation.is(); + + uno::Reference< io::XStream > xTargetStream; + + sal_Bool bStoreLoaded = sal_False; + if ( m_nObjectState == embed::EmbedStates::LOADED +#ifdef WNT + // if the object was NOT modified after storing it can be just copied + // as if it was in loaded state + || ( m_pOleComponent && !m_pOleComponent->IsDirty() ) +#endif + ) + { + sal_Bool bOptimizedCopyingDone = sal_False; + + if ( bTryOptimization && bStoreVis == HasVisReplInStream() ) + { + try + { + uno::Reference< embed::XOptimizedStorage > xSourceOptStor( m_xParentStorage, uno::UNO_QUERY_THROW ); + uno::Reference< embed::XOptimizedStorage > xTargetOptStor( xStorage, uno::UNO_QUERY_THROW ); + xSourceOptStor->copyElementDirectlyTo( m_aEntryName, xTargetOptStor, sEntName ); + bOptimizedCopyingDone = sal_True; + } + catch( uno::Exception& ) + { + } + } + + if ( !bOptimizedCopyingDone ) + { + // if optimized copying fails a normal one should be tried + m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName ); + } + + // the locally retrieved representation is always preferable + // since the object is in loaded state the representation is unchanged + if ( m_xCachedVisualRepresentation.is() ) + { + xCachedVisualRepresentation = m_xCachedVisualRepresentation; + bNeedLocalCache = sal_False; + } + + bVisReplIsStored = HasVisReplInStream(); + bStoreLoaded = sal_True; + } +#ifdef WNT + else if ( m_pOleComponent ) + { + xTargetStream = + xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE ); + if ( !xTargetStream.is() ) + throw io::IOException(); //TODO: access denied + + SetStreamMediaType_Impl( xTargetStream, ::rtl::OUString::createFromAscii( "application/vnd.sun.star.oleobject" ) ); + uno::Reference< io::XOutputStream > xOutStream = xTargetStream->getOutputStream(); + if ( !xOutStream.is() ) + throw io::IOException(); //TODO: access denied + + StoreObjectToStream( xOutStream ); + bVisReplIsStored = sal_True; + + if ( bSaveAs ) + { + // no need to do it on StoreTo since in this case the replacement is in the stream + // and there is no need to cache it even if it is thrown away because the object + // is not changed by StoreTo action + + uno::Reference< io::XStream > xTmpCVRepresentation = + TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); + + // the locally retrieved representation is always preferable + if ( xTmpCVRepresentation.is() ) + { + xCachedVisualRepresentation = xTmpCVRepresentation; + bNeedLocalCache = sal_False; + } + } + } +#endif + else + { + throw io::IOException(); // TODO + } + + if ( !xTargetStream.is() ) + { + xTargetStream = + xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE ); + if ( !xTargetStream.is() ) + throw io::IOException(); //TODO: access denied + } + + LetCommonStoragePassBeUsed_Impl( xTargetStream ); + + if ( bStoreVis != bVisReplIsStored ) + { + if ( bStoreVis ) + { + if ( !xCachedVisualRepresentation.is() ) + xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); + + OSL_ENSURE( xCachedVisualRepresentation.is(), "No representation is available!" ); + + // the following copying will be done in case it is SaveAs anyway + // if it is not SaveAs the seekable access is not required currently + // TODO/LATER: may be required in future + if ( bSaveAs ) + { + uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY ); + if ( !xCachedSeek.is() ) + { + xCachedVisualRepresentation + = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() ); + bNeedLocalCache = sal_False; + } + } + + InsertVisualCache_Impl( xTargetStream, xCachedVisualRepresentation ); + } + else + { + // the removed representation could be cached by this method + if ( !xCachedVisualRepresentation.is() ) + xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream ); + + RemoveVisualCache_Impl( xTargetStream ); + } + } + + if ( bSaveAs ) + { + m_bWaitSaveCompleted = sal_True; + m_xNewObjectStream = xTargetStream; + m_xNewParentStorage = xStorage; + m_aNewEntryName = sEntName; + m_bNewVisReplInStream = bStoreVis; + m_bStoreLoaded = bStoreLoaded; + + if ( xCachedVisualRepresentation.is() ) + { + if ( bNeedLocalCache ) + m_xNewCachedVisRepl = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() ); + else + m_xNewCachedVisRepl = xCachedVisualRepresentation; + } + + // TODO: register listeners for storages above, in case they are disposed + // an exception will be thrown on saveCompleted( true ) + } + else + { + uno::Reference< lang::XComponent > xComp( xTargetStream, uno::UNO_QUERY ); + if ( xComp.is() ) + { + try { + xComp->dispose(); + } catch( uno::Exception& ) + { + } + } + } +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::setPersistentEntry( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + sal_Int32 nEntryConnectionMode, + const uno::Sequence< beans::PropertyValue >& lArguments, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::setPersistentEntry" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setPersistentEntry( xStorage, sEntName, nEntryConnectionMode, lArguments, lObjArgs ); + return; + } + // end wrapping related part ==================== + + // TODO: use lObjArgs + + // the type of the object must be already set + // a kind of typedetection should be done in the factory; + // the only exception is object initialized from a stream, + // the class ID will be detected from the stream + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + // May be LOADED should be forbidden here ??? + if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) + && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) ) + { + // if the object is not loaded + // it can not get persistant representation without initialization + + // if the object is loaded + // it can switch persistant representation only without initialization + + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "Can't change persistant representation of activated object!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + { + if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) + saveCompleted( ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) ); + else + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); + if ( !xNameAccess.is() ) + throw uno::RuntimeException(); //TODO + + // detect entry existence + sal_Bool bElExists = xNameAccess->hasByName( sEntName ); + + m_bReadOnly = sal_False; + sal_Int32 nInd = 0; + for ( nInd = 0; nInd < lArguments.getLength(); nInd++ ) + if ( lArguments[nInd].Name.equalsAscii( "ReadOnly" ) ) + lArguments[nInd].Value >>= m_bReadOnly; + +#ifdef WNT + sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE; +#endif + + SwitchOwnPersistence( xStorage, sEntName ); + + for ( nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) + if ( lObjArgs[nInd].Name.equalsAscii( "StoreVisualReplacement" ) ) + lObjArgs[nInd].Value >>= m_bStoreVisRepl; + +#ifdef WNT + if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT ) + { + if ( m_bFromClipboard ) + { + // the object should be initialized from clipboard + // inpossibility to initialize the object means error here + CreateOleComponentFromClipboard_Impl( NULL ); + m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction + m_pOleComponent->RunObject(); + m_nObjectState = embed::EmbedStates::RUNNING; + } + else if ( bElExists ) + { + // load object from the stream + // after the loading the object can appear as a link + // will be detected by olecomponent + try + { + CreateOleComponentAndLoad_Impl( NULL ); + m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction + } + catch( uno::Exception& ) + { + // TODO/LATER: detect classID of the object if possible + // means that the object inprocess server could not be successfuly instantiated + GetRidOfComponent(); + } + + m_nObjectState = embed::EmbedStates::LOADED; + } + else + { + // create a new object + CreateOleComponent_Impl(); + m_pOleComponent->CreateNewEmbeddedObject( m_aClassID ); + m_pOleComponent->RunObject(); + m_nObjectState = embed::EmbedStates::RUNNING; + } + } + else + { + if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE ) + throw io::IOException(); + + if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) + { + // the document just already changed its stream to store to; + // the links to OLE documents switch their persistence in the same way + // as normal embedded objects + } + else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT ) + { + // create a new object, that will be stored in specified stream + CreateOleComponent_Impl(); + + m_pOleComponent->CreateNewEmbeddedObject( m_aClassID ); + m_pOleComponent->RunObject(); + m_nObjectState = embed::EmbedStates::RUNNING; + } + else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT ) + { + // use URL ( may be content or stream later ) from MediaDescriptor to initialize object + ::rtl::OUString aURL; + for ( sal_Int32 nInd = 0; nInd < lArguments.getLength(); nInd++ ) + if ( lArguments[nInd].Name.equalsAscii( "URL" ) ) + lArguments[nInd].Value >>= aURL; + + if ( !aURL.getLength() ) + throw lang::IllegalArgumentException( + ::rtl::OUString::createFromAscii( "Empty URL is provided in the media descriptor!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 4 ); + + CreateOleComponent_Impl(); + + // TODO: the m_bIsLink value must be set already + if ( !m_bIsLink ) + m_pOleComponent->CreateObjectFromFile( aURL ); + else + m_pOleComponent->CreateLinkFromFile( aURL ); + + m_pOleComponent->RunObject(); + m_aClassID = m_pOleComponent->GetCLSID(); // was not set during consruction + + m_nObjectState = embed::EmbedStates::RUNNING; + } + //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT ) + //{ + //TODO: + //} + else + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 3 ); + } +#else + // On unix the ole object can not do anything except storing itself somewere + if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT && bElExists ) + { + // TODO/LATER: detect classID of the object + // can be a real problem for the links + + m_nObjectState = embed::EmbedStates::LOADED; + } + else if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT ) + { + // do nothing, the object has already switched it's persistence + } + else + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong connection mode is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 3 ); + +#endif +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& lArguments, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeToEntry" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->storeToEntry( xStorage, sEntName, lArguments, lObjArgs ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); + + StoreToLocation_Impl( xStorage, sEntName, lArguments, lObjArgs, sal_False ); + + // TODO: should the listener notification be done? +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& lArguments, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeAsEntry" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->storeAsEntry( xStorage, sEntName, lArguments, lObjArgs ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); + + StoreToLocation_Impl( xStorage, sEntName, lArguments, lObjArgs, sal_True ); + + // TODO: should the listener notification be done here or in saveCompleted? +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::saveCompleted( sal_Bool bUseNew ) + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::saveCompleted" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->saveCompleted( bUseNew ); + return; + } + // end wrapping related part ==================== + + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + // it is allowed to call saveCompleted( false ) for nonstored objects + if ( !m_bWaitSaveCompleted && !bUseNew ) + return; + + OSL_ENSURE( m_bWaitSaveCompleted, "Unexpected saveCompleted() call!\n" ); + if ( !m_bWaitSaveCompleted ) + throw io::IOException(); // TODO: illegal call + + OSL_ENSURE( m_xNewObjectStream.is() && m_xNewParentStorage.is() , "Internal object information is broken!\n" ); + if ( !m_xNewObjectStream.is() || !m_xNewParentStorage.is() ) + throw uno::RuntimeException(); // TODO: broken internal information + + if ( bUseNew ) + { + SwitchOwnPersistence( m_xNewParentStorage, m_xNewObjectStream, m_aNewEntryName ); + m_bStoreVisRepl = m_bNewVisReplInStream; + SetVisReplInStream( m_bNewVisReplInStream ); + m_xCachedVisualRepresentation = m_xNewCachedVisRepl; + } + else + { + // close remembered stream + try { + uno::Reference< lang::XComponent > xComponent( m_xNewObjectStream, uno::UNO_QUERY ); + OSL_ENSURE( xComponent.is(), "Wrong storage implementation!" ); + if ( xComponent.is() ) + xComponent->dispose(); + } + catch ( uno::Exception& ) + { + } + } + + sal_Bool bStoreLoaded = m_bStoreLoaded; + + m_xNewObjectStream = uno::Reference< io::XStream >(); + m_xNewParentStorage = uno::Reference< embed::XStorage >(); + m_aNewEntryName = ::rtl::OUString(); + m_bWaitSaveCompleted = sal_False; + m_bNewVisReplInStream = sal_False; + m_xNewCachedVisRepl = uno::Reference< io::XStream >(); + m_bStoreLoaded = sal_False; + + if ( bUseNew && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded + && m_nObjectState != embed::EmbedStates::LOADED ) + { + // the object replacement image should be updated, so the cached size as well + m_bHasCachedSize = sal_False; + try + { + // the call will cache the size in case of success + // probably it might need to be done earlier, while the object is in active state + getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + } + catch( uno::Exception& ) + {} + } + + aGuard.clear(); + if ( bUseNew ) + { + MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnSaveAsDone" ) ); + + // the object can be changed only on windows + // the notification should be done only if the object is not in loaded state + if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) + { + MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) ); + } + } +} + +//------------------------------------------------------ +sal_Bool SAL_CALL OleEmbeddedObject::hasEntry() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->hasEntry(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( m_xObjectStream.is() ) + return sal_True; + + return sal_False; +} + +//------------------------------------------------------ +::rtl::OUString SAL_CALL OleEmbeddedObject::getEntryName() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getEntryName(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + return m_aEntryName; +} + + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::storeOwn() + throw ( embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::storeOwn" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->storeOwn(); + return; + } + // end wrapping related part ==================== + + // during switching from Activated to Running and from Running to Loaded states the object will + // ask container to store the object, the container has to make decision + // to do so or not + + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't store object without persistence!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( m_bReadOnly ) + throw io::IOException(); // TODO: access denied + + LetCommonStoragePassBeUsed_Impl( m_xObjectStream ); + + sal_Bool bStoreLoaded = sal_True; + +#ifdef WNT + if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && m_pOleComponent->IsDirty() ) + { + bStoreLoaded = sal_False; + + OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!\n" ); + + if ( !m_xObjectStream.is() ) + throw io::IOException(); //TODO: access denied + + SetStreamMediaType_Impl( m_xObjectStream, ::rtl::OUString::createFromAscii( "application/vnd.sun.star.oleobject" ) ); + uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream(); + if ( !xOutStream.is() ) + throw io::IOException(); //TODO: access denied + + if ( m_bIsLink ) + { + // just let the link store itself + // in case visual repersentation must be stored also + // the procedure should be the same as for embedded objects + + uno::Reference< io::XOutputStream > xOutStream = GetStreamForSaving(); + + // should the component detect that it is a link??? + StoreObjectToStream( xOutStream ); + } + else + { + uno::Reference< io::XOutputStream > xOutStream = GetStreamForSaving(); + StoreObjectToStream( xOutStream ); + } + + // the replacement is changed probably, and it must be in the object stream + if ( !m_pOleComponent->IsWorkaroundActive() ) + m_xCachedVisualRepresentation = uno::Reference< io::XStream >(); + SetVisReplInStream( sal_True ); + } +#endif + + if ( m_bStoreVisRepl != HasVisReplInStream() ) + { + if ( m_bStoreVisRepl ) + { + // the m_xCachedVisualRepresentation must be set or it should be already stored + if ( m_xCachedVisualRepresentation.is() ) + InsertVisualCache_Impl( m_xObjectStream, m_xCachedVisualRepresentation ); + else + { + m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); + OSL_ENSURE( m_xCachedVisualRepresentation.is(), "No representation is available!" ); + } + } + else + { + if ( !m_xCachedVisualRepresentation.is() ) + m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); + RemoveVisualCache_Impl( m_xObjectStream ); + } + + SetVisReplInStream( m_bStoreVisRepl ); + } + + if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) + { + // the object replacement image should be updated, so the cached size as well + m_bHasCachedSize = sal_False; + try + { + // the call will cache the size in case of success + // probably it might need to be done earlier, while the object is in active state + getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ); + } + catch( uno::Exception& ) + {} + } + + aGuard.clear(); + + MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnSaveDone" ) ); + + // the object can be changed only on Windows + // the notification should be done only if the object is not in loaded state + if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded ) + MakeEventListenerNotification_Impl( ::rtl::OUString::createFromAscii( "OnVisAreaChanged" ) ); +} + +//------------------------------------------------------ +sal_Bool SAL_CALL OleEmbeddedObject::isReadonly() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->isReadonly(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + return m_bReadOnly; +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::reload( + const uno::Sequence< beans::PropertyValue >& lArguments, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->reload( lArguments, lObjArgs ); + return; + } + // end wrapping related part ==================== + + // TODO: use lObjArgs + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_nObjectState == -1 ) + { + // the object is still not loaded + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object persistence is not initialized!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + // TODO: + // throw away current document + // load new document from current storage + // use meaningfull part of lArguments +} + +//------------------------------------------------------ +void SAL_CALL OleEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->breakLink( xStorage, sEntName ); + return; + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + // TODO: The object must be at least in Running state; + if ( !m_bIsLink || m_nObjectState == -1 || !m_pOleComponent ) + { + // it must be a linked initialized object + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object is not a valid linked object!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + if ( m_bReadOnly ) + throw io::IOException(); // TODO: Access denied + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + +#ifdef WNT + if ( m_pOleComponent ) + { + // TODO: create an object based on the link + + // disconnect the old temporary URL + ::rtl::OUString aOldTempURL = m_aTempURL; + m_aTempURL = ::rtl::OUString(); + + OleComponent* pNewOleComponent = new OleComponent( m_xFactory, this ); + try { + pNewOleComponent->InitEmbeddedCopyOfLink( m_pOleComponent ); + } + catch ( uno::Exception& ) + { + delete pNewOleComponent; + if ( m_aTempURL ) + KillFile_Impl( m_aTempURL, m_xFactory ); + m_aTempURL = aOldTempURL; + throw; + } + + try { + GetRidOfComponent(); + } + catch( uno::Exception& ) + { + delete pNewOleComponent; + if ( m_aTempURL ) + KillFile_Impl( m_aTempURL, m_xFactory ); + m_aTempURL = aOldTempURL; + throw; + } + + KillFile_Impl( aOldTempURL, m_xFactory ); + + CreateOleComponent_Impl( pNewOleComponent ); + + if ( m_xParentStorage != xStorage || !m_aEntryName.equals( sEntName ) ) + SwitchOwnPersistence( xStorage, sEntName ); + + if ( m_nObjectState != embed::EmbedStates::LOADED ) + { + // TODO: should we activate the new object if the link was activated? + + sal_Int32 nTargetState = m_nObjectState; + m_nObjectState = embed::EmbedStates::LOADED; + + if ( m_nObjectState == embed::EmbedStates::RUNNING ) + m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed + else // m_nObjectState == embed::EmbedStates::ACTIVE + { + m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed + m_pOleComponent->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN ); + } + + m_nObjectState = nTargetState; + } + + m_bIsLink = sal_False; + m_aLinkURL = ::rtl::OUString(); + } + else +#endif + { + throw io::IOException(); //TODO: + } +} + +//------------------------------------------------------ +sal_Bool SAL_CALL OleEmbeddedObject::isLink() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->isLink(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + return m_bIsLink; +} + +//------------------------------------------------------ +::rtl::OUString SAL_CALL OleEmbeddedObject::getLinkURL() + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY ); + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getLinkURL(); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + if ( m_bWaitSaveCompleted ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object waits for saveCompleted() call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( !m_bIsLink ) + throw embed::WrongStateException( + ::rtl::OUString::createFromAscii( "The object is not a link object!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + // TODO: probably the link URL can be retrieved from OLE + + return m_aLinkURL; +} + diff --git a/embeddedobj/source/msole/oleregister.cxx b/embeddedobj/source/msole/oleregister.cxx new file mode 100644 index 000000000000..8df419752807 --- /dev/null +++ b/embeddedobj/source/msole/oleregister.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" + + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/registry/InvalidRegistryException.hpp> +#include <cppuhelper/factory.hxx> + +#include "xolefactory.hxx" +#include "xdialogcreator.hxx" + +using namespace ::com::sun::star; + + +extern "C" { + +void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +void * SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + ::rtl::OUString aImplName( ::rtl::OUString::createFromAscii( pImplName ) ); + uno::Reference< lang::XSingleServiceFactory > xFactory; + + if ( pServiceManager ) + { + if ( aImplName.equals( OleEmbeddedObjectFactory::impl_staticGetImplementationName() ) ) + { + xFactory= ::cppu::createOneInstanceFactory( reinterpret_cast< lang::XMultiServiceFactory*>( pServiceManager ), + OleEmbeddedObjectFactory::impl_staticGetImplementationName(), + OleEmbeddedObjectFactory::impl_staticCreateSelfInstance, + OleEmbeddedObjectFactory::impl_staticGetSupportedServiceNames() ); + } +#ifdef WNT + // the following service makes sence only on windows + else if ( aImplName.equals( MSOLEDialogObjectCreator::impl_staticGetImplementationName() ) ) + { + xFactory= ::cppu::createOneInstanceFactory( reinterpret_cast< lang::XMultiServiceFactory*>( pServiceManager ), + MSOLEDialogObjectCreator::impl_staticGetImplementationName(), + MSOLEDialogObjectCreator::impl_staticCreateSelfInstance, + MSOLEDialogObjectCreator::impl_staticGetSupportedServiceNames() ); + } +#endif + } + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + +sal_Bool SAL_CALL component_writeInfo( void * /*pServiceManager*/, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + uno::Reference< registry::XRegistryKey > xKey( reinterpret_cast< registry::XRegistryKey* >( pRegistryKey ) ); + uno::Reference< registry::XRegistryKey > xNewKey; + + xNewKey = xKey->createKey( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + + OleEmbeddedObjectFactory::impl_staticGetImplementationName() + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/UNO/SERVICES") ) ); + uno::Sequence< ::rtl::OUString > rServices = OleEmbeddedObjectFactory::impl_staticGetSupportedServiceNames(); + for( sal_Int32 ind = 0; ind < rServices.getLength(); ind++ ) + xNewKey->createKey( rServices.getConstArray()[ind] ); + +#ifdef WNT + // the following service makes sence only on windows + xNewKey = xKey->createKey( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + + MSOLEDialogObjectCreator::impl_staticGetImplementationName() + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/UNO/SERVICES") ) ); + rServices = MSOLEDialogObjectCreator::impl_staticGetSupportedServiceNames(); + for( sal_Int32 ind = 0; ind < rServices.getLength(); ind++ ) + xNewKey->createKey( rServices.getConstArray()[ind] ); +#endif + + return sal_True; + } + catch (registry::InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} + +} // extern "C" + diff --git a/embeddedobj/source/msole/olevisual.cxx b/embeddedobj/source/msole/olevisual.cxx new file mode 100644 index 000000000000..84461caa7ee3 --- /dev/null +++ b/embeddedobj/source/msole/olevisual.cxx @@ -0,0 +1,444 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/EmbedMapUnits.hpp> +#include <com/sun/star/embed/EmbedMisc.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> + +#include <rtl/logfile.hxx> + +#include <oleembobj.hxx> +#include <olecomponent.hxx> +#include <comphelper/mimeconfighelper.hxx> +#include <comphelper/seqstream.hxx> + +using namespace ::com::sun::star; +using namespace ::comphelper; + +embed::VisualRepresentation OleEmbeddedObject::GetVisualRepresentationInNativeFormat_Impl( + const uno::Reference< io::XStream > xCachedVisRepr ) + throw ( uno::Exception ) +{ + embed::VisualRepresentation aVisualRepr; + + // TODO: detect the format in the future for now use workaround + uno::Reference< io::XInputStream > xInStream = xCachedVisRepr->getInputStream(); + uno::Reference< io::XSeekable > xSeekable( xCachedVisRepr, uno::UNO_QUERY ); + if ( !xInStream.is() || !xSeekable.is() ) + throw uno::RuntimeException(); + + uno::Sequence< sal_Int8 > aSeq( 2 ); + xInStream->readBytes( aSeq, 2 ); + xSeekable->seek( 0 ); + if ( aSeq.getLength() == 2 && aSeq[0] == 'B' && aSeq[1] == 'M' ) + { + // it's a bitmap + aVisualRepr.Flavor = datatransfer::DataFlavor( + ::rtl::OUString::createFromAscii( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ), + ::rtl::OUString::createFromAscii( "Bitmap" ), + ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); + } + else + { + // it's a metafile + aVisualRepr.Flavor = datatransfer::DataFlavor( + ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), + ::rtl::OUString::createFromAscii( "Windows Metafile" ), + ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); + } + + sal_Int32 nStreamLength = (sal_Int32)xSeekable->getLength(); + uno::Sequence< sal_Int8 > aRepresent( nStreamLength ); + xInStream->readBytes( aRepresent, nStreamLength ); + aVisualRepr.Data <<= aRepresent; + + return aVisualRepr; +} + +void SAL_CALL OleEmbeddedObject::setVisualAreaSize( sal_Int64 nAspect, const awt::Size& aSize ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::setVisualAreaSize" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + xWrappedObject->setVisualAreaSize( nAspect, aSize ); + return; + } + // end wrapping related part ==================== + + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); + if ( nAspect == embed::Aspects::MSOLE_ICON ) + // no representation can be retrieved + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + +#ifdef WNT + // RECOMPOSE_ON_RESIZE misc flag means that the object has to be switched to running state on resize. + // SetExtent() is called only for objects that require it, + // it should not be called for MSWord documents to workaround problem i49369 + // If cached size is not set, that means that this is the size initialization, so there is no need to set the real size + sal_Bool bAllowToSetExtent = + ( ( getStatus( nAspect ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) + && !MimeConfigurationHelper::ClassIDsEqual( m_aClassID, MimeConfigurationHelper::GetSequenceClassID( 0x00020906L, 0x0000, 0x0000, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 ) ) + && m_bHasCachedSize ); + + if ( m_nObjectState == embed::EmbedStates::LOADED && bAllowToSetExtent ) + { + aGuard.clear(); + try { + changeState( embed::EmbedStates::RUNNING ); + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "The object should not be resized without activation!\n" ); + } + aGuard.reset(); + } + + if ( m_pOleComponent && m_nObjectState != embed::EmbedStates::LOADED && bAllowToSetExtent ) + { + awt::Size aSizeToSet = aSize; + aGuard.clear(); + try { + m_pOleComponent->SetExtent( aSizeToSet, nAspect ); // will throw an exception in case of failure + m_bHasSizeToSet = sal_False; + } + catch( uno::Exception& ) + { + // some objects do not allow to set the size even in running state + m_bHasSizeToSet = sal_True; + m_aSizeToSet = aSizeToSet; + m_nAspectToSet = nAspect; + } + aGuard.reset(); + } +#endif + + // cache the values + m_bHasCachedSize = sal_True; + m_aCachedSize = aSize; + m_nCachedAspect = nAspect; +} + +awt::Size SAL_CALL OleEmbeddedObject::getVisualAreaSize( sal_Int64 nAspect ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::getVisualAreaSize" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getVisualAreaSize( nAspect ); + } + // end wrapping related part ==================== + + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); + if ( nAspect == embed::Aspects::MSOLE_ICON ) + // no representation can be retrieved + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + awt::Size aResult; + +#ifdef WNT + // TODO/LATER: Support different aspects + if ( m_pOleComponent && !m_bHasSizeToSet && nAspect == embed::Aspects::MSOLE_CONTENT ) + { + try + { + // the cached size updated every time the object is stored + if ( m_bHasCachedSize ) + { + aResult = m_aCachedSize; + } + else + { + // there is no internal cache + awt::Size aSize; + aGuard.clear(); + + sal_Bool bSuccess = sal_False; + if ( getCurrentState() == embed::EmbedStates::LOADED ) + { + OSL_ENSURE( sal_False, "Loaded object has no cached size!\n" ); + + // try to switch the object to RUNNING state and request the value again + try { + changeState( embed::EmbedStates::RUNNING ); + } + catch( uno::Exception ) + { + throw embed::NoVisualAreaSizeException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + } + + try + { + // first try to get size using replacement image + aSize = m_pOleComponent->GetExtent( nAspect ); // will throw an exception in case of failure + bSuccess = sal_True; + } + catch( uno::Exception& ) + { + } + + if ( !bSuccess ) + { + try + { + // second try the cached replacement image + aSize = m_pOleComponent->GetCachedExtent( nAspect ); // will throw an exception in case of failure + bSuccess = sal_True; + } + catch( uno::Exception& ) + { + } + } + + if ( !bSuccess ) + { + try + { + // third try the size reported by the object + aSize = m_pOleComponent->GetReccomendedExtent( nAspect ); // will throw an exception in case of failure + bSuccess = sal_True; + } + catch( uno::Exception& ) + { + } + } + + if ( !bSuccess ) + throw embed::NoVisualAreaSizeException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + aGuard.reset(); + + m_aCachedSize = aSize; + m_nCachedAspect = nAspect; + m_bHasCachedSize = sal_True; + + aResult = m_aCachedSize; + } + } + catch ( embed::NoVisualAreaSizeException& ) + { + throw; + } + catch ( uno::Exception& ) + { + throw embed::NoVisualAreaSizeException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + } + else +#endif + { + // return cached value + if ( m_bHasCachedSize ) + { + OSL_ENSURE( nAspect == m_nCachedAspect, "Unexpected aspect is requested!\n" ); + aResult = m_aCachedSize; + } + else + { + throw embed::NoVisualAreaSizeException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No size available!\n" ) ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + } + + return aResult; +} + +embed::VisualRepresentation SAL_CALL OleEmbeddedObject::getPreferredVisualRepresentation( sal_Int64 nAspect ) + throw ( lang::IllegalArgumentException, + embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObject::getPreferredVisualRepresentation" ); + + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getPreferredVisualRepresentation( nAspect ); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); + if ( nAspect == embed::Aspects::MSOLE_ICON ) + // no representation can be retrieved + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + // TODO: if the object has cached representation then it should be returned + // TODO: if the object has no cached representation and is in loaded state it should switch itself to the running state + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + embed::VisualRepresentation aVisualRepr; + + // TODO: in case of different aspects they must be applied to the mediatype and XTransferable must be used + // the cache is used only as a fallback if object is not in loaded state + if ( !m_xCachedVisualRepresentation.is() && ( !m_bVisReplInitialized || m_bVisReplInStream ) + && m_nObjectState == embed::EmbedStates::LOADED ) + { + m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream, sal_True ); + SetVisReplInStream( m_xCachedVisualRepresentation.is() ); + } + + if ( m_xCachedVisualRepresentation.is() ) + { + return GetVisualRepresentationInNativeFormat_Impl( m_xCachedVisualRepresentation ); + } +#ifdef WNT + else if ( m_pOleComponent ) + { + try + { + if ( m_nObjectState == embed::EmbedStates::LOADED ) + changeState( embed::EmbedStates::RUNNING ); + + datatransfer::DataFlavor aDataFlavor( + ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), + ::rtl::OUString::createFromAscii( "Windows Metafile" ), + ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); + + aVisualRepr.Data = m_pOleComponent->getTransferData( aDataFlavor ); + aVisualRepr.Flavor = aDataFlavor; + + uno::Sequence< sal_Int8 > aVisReplSeq; + aVisualRepr.Data >>= aVisReplSeq; + if ( aVisReplSeq.getLength() ) + { + m_xCachedVisualRepresentation = GetNewFilledTempStream_Impl( + uno::Reference< io::XInputStream > ( static_cast< io::XInputStream* > ( + new ::comphelper::SequenceInputStream( aVisReplSeq ) ) ) ); + } + + return aVisualRepr; + } + catch( uno::Exception& ) + {} + } +#endif + + // the cache is used only as a fallback if object is not in loaded state + if ( !m_xCachedVisualRepresentation.is() && ( !m_bVisReplInitialized || m_bVisReplInStream ) ) + { + m_xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( m_xObjectStream ); + SetVisReplInStream( m_xCachedVisualRepresentation.is() ); + } + + if ( !m_xCachedVisualRepresentation.is() ) + { + // no representation can be retrieved + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + } + + return GetVisualRepresentationInNativeFormat_Impl( m_xCachedVisualRepresentation ); +} + +sal_Int32 SAL_CALL OleEmbeddedObject::getMapUnit( sal_Int64 nAspect ) + throw ( uno::Exception, + uno::RuntimeException) +{ + // begin wrapping related part ==================== + uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject; + if ( xWrappedObject.is() ) + { + // the object was converted to OOo embedded object, the current implementation is now only a wrapper + return xWrappedObject->getMapUnit( nAspect ); + } + // end wrapping related part ==================== + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bDisposed ) + throw lang::DisposedException(); // TODO + + OSL_ENSURE( nAspect != embed::Aspects::MSOLE_ICON, "For iconified objects no graphical replacement is required!\n" ); + if ( nAspect == embed::Aspects::MSOLE_ICON ) + // no representation can be retrieved + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Illegal call!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + if ( m_nObjectState == -1 ) + throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "The object is not loaded!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ) ); + + return embed::EmbedMapUnits::ONE_100TH_MM; +} + + diff --git a/embeddedobj/source/msole/olewrapclient.cxx b/embeddedobj/source/msole/olewrapclient.cxx new file mode 100644 index 000000000000..6538c793c194 --- /dev/null +++ b/embeddedobj/source/msole/olewrapclient.cxx @@ -0,0 +1,158 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" + +#include <osl/diagnose.h> + +#include "olewrapclient.hxx" +#include "olecomponent.hxx" + +// TODO: May be a mutex must be introduced + +OleWrapperClientSite::OleWrapperClientSite( OleComponent* pOleComp ) +: m_nRefCount( 0 ) +, m_pOleComp( pOleComp ) +{ + OSL_ENSURE( m_pOleComp, "No ole component is provided!\n" ); +} + +OleWrapperClientSite::~OleWrapperClientSite() +{ +} + +STDMETHODIMP OleWrapperClientSite::QueryInterface( REFIID riid , void** ppv ) +{ + *ppv=NULL; + + if ( riid == IID_IUnknown ) + *ppv = (IUnknown*)this; + + if ( riid == IID_IOleClientSite ) + *ppv = (IOleClientSite*)this; + + if ( *ppv != NULL ) + { + ((IUnknown*)*ppv)->AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) OleWrapperClientSite::AddRef() +{ + return osl_incrementInterlockedCount( &m_nRefCount); +} + +STDMETHODIMP_(ULONG) OleWrapperClientSite::Release() +{ + ULONG nReturn = --m_nRefCount; + if ( m_nRefCount == 0 ) + delete this; + + return nReturn; +} + +void OleWrapperClientSite::disconnectOleComponent() +{ + // must not be called from the descructor of OleComponent!!! + osl::MutexGuard aGuard( m_aMutex ); + m_pOleComp = NULL; +} + +STDMETHODIMP OleWrapperClientSite::SaveObject() +{ + OleComponent* pLockComponent = NULL; + HRESULT hResult = E_FAIL; + + { + osl::MutexGuard aGuard( m_aMutex ); + if ( m_pOleComp ) + { + pLockComponent = m_pOleComp; + pLockComponent->acquire(); + } + } + + if ( pLockComponent ) + { + if ( pLockComponent->SaveObject_Impl() ) + hResult = S_OK; + + pLockComponent->release(); + } + + return hResult; +} + +STDMETHODIMP OleWrapperClientSite::GetMoniker( DWORD, DWORD, LPMONIKER *ppmk ) +{ + *ppmk = NULL; + return E_NOTIMPL; +} + +STDMETHODIMP OleWrapperClientSite::GetContainer( LPOLECONTAINER* ppContainer ) +{ + *ppContainer = NULL; + return E_NOTIMPL; +} + +STDMETHODIMP OleWrapperClientSite::ShowObject(void) +{ + return S_OK; +} + +STDMETHODIMP OleWrapperClientSite::OnShowWindow( BOOL bShow ) +{ + OleComponent* pLockComponent = NULL; + + // TODO/LATER: redirect the notification to the main thread so that SolarMutex can be locked + { + osl::MutexGuard aGuard( m_aMutex ); + if ( m_pOleComp ) + { + pLockComponent = m_pOleComp; + pLockComponent->acquire(); + } + } + + if ( pLockComponent ) + { + pLockComponent->OnShowWindow_Impl( bShow ); // the result is not interesting + pLockComponent->release(); + } + + return S_OK; +} + +STDMETHODIMP OleWrapperClientSite::RequestNewObjectLayout(void) +{ + return E_NOTIMPL; +} + diff --git a/embeddedobj/source/msole/olewrapclient.hxx b/embeddedobj/source/msole/olewrapclient.hxx new file mode 100644 index 000000000000..14bf28780f8b --- /dev/null +++ b/embeddedobj/source/msole/olewrapclient.hxx @@ -0,0 +1,56 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <osl/interlck.h> +#include <osl/mutex.hxx> +#include <platform.h> + +class OleComponent; +class OleWrapperClientSite : public IOleClientSite +{ + osl::Mutex m_aMutex; + oslInterlockedCount m_nRefCount; + OleComponent* m_pOleComp; + +public: + OleWrapperClientSite( OleComponent* pOleComp ); + virtual ~OleWrapperClientSite(void); + + void disconnectOleComponent(); + + STDMETHODIMP QueryInterface(REFIID, void**); + STDMETHODIMP_(ULONG) AddRef(void); + STDMETHODIMP_(ULONG) Release(void); + + STDMETHODIMP SaveObject(void); + STDMETHODIMP GetMoniker(DWORD, DWORD, LPMONIKER *); + STDMETHODIMP GetContainer(LPOLECONTAINER *); + STDMETHODIMP ShowObject(void); + STDMETHODIMP OnShowWindow(BOOL); + STDMETHODIMP RequestNewObjectLayout(void); +}; + diff --git a/embeddedobj/source/msole/ownview.cxx b/embeddedobj/source/msole/ownview.cxx new file mode 100644 index 000000000000..9de41cfa2def --- /dev/null +++ b/embeddedobj/source/msole/ownview.cxx @@ -0,0 +1,665 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/embed/XClassifiedObject.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTBRODCASTER_HPP_ +#include <com/sun/star/document/XEventBroadcaster.hpp> +#endif +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/document/XTypeDetection.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <cppuhelper/implbase1.hxx> +#include <comphelper/storagehelper.hxx> +#include <comphelper/mimeconfighelper.hxx> + +#include "ownview.hxx" + + +using namespace ::com::sun::star; +using namespace ::comphelper; + +::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException ); +::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException ); +sal_Bool KillFile_Impl( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory ); +uno::Reference< io::XStream > TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw ( uno::Exception ); + +//======================================================== +// Dummy interaction handler +//======================================================== +//-------------------------------------------------------- +class DummyHandler_Impl : public ::cppu::WeakImplHelper1< task::XInteractionHandler > +{ +public: + DummyHandler_Impl() {} + ~DummyHandler_Impl(); + + virtual void SAL_CALL handle( const uno::Reference< task::XInteractionRequest >& xRequest ) + throw( uno::RuntimeException ); +}; + +//-------------------------------------------------------- +DummyHandler_Impl::~DummyHandler_Impl() +{ +} + +//-------------------------------------------------------- +void SAL_CALL DummyHandler_Impl::handle( const uno::Reference< task::XInteractionRequest >& ) + throw( uno::RuntimeException ) +{ + return; +} + +//======================================================== +// Object viewer +//======================================================== +//-------------------------------------------------------- +OwnView_Impl::OwnView_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory, + const uno::Reference< io::XInputStream >& xInputStream ) +: m_xFactory( xFactory ) +, m_bBusy( sal_False ) +, m_bUseNative( sal_False ) +{ + if ( !xFactory.is() || !xInputStream.is() ) + throw uno::RuntimeException(); + + m_aTempFileURL = GetNewFilledTempFile_Impl( xInputStream, m_xFactory ); +} + +//-------------------------------------------------------- +OwnView_Impl::~OwnView_Impl() +{ + try { + KillFile_Impl( m_aTempFileURL, m_xFactory ); + } catch( uno::Exception& ) {} + + try { + if ( m_aNativeTempURL.getLength() ) + KillFile_Impl( m_aNativeTempURL, m_xFactory ); + } catch( uno::Exception& ) {} +} + +//-------------------------------------------------------- +sal_Bool OwnView_Impl::CreateModelFromURL( const ::rtl::OUString& aFileURL ) +{ + sal_Bool bResult = sal_False; + + if ( aFileURL.getLength() ) + { + try { + uno::Reference < frame::XComponentLoader > xDocumentLoader( + m_xFactory->createInstance ( + ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), + uno::UNO_QUERY ); + + if ( xDocumentLoader.is() ) + { + uno::Sequence< beans::PropertyValue > aArgs( m_aFilterName.getLength() ? 5 : 4 ); + + aArgs[0].Name = ::rtl::OUString::createFromAscii( "URL" ); + aArgs[0].Value <<= aFileURL; + + aArgs[1].Name = ::rtl::OUString::createFromAscii( "ReadOnly" ); + aArgs[1].Value <<= sal_True; + + aArgs[2].Name = ::rtl::OUString::createFromAscii( "InteractionHandler" ); + aArgs[2].Value <<= uno::Reference< task::XInteractionHandler >( + static_cast< ::cppu::OWeakObject* >( new DummyHandler_Impl() ), uno::UNO_QUERY ); + + aArgs[3].Name = ::rtl::OUString::createFromAscii( "DontEdit" ); + aArgs[3].Value <<= sal_True; + + if ( m_aFilterName.getLength() ) + { + aArgs[4].Name = ::rtl::OUString::createFromAscii( "FilterName" ); + aArgs[4].Value <<= m_aFilterName; + } + + uno::Reference< frame::XModel > xModel( xDocumentLoader->loadComponentFromURL( + aFileURL, + ::rtl::OUString::createFromAscii( "_blank" ), + 0, + aArgs ), + uno::UNO_QUERY ); + + if ( xModel.is() ) + { + uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY ); + if ( xBroadCaster.is() ) + xBroadCaster->addEventListener( uno::Reference< document::XEventListener >( + static_cast< ::cppu::OWeakObject* >( this ), + uno::UNO_QUERY ) ); + + uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY ); + if ( xCloseable.is() ) + { + xCloseable->addCloseListener( uno::Reference< util::XCloseListener >( + static_cast< ::cppu::OWeakObject* >( this ), + uno::UNO_QUERY ) ); + + ::osl::MutexGuard aGuard( m_aMutex ); + m_xModel = xModel; + bResult = sal_True; + } + } + } + } + catch( uno::Exception& ) + { + } + } + + return bResult; +} + +//-------------------------------------------------------- +sal_Bool OwnView_Impl::CreateModel( sal_Bool bUseNative ) +{ + sal_Bool bResult = sal_False; + + try { + bResult = CreateModelFromURL( bUseNative ? m_aNativeTempURL : m_aTempFileURL ); + } + catch( uno::Exception& ) + { + } + + return bResult; +} + +//-------------------------------------------------------- +::rtl::OUString OwnView_Impl::GetFilterNameFromExtentionAndInStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory, + const ::rtl::OUString& aNameWithExtention, + const uno::Reference< io::XInputStream >& xInputStream ) +{ + if ( !xInputStream.is() ) + throw uno::RuntimeException(); + + uno::Reference< document::XTypeDetection > xTypeDetection( + xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" ) ), + uno::UNO_QUERY_THROW ); + + ::rtl::OUString aTypeName; + + if ( aNameWithExtention.getLength() ) + { + ::rtl::OUString aURLToAnalyze = + ( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "file:///" ) ) + aNameWithExtention ); + aTypeName = xTypeDetection->queryTypeByURL( aURLToAnalyze ); + } + + uno::Sequence< beans::PropertyValue > aArgs( aTypeName.getLength() ? 3 : 2 ); + aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); + aArgs[0].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:stream" ) ); + aArgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "InputStream" ) ); + aArgs[1].Value <<= xInputStream; + if ( aTypeName.getLength() ) + { + aArgs[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TypeName" ) ); + aArgs[2].Value <<= aTypeName; + } + + aTypeName = xTypeDetection->queryTypeByDescriptor( aArgs, sal_True ); + + ::rtl::OUString aFilterName; + for ( sal_Int32 nInd = 0; nInd < aArgs.getLength(); nInd++ ) + if ( aArgs[nInd].Name.equalsAscii( "FilterName" ) ) + aArgs[nInd].Value >>= aFilterName; + + if ( !aFilterName.getLength() && aTypeName.getLength() ) + { + // get the default filter name for the type + uno::Reference< container::XNameAccess > xNameAccess( xTypeDetection, uno::UNO_QUERY_THROW ); + uno::Sequence< beans::PropertyValue > aTypes; + + if ( xNameAccess.is() && ( xNameAccess->getByName( aTypeName ) >>= aTypes ) ) + { + for ( sal_Int32 nInd = 0; nInd < aTypes.getLength(); nInd++ ) + { + if ( aTypes[nInd].Name.equalsAscii( "PreferredFilter" ) && ( aTypes[nInd].Value >>= aFilterName ) ) + { + aTypes[nInd].Value >>= aFilterName; + break; + } + } + } + } + + return aFilterName; +} + +//-------------------------------------------------------- +sal_Bool OwnView_Impl::ReadContentsAndGenerateTempFile( const uno::Reference< io::XInputStream >& xInStream, + sal_Bool bParseHeader ) +{ + uno::Reference< io::XSeekable > xSeekable( xInStream, uno::UNO_QUERY_THROW ); + xSeekable->seek( 0 ); + + // create m_aNativeTempURL + ::rtl::OUString aNativeTempURL; + uno::Reference < beans::XPropertySet > xNativeTempFile( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY_THROW ); + uno::Reference < io::XStream > xNativeTempStream( xNativeTempFile, uno::UNO_QUERY_THROW ); + uno::Reference < io::XOutputStream > xNativeOutTemp = xNativeTempStream->getOutputStream(); + uno::Reference < io::XInputStream > xNativeInTemp = xNativeTempStream->getInputStream(); + if ( !xNativeOutTemp.is() || !xNativeInTemp.is() ) + throw uno::RuntimeException(); + + try { + xNativeTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) ); + uno::Any aUrl = xNativeTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); + aUrl >>= aNativeTempURL; + } + catch ( uno::Exception& ) + { + } + + sal_Bool bFailed = sal_False; + ::rtl::OUString aFileSuffix; + + if ( bParseHeader ) + { + uno::Sequence< sal_Int8 > aReadSeq( 4 ); + // read the complete size of the Object Package + if ( xInStream->readBytes( aReadSeq, 4 ) != 4 ) + return sal_False; +/* + sal_uInt32 nLength = (sal_uInt8)aReadSeq[0] + + (sal_uInt8)aReadSeq[1] * 0x100 + + (sal_uInt8)aReadSeq[2] * 0x10000 + + (sal_uInt8)aReadSeq[3] * 0x1000000; +*/ + // read the first header ( have no idea what does this header mean ) + if ( xInStream->readBytes( aReadSeq, 2 ) != 2 || aReadSeq[0] != 2 || aReadSeq[1] != 0 ) + return sal_False; + + // read file name + // only extension is interesting so only subset of symbols is accepted + do + { + if ( xInStream->readBytes( aReadSeq, 1 ) != 1 ) + return sal_False; + + if ( + (aReadSeq[0] >= '0' && aReadSeq[0] <= '9') || + (aReadSeq[0] >= 'a' && aReadSeq[0] <= 'z') || + (aReadSeq[0] >= 'A' && aReadSeq[0] <= 'Z') || + aReadSeq[0] == '.' + ) + { + aFileSuffix += ::rtl::OUString::valueOf( (sal_Unicode) aReadSeq[0] ); + } + + } while( aReadSeq[0] ); + + // skip url + do + { + if ( xInStream->readBytes( aReadSeq, 1 ) != 1 ) + return sal_False; + } while( aReadSeq[0] ); + + // check the next header + if ( xInStream->readBytes( aReadSeq, 4 ) != 4 + || aReadSeq[0] || aReadSeq[1] || aReadSeq[2] != 3 || aReadSeq[3] ) + return sal_False; + + // get the size of the next entry + if ( xInStream->readBytes( aReadSeq, 4 ) != 4 ) + return sal_False; + + sal_uInt32 nUrlSize = (sal_uInt8)aReadSeq[0] + + (sal_uInt8)aReadSeq[1] * 0x100 + + (sal_uInt8)aReadSeq[2] * 0x10000 + + (sal_uInt8)aReadSeq[3] * 0x1000000; + sal_Int64 nTargetPos = xSeekable->getPosition() + nUrlSize; + + xSeekable->seek( nTargetPos ); + + // get the size of stored data + if ( xInStream->readBytes( aReadSeq, 4 ) != 4 ) + return sal_False; + + sal_uInt32 nDataSize = (sal_uInt8)aReadSeq[0] + + (sal_uInt8)aReadSeq[1] * 0x100 + + (sal_uInt8)aReadSeq[2] * 0x10000 + + (sal_uInt8)aReadSeq[3] * 0x1000000; + + aReadSeq.realloc( 32000 ); + sal_uInt32 nRead = 0; + while ( nRead < nDataSize ) + { + sal_uInt32 nToRead = ( nDataSize - nRead > 32000 ) ? 32000 : nDataSize - nRead; + sal_uInt32 nLocalRead = xInStream->readBytes( aReadSeq, nToRead ); + + + if ( !nLocalRead ) + { + bFailed = sal_True; + break; + } + else if ( nLocalRead == 32000 ) + xNativeOutTemp->writeBytes( aReadSeq ); + else + { + uno::Sequence< sal_Int8 > aToWrite( aReadSeq ); + aToWrite.realloc( nLocalRead ); + xNativeOutTemp->writeBytes( aToWrite ); + } + + nRead += nLocalRead; + } + } + else + { + uno::Sequence< sal_Int8 > aData( 8 ); + if ( xInStream->readBytes( aData, 8 ) == 8 + && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 + && ( aData[4] == 2 || aData[4] == 3 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 ) + { + // the header has to be removed + xSeekable->seek( 40 ); + } + else + { + // the usual Ole10Native format + xSeekable->seek( 4 ); + } + + ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xNativeOutTemp ); + } + + xNativeOutTemp->closeOutput(); + + // The temporary native file is created, now the filter must be detected + if ( !bFailed ) + { + m_aFilterName = GetFilterNameFromExtentionAndInStream( m_xFactory, aFileSuffix, xNativeInTemp ); + m_aNativeTempURL = aNativeTempURL; + } + + return !bFailed; +} + +//-------------------------------------------------------- +void OwnView_Impl::CreateNative() +{ + if ( m_aNativeTempURL.getLength() ) + return; + + try + { + uno::Reference < ucb::XSimpleFileAccess > xAccess( + m_xFactory->createInstance ( + ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), + uno::UNO_QUERY_THROW ); + + uno::Reference< io::XInputStream > xInStream = xAccess->openFileRead( m_aTempFileURL ); + if ( !xInStream.is() ) + throw uno::RuntimeException(); + + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[0] <<= xInStream; + uno::Reference< container::XNameAccess > xNameAccess( + m_xFactory->createInstanceWithArguments( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLESimpleStorage" ), + aArgs ), + uno::UNO_QUERY_THROW ); + + ::rtl::OUString aSubStreamName = ::rtl::OUString::createFromAscii( "\1Ole10Native" ); + uno::Reference< embed::XClassifiedObject > xStor( xNameAccess, uno::UNO_QUERY_THROW ); + uno::Sequence< sal_Int8 > aStorClassID = xStor->getClassID(); + + if ( xNameAccess->hasByName( aSubStreamName ) ) + { + sal_uInt8 aClassID[] = + { 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }; + uno::Sequence< sal_Int8 > aPackageClassID( (sal_Int8*)aClassID, 16 ); + + uno::Reference< io::XStream > xSubStream; + xNameAccess->getByName( aSubStreamName ) >>= xSubStream; + if ( xSubStream.is() ) + { + sal_Bool bOk = sal_False; + + if ( MimeConfigurationHelper::ClassIDsEqual( aPackageClassID, aStorClassID ) ) + { + // the storage represents Object Package + + bOk = ReadContentsAndGenerateTempFile( xSubStream->getInputStream(), sal_True ); + + if ( !bOk && m_aNativeTempURL.getLength() ) + { + KillFile_Impl( m_aNativeTempURL, m_xFactory ); + m_aNativeTempURL = ::rtl::OUString(); + } + } + + if ( !bOk ) + { + bOk = ReadContentsAndGenerateTempFile( xSubStream->getInputStream(), sal_False ); + + if ( !bOk && m_aNativeTempURL.getLength() ) + { + KillFile_Impl( m_aNativeTempURL, m_xFactory ); + m_aNativeTempURL = ::rtl::OUString(); + } + } + } + } + else + { + // TODO/LATER: No native stream, needs a new solution + } + } + catch( uno::Exception& ) + {} +} + +//-------------------------------------------------------- +sal_Bool OwnView_Impl::Open() +{ + sal_Bool bResult = sal_False; + + uno::Reference< frame::XModel > xExistingModel; + + { + ::osl::MutexGuard aGuard( m_aMutex ); + xExistingModel = m_xModel; + if ( m_bBusy ) + return sal_False; + + m_bBusy = sal_True; + } + + if ( xExistingModel.is() ) + { + try { + uno::Reference< frame::XController > xController = xExistingModel->getCurrentController(); + if ( xController.is() ) + { + uno::Reference< frame::XFrame > xFrame = xController->getFrame(); + if ( xFrame.is() ) + { + xFrame->activate(); + uno::Reference<awt::XTopWindow> xTopWindow( xFrame->getContainerWindow(), uno::UNO_QUERY ); + if(xTopWindow.is()) + xTopWindow->toFront(); + + bResult = sal_True; + } + } + } + catch( uno::Exception& ) + { + } + } + else + { + bResult = CreateModel( m_bUseNative ); + + if ( !bResult && !m_bUseNative ) + { + // the original storage can not be recognized + if ( !m_aNativeTempURL.getLength() ) + { + // create a temporary file for the native representation if there is no + CreateNative(); + } + + if ( m_aNativeTempURL.getLength() ) + { + bResult = CreateModel( sal_True ); + if ( bResult ) + m_bUseNative = sal_True; + } + } + } + + m_bBusy = sal_False; + + return bResult; +} + +//-------------------------------------------------------- +void OwnView_Impl::Close() +{ + uno::Reference< frame::XModel > xModel; + + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xModel.is() ) + return; + xModel = m_xModel; + m_xModel = uno::Reference< frame::XModel >(); + + if ( m_bBusy ) + return; + + m_bBusy = sal_True; + } + + try { + uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY ); + if ( xBroadCaster.is() ) + xBroadCaster->removeEventListener( uno::Reference< document::XEventListener >( + static_cast< ::cppu::OWeakObject* >( this ), + uno::UNO_QUERY ) ); + + uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY ); + if ( xCloseable.is() ) + { + xCloseable->removeCloseListener( uno::Reference< util::XCloseListener >( + static_cast< ::cppu::OWeakObject* >( this ), + uno::UNO_QUERY ) ); + xCloseable->close( sal_True ); + } + } + catch( uno::Exception& ) + {} + + m_bBusy = sal_False; +} + +//-------------------------------------------------------- +void SAL_CALL OwnView_Impl::notifyEvent( const document::EventObject& aEvent ) + throw ( uno::RuntimeException ) +{ + + uno::Reference< frame::XModel > xModel; + + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( aEvent.Source == m_xModel && aEvent.EventName.equalsAscii( "OnSaveAsDone" ) ) + { + // SaveAs operation took place, so just forget the model and deregister listeners + xModel = m_xModel; + m_xModel = uno::Reference< frame::XModel >(); + } + } + + if ( xModel.is() ) + { + try { + uno::Reference< document::XEventBroadcaster > xBroadCaster( xModel, uno::UNO_QUERY ); + if ( xBroadCaster.is() ) + xBroadCaster->removeEventListener( uno::Reference< document::XEventListener >( + static_cast< ::cppu::OWeakObject* >( this ), + uno::UNO_QUERY ) ); + + uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY ); + if ( xCloseable.is() ) + xCloseable->removeCloseListener( uno::Reference< util::XCloseListener >( + static_cast< ::cppu::OWeakObject* >( this ), + uno::UNO_QUERY ) ); + } + catch( uno::Exception& ) + {} + } +} + +//-------------------------------------------------------- +void SAL_CALL OwnView_Impl::queryClosing( const lang::EventObject&, sal_Bool ) + throw ( util::CloseVetoException, + uno::RuntimeException ) +{ +} + +//-------------------------------------------------------- +void SAL_CALL OwnView_Impl::notifyClosing( const lang::EventObject& Source ) + throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( Source.Source == m_xModel ) + m_xModel = uno::Reference< frame::XModel >(); +} + +//-------------------------------------------------------- +void SAL_CALL OwnView_Impl::disposing( const lang::EventObject& Source ) + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( Source.Source == m_xModel ) + m_xModel = uno::Reference< frame::XModel >(); +}; + diff --git a/embeddedobj/source/msole/ownview.hxx b/embeddedobj/source/msole/ownview.hxx new file mode 100644 index 000000000000..c8fd7951c548 --- /dev/null +++ b/embeddedobj/source/msole/ownview.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __OWNVIEW_HXX_ +#define __OWNVIEW_HXX_ + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/util/XCloseListener.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <cppuhelper/implbase2.hxx> + +#include <osl/mutex.hxx> + +class OwnView_Impl : public ::cppu::WeakImplHelper2 < ::com::sun::star::util::XCloseListener, + ::com::sun::star::document::XEventListener > +{ + ::osl::Mutex m_aMutex; + + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > m_xModel; + + ::rtl::OUString m_aTempFileURL; + ::rtl::OUString m_aNativeTempURL; + + ::rtl::OUString m_aFilterName; + + sal_Bool m_bBusy; + + sal_Bool m_bUseNative; + +private: + sal_Bool CreateModelFromURL( const ::rtl::OUString& aFileURL ); + + sal_Bool CreateModel( sal_Bool bUseNative ); + + sal_Bool ReadContentsAndGenerateTempFile( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xStream, sal_Bool bParseHeader ); + + void CreateNative(); + +public: + static ::rtl::OUString GetFilterNameFromExtentionAndInStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory, + const ::rtl::OUString& aNameWithExtention, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xInputStream ); + + OwnView_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xStream ); + virtual ~OwnView_Impl(); + + sal_Bool Open(); + + void Close(); + + virtual void SAL_CALL notifyEvent( const ::com::sun::star::document::EventObject& Event ) throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL queryClosing( const ::com::sun::star::lang::EventObject& Source, sal_Bool GetsOwnership ) throw (::com::sun::star::util::CloseVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL notifyClosing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); +}; + +#endif + diff --git a/embeddedobj/source/msole/platform.h b/embeddedobj/source/msole/platform.h new file mode 100644 index 000000000000..b64d9d5749d3 --- /dev/null +++ b/embeddedobj/source/msole/platform.h @@ -0,0 +1,49 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ + +#define STRICT +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif +#define _ATL_APARTMENT_THREADED + +#if defined _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable: 4548 4555 4917) +#endif + +#include "windows.h" + +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif + diff --git a/embeddedobj/source/msole/xdialogcreator.cxx b/embeddedobj/source/msole/xdialogcreator.cxx new file mode 100644 index 000000000000..17b331f8bff9 --- /dev/null +++ b/embeddedobj/source/msole/xdialogcreator.cxx @@ -0,0 +1,385 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" +#include <com/sun/star/embed/XEmbedObjectCreator.hpp> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/embed/EntryInitModes.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> + + +#include <osl/thread.h> +#include <osl/file.hxx> +#include <vos/module.hxx> +#include <comphelper/classids.hxx> + +#include "platform.h" +#include <comphelper/mimeconfighelper.hxx> + +#include "xdialogcreator.hxx" +#include "oleembobj.hxx" +// LLA: tip from FS +// #include <confighelper.hxx> +#include <xdialogcreator.hxx> +#include <oleembobj.hxx> + + +#ifdef WNT + +#include <oledlg.h> + +class InitializedOleGuard +{ +public: + InitializedOleGuard() + { + if ( !SUCCEEDED( OleInitialize( NULL ) ) ) + throw ::com::sun::star::uno::RuntimeException(); + } + + ~InitializedOleGuard() + { + OleUninitialize(); + } +}; + +extern "C" { +typedef UINT STDAPICALLTYPE OleUIInsertObjectA_Type(LPOLEUIINSERTOBJECTA); +} + +#endif + + +using namespace ::com::sun::star; +using namespace ::comphelper; +//------------------------------------------------------------------------- +uno::Sequence< sal_Int8 > GetRelatedInternalID_Impl( const uno::Sequence< sal_Int8 >& aClassID ) +{ + // Writer + if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_60 ) ) + || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_8 ) ) ) + return MimeConfigurationHelper::GetSequenceClassID( SO3_SW_CLASSID_60 ); + + // Calc + if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_60 ) ) + || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_8 ) ) ) + return MimeConfigurationHelper::GetSequenceClassID( SO3_SC_CLASSID_60 ); + + // Impress + if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 ) ) + || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) ) ) + return MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_CLASSID_60 ); + + // Draw + if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_60 ) ) + || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) ) ) + return MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_CLASSID_60 ); + + // Chart + if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_60 ) ) + || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_8 ) ) ) + return MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_CLASSID_60 ); + + // Math + if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_60 ) ) + || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_8 ) ) ) + return MimeConfigurationHelper::GetSequenceClassID( SO3_SM_CLASSID_60 ); + + return aClassID; +} + +//------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL MSOLEDialogObjectCreator::impl_staticGetSupportedServiceNames() +{ + uno::Sequence< ::rtl::OUString > aRet(2); + aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.MSOLEObjectSystemCreator"); + aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.MSOLEObjectSystemCreator"); + return aRet; +} + +//------------------------------------------------------------------------- +::rtl::OUString SAL_CALL MSOLEDialogObjectCreator::impl_staticGetImplementationName() +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.MSOLEObjectSystemCreator"); +} + +//------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL MSOLEDialogObjectCreator::impl_staticCreateSelfInstance( + const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) +{ + return uno::Reference< uno::XInterface >( *new MSOLEDialogObjectCreator( xServiceManager ) ); +} + +//------------------------------------------------------------------------- +embed::InsertedObjectInfo SAL_CALL MSOLEDialogObjectCreator::createInstanceByDialog( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& aInObjArgs ) + throw ( lang::IllegalArgumentException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + embed::InsertedObjectInfo aObjectInfo; + uno::Sequence< beans::PropertyValue > aObjArgs( aInObjArgs ); + +#ifdef WNT + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + InitializedOleGuard aGuard; + + OLEUIINSERTOBJECT io; + char szFile[MAX_PATH]; + UINT uTemp; + + memset(&io, 0, sizeof(io)); + + io.cbStruct = sizeof(io); + io.hWndOwner = GetActiveWindow(); + + szFile[0] = 0; + io.lpszFile = szFile; + io.cchFile = MAX_PATH; + + io.dwFlags = IOF_SELECTCREATENEW | IOF_DISABLELINK; + + + ::vos::OModule aOleDlgLib; + if( !aOleDlgLib.load( ::rtl::OUString::createFromAscii( "oledlg" ) ) ) + throw uno::RuntimeException(); + + OleUIInsertObjectA_Type * pInsertFct = (OleUIInsertObjectA_Type *) + aOleDlgLib.getSymbol( ::rtl::OUString::createFromAscii( "OleUIInsertObjectA" ) ); + if( !pInsertFct ) + throw uno::RuntimeException(); + + uTemp=pInsertFct(&io); + + if ( OLEUI_OK == uTemp ) + { + if (io.dwFlags & IOF_SELECTCREATENEW) + { + uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( + m_xFactory->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.EmbeddedObjectCreator" ) ), + uno::UNO_QUERY ); + if ( !xEmbCreator.is() ) + throw uno::RuntimeException(); + + uno::Sequence< sal_Int8 > aClassID = MimeConfigurationHelper::GetSequenceClassID( io.clsid.Data1, + io.clsid.Data2, + io.clsid.Data3, + io.clsid.Data4[0], + io.clsid.Data4[1], + io.clsid.Data4[2], + io.clsid.Data4[3], + io.clsid.Data4[4], + io.clsid.Data4[5], + io.clsid.Data4[6], + io.clsid.Data4[7] ); + + aClassID = GetRelatedInternalID_Impl( aClassID ); + + //TODO: retrieve ClassName + ::rtl::OUString aClassName; + aObjectInfo.Object = uno::Reference< embed::XEmbeddedObject >( + xEmbCreator->createInstanceInitNew( aClassID, aClassName, xStorage, sEntName, aObjArgs ), + uno::UNO_QUERY ); + } + else + { + ::rtl::OUString aFileName = ::rtl::OStringToOUString( ::rtl::OString( szFile ), osl_getThreadTextEncoding() ); + rtl::OUString aFileURL; + if ( osl::FileBase::getFileURLFromSystemPath( aFileName, aFileURL ) != osl::FileBase::E_None ) + throw uno::RuntimeException(); + + uno::Sequence< beans::PropertyValue > aMediaDescr( 1 ); + aMediaDescr[0].Name = ::rtl::OUString::createFromAscii( "URL" ); + aMediaDescr[0].Value <<= aFileURL; + + // TODO: use config helper for type detection + uno::Reference< embed::XEmbedObjectCreator > xEmbCreator; + ::comphelper::MimeConfigurationHelper aHelper( m_xFactory ); + + if ( aHelper.AddFilterNameCheckOwnFile( aMediaDescr ) ) + xEmbCreator = uno::Reference< embed::XEmbedObjectCreator >( + m_xFactory->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.EmbeddedObjectCreator" ) ), + uno::UNO_QUERY ); + else + xEmbCreator = uno::Reference< embed::XEmbedObjectCreator >( + m_xFactory->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.OLEEmbeddedObjectFactory" ) ), + uno::UNO_QUERY ); + + if ( !xEmbCreator.is() ) + throw uno::RuntimeException(); + + aObjectInfo.Object = uno::Reference< embed::XEmbeddedObject >( + xEmbCreator->createInstanceInitFromMediaDescriptor( xStorage, sEntName, aMediaDescr, aObjArgs ), + uno::UNO_QUERY ); + } + + if ( ( io.dwFlags & IOF_CHECKDISPLAYASICON) && io.hMetaPict != NULL ) + { + METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( io.hMetaPict ); + if ( pMF ) + { + sal_uInt32 nBufSize = GetMetaFileBitsEx( pMF->hMF, 0, NULL ); + uno::Sequence< sal_Int8 > aMetafile( nBufSize + 22 ); + sal_uInt8* pBuf = (sal_uInt8*)( aMetafile.getArray() ); + *( (long* )pBuf ) = 0x9ac6cdd7L; + *( (short* )( pBuf+6 )) = ( SHORT ) 0; + *( (short* )( pBuf+8 )) = ( SHORT ) 0; + *( (short* )( pBuf+10 )) = ( SHORT ) pMF->xExt; + *( (short* )( pBuf+12 )) = ( SHORT ) pMF->yExt; + *( (short* )( pBuf+14 )) = ( USHORT ) 2540; + + if ( nBufSize && nBufSize == GetMetaFileBitsEx( pMF->hMF, nBufSize, pBuf+22 ) ) + { + datatransfer::DataFlavor aFlavor( + ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ), + ::rtl::OUString::createFromAscii( "Image WMF" ), + getCppuType( ( const uno::Sequence< sal_Int8 >* ) 0 ) ); + + aObjectInfo.Options.realloc( 2 ); + aObjectInfo.Options[0].Name = ::rtl::OUString::createFromAscii( "Icon" ); + aObjectInfo.Options[0].Value <<= aMetafile; + aObjectInfo.Options[1].Name = ::rtl::OUString::createFromAscii( "IconFormat" ); + aObjectInfo.Options[1].Value <<= aFlavor; + } + + GlobalUnlock( io.hMetaPict ); + } + } + } + else + throw ucb::CommandAbortedException(); + +#else + throw lang::NoSupportException(); // TODO: +#endif + + OSL_ENSURE( aObjectInfo.Object.is(), "No object was created!\n" ); + if ( !aObjectInfo.Object.is() ) + throw uno::RuntimeException(); + + return aObjectInfo; +} + +//------------------------------------------------------------------------- +embed::InsertedObjectInfo SAL_CALL MSOLEDialogObjectCreator::createInstanceInitFromClipboard( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntryName, + const uno::Sequence< beans::PropertyValue >& aObjectArgs ) + throw ( lang::IllegalArgumentException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + embed::InsertedObjectInfo aObjectInfo; + +#ifdef WNT + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntryName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + uno::Reference< embed::XEmbeddedObject > xResult( + static_cast< ::cppu::OWeakObject* > ( new OleEmbeddedObject( m_xFactory ) ), + uno::UNO_QUERY ); + + uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); + + if ( !xPersist.is() ) + throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects + + xPersist->setPersistentEntry( xStorage, + sEntryName, + embed::EntryInitModes::DEFAULT_INIT, + uno::Sequence< beans::PropertyValue >(), + aObjectArgs ); + + aObjectInfo.Object = xResult; + + // TODO/LATER: in case of iconifie object the icon should be stored in aObjectInfo +#else + throw lang::NoSupportException(); // TODO: +#endif + + OSL_ENSURE( aObjectInfo.Object.is(), "No object was created!\n" ); + if ( !aObjectInfo.Object.is() ) + throw uno::RuntimeException(); + + return aObjectInfo; +} + +//------------------------------------------------------------------------- +::rtl::OUString SAL_CALL MSOLEDialogObjectCreator::getImplementationName() + throw ( uno::RuntimeException ) +{ + return impl_staticGetImplementationName(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL MSOLEDialogObjectCreator::supportsService( const ::rtl::OUString& ServiceName ) + throw ( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); + + for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) + if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) + return sal_True; + + return sal_False; +} + +//------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL MSOLEDialogObjectCreator::getSupportedServiceNames() + throw ( uno::RuntimeException ) +{ + return impl_staticGetSupportedServiceNames(); +} + diff --git a/embeddedobj/source/msole/xdialogcreator.hxx b/embeddedobj/source/msole/xdialogcreator.hxx new file mode 100644 index 000000000000..c8c4d1752624 --- /dev/null +++ b/embeddedobj/source/msole/xdialogcreator.hxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __XDIALOGCREATOR_HXX_ +#define __XDIALOGCREATOR_HXX_ + +#include <com/sun/star/embed/XInsertObjectDialog.hpp> +#include <com/sun/star/embed/XEmbedObjectClipboardCreator.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + + +#include <cppuhelper/implbase3.hxx> + + +class MSOLEDialogObjectCreator : public ::cppu::WeakImplHelper3< + ::com::sun::star::embed::XInsertObjectDialog, + ::com::sun::star::embed::XEmbedObjectClipboardCreator, + ::com::sun::star::lang::XServiceInfo > +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory; + +public: + MSOLEDialogObjectCreator( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory ) + : m_xFactory( xFactory ) + { + OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" ); + } + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames(); + + static ::rtl::OUString SAL_CALL impl_staticGetImplementationName(); + + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + impl_staticCreateSelfInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ); + + + // XInsertObjectDialog + virtual ::com::sun::star::embed::InsertedObjectInfo SAL_CALL createInstanceByDialog( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XEmbedObjectClipboardCreator + virtual ::com::sun::star::embed::InsertedObjectInfo SAL_CALL createInstanceInitFromClipboard( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntryName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aObjectArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException); + +}; + +#endif + diff --git a/embeddedobj/source/msole/xolefactory.cxx b/embeddedobj/source/msole/xolefactory.cxx new file mode 100644 index 000000000000..083890ff8e6d --- /dev/null +++ b/embeddedobj/source/msole/xolefactory.cxx @@ -0,0 +1,342 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_embeddedobj.hxx" +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/EntryInitModes.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/embed/Aspects.hpp> + +#include <rtl/logfile.hxx> + + +#include "xolefactory.hxx" +#include "oleembobj.hxx" + + +using namespace ::com::sun::star; + +// TODO: do not create OLE objects that represent OOo documents + +//------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OleEmbeddedObjectFactory::impl_staticGetSupportedServiceNames() +{ + uno::Sequence< ::rtl::OUString > aRet(2); + aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.OLEEmbeddedObjectFactory"); + aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OLEEmbeddedObjectFactory"); + return aRet; +} + +//------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OleEmbeddedObjectFactory::impl_staticGetImplementationName() +{ + return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.OLEEmbeddedObjectFactory"); +} + +//------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OleEmbeddedObjectFactory::impl_staticCreateSelfInstance( + const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) +{ + return uno::Reference< uno::XInterface >( *new OleEmbeddedObjectFactory( xServiceManager ) ); +} + +//------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OleEmbeddedObjectFactory::createInstanceInitFromEntry( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& aMedDescr, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + container::NoSuchElementException, + io::IOException, + uno::Exception, + uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObjectFactory::createInstanceInitFromEntry" ); + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY ); + if ( !xNameAccess.is() ) + throw uno::RuntimeException(); //TODO + + // detect entry existence + if ( !xNameAccess->hasByName( sEntName ) ) + throw container::NoSuchElementException(); + + if ( !xStorage->isStreamElement( sEntName ) ) + { + // if it is not an OLE object throw an exception + throw io::IOException(); // TODO: + } + + uno::Reference< uno::XInterface > xResult( + static_cast< ::cppu::OWeakObject* > ( new OleEmbeddedObject( m_xFactory, sal_False ) ), + uno::UNO_QUERY ); + + uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); + + if ( !xPersist.is() ) + throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects + + xPersist->setPersistentEntry( xStorage, + sEntName, + embed::EntryInitModes::DEFAULT_INIT, + aMedDescr, + lObjArgs ); + + for ( sal_Int32 nInd = 0; nInd < lObjArgs.getLength(); nInd++ ) + { + if ( lObjArgs[nInd].Name.equalsAscii( "CloneFrom" ) ) + { + try + { + uno::Reference < embed::XEmbeddedObject > xObj; + uno::Reference < embed::XEmbeddedObject > xNew( xResult, uno::UNO_QUERY ); + lObjArgs[nInd].Value >>= xObj; + if ( xObj.is() ) + xNew->setVisualAreaSize( embed::Aspects::MSOLE_CONTENT, xObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT ) ); + } + catch ( uno::Exception& ) {}; + break; + } + } + + return xResult; +} + +//------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OleEmbeddedObjectFactory::createInstanceInitFromMediaDescriptor( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& aMediaDescr, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + io::IOException, + uno::Exception, + uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObjectFactory::createInstanceInitFromMediaDescriptor" ); + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + uno::Reference< uno::XInterface > xResult( + static_cast< ::cppu::OWeakObject* > ( new OleEmbeddedObject( m_xFactory, sal_False ) ), + uno::UNO_QUERY ); + + uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); + + if ( !xPersist.is() ) + throw uno::RuntimeException(); // TODO: the interface must be supported ( what about applets? ) + + xPersist->setPersistentEntry( xStorage, + sEntName, + embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT, + aMediaDescr, + lObjArgs ); + + return xResult; +} + +//------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OleEmbeddedObjectFactory::createInstanceInitNew( + const uno::Sequence< sal_Int8 >& aClassID, + const ::rtl::OUString& aClassName, + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + io::IOException, + uno::Exception, + uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObjectFactory::createInstanceInitNew" ); + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 3 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 4 ); + + uno::Reference< uno::XInterface > xResult( + static_cast< ::cppu::OWeakObject* > ( new OleEmbeddedObject( m_xFactory, aClassID, aClassName ) ), + uno::UNO_QUERY ); + + uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); + + if ( !xPersist.is() ) + throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects + + xPersist->setPersistentEntry( xStorage, + sEntName, + embed::EntryInitModes::TRUNCATE_INIT, + uno::Sequence< beans::PropertyValue >(), + lObjArgs ); + + return xResult; +} + +//------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OleEmbeddedObjectFactory::createInstanceLink( + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + const uno::Sequence< beans::PropertyValue >& aMediaDescr, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObjectFactory::createInstanceLink" ); + + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( + static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( + static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + uno::Reference< uno::XInterface > xResult( + static_cast< ::cppu::OWeakObject* > ( new OleEmbeddedObject( m_xFactory, sal_True ) ), + uno::UNO_QUERY ); + + uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); + + if ( !xPersist.is() ) + throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects + + xPersist->setPersistentEntry( xStorage, + sEntName, + embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT, + aMediaDescr, + lObjArgs ); + + return xResult; +} + +//------------------------------------------------------------------------- +uno::Reference< uno::XInterface > SAL_CALL OleEmbeddedObjectFactory::createInstanceUserInit( + const uno::Sequence< sal_Int8 >& aClassID, + const ::rtl::OUString& aClassName, + const uno::Reference< embed::XStorage >& xStorage, + const ::rtl::OUString& sEntName, + sal_Int32 /*nEntryConnectionMode*/, + const uno::Sequence< beans::PropertyValue >& /*lArguments*/, + const uno::Sequence< beans::PropertyValue >& lObjArgs ) + throw ( lang::IllegalArgumentException, + io::IOException, + uno::Exception, + uno::RuntimeException ) +{ + RTL_LOGFILE_CONTEXT( aLog, "embeddedobj (mv76033) OleEmbeddedObjectFactory::createInstanceUserInit" ); + + // the initialization is completelly controlled by user + if ( !xStorage.is() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + if ( !sEntName.getLength() ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 2 ); + + uno::Reference< uno::XInterface > xResult( + static_cast< ::cppu::OWeakObject* > ( new OleEmbeddedObject( m_xFactory, aClassID, aClassName ) ), + uno::UNO_QUERY ); + + uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY ); + if ( xPersist.is() ) + { + xPersist->setPersistentEntry( xStorage, + sEntName, + embed::EntryInitModes::DEFAULT_INIT, + uno::Sequence< beans::PropertyValue >(), + lObjArgs ); + + } + else + throw uno::RuntimeException(); // TODO: + + return xResult; +} + +//------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OleEmbeddedObjectFactory::getImplementationName() + throw ( uno::RuntimeException ) +{ + return impl_staticGetImplementationName(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL OleEmbeddedObjectFactory::supportsService( const ::rtl::OUString& ServiceName ) + throw ( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); + + for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) + if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) + return sal_True; + + return sal_False; +} + +//------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > SAL_CALL OleEmbeddedObjectFactory::getSupportedServiceNames() + throw ( uno::RuntimeException ) +{ + return impl_staticGetSupportedServiceNames(); +} + diff --git a/embeddedobj/source/msole/xolefactory.hxx b/embeddedobj/source/msole/xolefactory.hxx new file mode 100644 index 000000000000..4515eedec315 --- /dev/null +++ b/embeddedobj/source/msole/xolefactory.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __XFACTORY_HXX_ +#define __XFACTORY_HXX_ + +#include <com/sun/star/embed/XEmbedObjectCreator.hpp> +#include <com/sun/star/embed/XEmbedObjectFactory.hpp> +#include <com/sun/star/embed/XLinkCreator.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + + +#include <cppuhelper/implbase4.hxx> + + +class OleEmbeddedObjectFactory : public ::cppu::WeakImplHelper4< + ::com::sun::star::embed::XEmbedObjectCreator, + ::com::sun::star::embed::XEmbedObjectFactory, + ::com::sun::star::embed::XLinkCreator, + ::com::sun::star::lang::XServiceInfo > +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory; + +public: + OleEmbeddedObjectFactory( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory ) + : m_xFactory( xFactory ) + { + OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" ); + } + + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames(); + + static ::rtl::OUString SAL_CALL impl_staticGetImplementationName(); + + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + impl_staticCreateSelfInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ); + + + // XEmbedObjectCreator + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitNew( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMedDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromMediaDescriptor( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XEmbedObjectFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceUserInit( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, sal_Int32 nEntryConnectionMode, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XLinkCreator + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceLink( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException); + +}; + +#endif + |