/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ownview.hxx" using namespace ::com::sun::star; #ifdef WNT //---------------------------------------------- void OleEmbeddedObject::SwitchComponentToRunningState_Impl() { if ( m_pOleComponent ) { try { m_pOleComponent->RunObject(); } catch( const embed::UnreachableStateException& ) { GetRidOfComponent(); throw; } catch( const 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 ) { SAL_WARN_IF( m_nObjectState == embed::EmbedStates::LOADED, "embeddedobj.ole", "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( const 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( const 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( const uno::RuntimeException& ) { pIterator.remove(); } } } } } delete m_pInterfaceContainer; m_pInterfaceContainer = NULL; } } //---------------------------------------------- uno::Reference< embed::XStorage > OleEmbeddedObject::CreateTemporarySubstorage( OUString& o_aStorageName ) { uno::Reference< embed::XStorage > xResult; for ( sal_Int32 nInd = 0; nInd < 32000 && !xResult.is(); nInd++ ) { OUString aName = OUString::number( nInd ) + "TMPSTOR" + m_aEntryName; if ( !m_xParentStorage->hasByName( aName ) ) { xResult = m_xParentStorage->openStorageElement( aName, embed::ElementModes::READWRITE ); o_aStorageName = aName; } } if ( !xResult.is() ) { o_aStorageName = OUString(); throw uno::RuntimeException(); } return xResult; } //---------------------------------------------- OUString OleEmbeddedObject::MoveToTemporarySubstream() { OUString aResult; for ( sal_Int32 nInd = 0; nInd < 32000 && aResult.isEmpty(); nInd++ ) { OUString aName = OUString::number( nInd ) + "TMPSTREAM" + m_aEntryName; if ( !m_xParentStorage->hasByName( aName ) ) { m_xParentStorage->renameElement( m_aEntryName, aName ); aResult = aName; } } if ( aResult.isEmpty() ) throw uno::RuntimeException(); return aResult; } //---------------------------------------------- sal_Bool OleEmbeddedObject::TryToConvertToOOo() { sal_Bool bResult = sal_False; OUString aStorageName; 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 ); OUString aFilterName = OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xFactory, OUString(), m_xObjectStream->getInputStream() ); // use the solution only for OOXML format currently if ( !aFilterName.isEmpty() && ( aFilterName == "Calc MS Excel 2007 XML" || aFilterName == "Impress MS PowerPoint 2007 XML" || aFilterName == "MS Word 2007 XML" ) ) { uno::Reference< container::XNameAccess > xFilterFactory( m_xFactory->createInstance("com.sun.star.document.FilterFactory"), uno::UNO_QUERY_THROW ); 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 == "DocumentService" ) aFilterData[nInd].Value >>= aDocServiceName; } if ( !aDocServiceName.isEmpty() ) { // create the model uno::Sequence< uno::Any > aArguments(1); aArguments[0] <<= beans::NamedValue( OUString( "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 = "SetEmbedded"; aSeq[0].Value <<= sal_True; xModel->attachResource( OUString(), aSeq ); // load the model from the stream uno::Sequence< beans::PropertyValue > aArgs( 5 ); aArgs[0].Name = "HierarchicalDocumentName"; aArgs[0].Value <<= m_aEntryName; aArgs[1].Name = "ReadOnly"; aArgs[1].Value <<= sal_True; aArgs[2].Name = "FilterName"; aArgs[2].Value <<= aFilterName; aArgs[3].Name = "URL"; aArgs[3].Value <<= OUString( "private:stream" ); aArgs[4].Name = "InputStream"; aArgs[4].Value <<= m_xObjectStream->getInputStream(); xSeekable->seek( 0 ); xLoadable->load( aArgs ); // the model is successfully 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 ); OUString aMediaType; xStorProps->getPropertyValue("MediaType") >>= aMediaType; xTmpStorage->dispose(); // look for the related embedded object factory ::comphelper::MimeConfigurationHelper aConfigHelper( comphelper::getComponentContext(m_xFactory) ); OUString aEmbedFactory; if ( !aMediaType.isEmpty() ) aEmbedFactory = aConfigHelper.GetFactoryNameByMediaType( aMediaType ); if ( aEmbedFactory.isEmpty() ) 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( const uno::Exception& ) { // the success of the removing is not so important } } } } catch( const uno::Exception& ) { // repair the object if necessary switch( nStep ) { case 4: case 3: if ( !aTmpStreamName.isEmpty() && aTmpStreamName != m_aEntryName ) try { if ( m_xParentStorage->hasByName( m_aEntryName ) ) m_xParentStorage->removeElement( m_aEntryName ); m_xParentStorage->renameElement( aTmpStreamName, m_aEntryName ); } catch ( const uno::Exception& ) { try { close( sal_True ); } catch( const 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( const uno::Exception& ) { try { close( sal_True ); } catch( const uno::Exception& ) {} throw uno::RuntimeException(); // the repairing is not possible } // no break as designed! case 1: case 0: if ( !aStorageName.isEmpty() ) try { m_xParentStorage->removeElement( aStorageName ); } catch( const uno::Exception& ) { SAL_WARN( "embeddedobj.ole", "Can not remove temporary storage!" ); } break; } } if ( bResult ) { // the conversion was done successfully, 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 ) { SAL_INFO( "embeddedobj.ole", "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( OUString( "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( 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(); } 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( const 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 ) { SAL_INFO( "embeddedobj.ole", "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( OUString( "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( OUString( "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 xIn, uno::Reference 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 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) { OUString sUrl; // the solution is only active for Unix systems #ifndef WNT uno::Reference xNativeTempFile( io::TempFile::create(comphelper::getComponentContext(xFactory)), 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( OUString("com.sun.star.embed.OLESimpleStorage"), aArgs ), uno::UNO_QUERY_THROW ); uno::Reference< io::XStream > xCONTENTS; try { xNameContainer->getByName("CONTENTS") >>= xCONTENTS; } catch (container::NoSuchElementException const&) { // ignore } 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("RemoveFile", uno::makeAny(sal_False)); uno::Any aUrl = xNativeTempFile->getPropertyValue("Uri"); aUrl >>= sUrl; xNativeTempFile = uno::Reference(); uno::Reference < ucb::XSimpleFileAccess3 > xSimpleFileAccess( ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory) ) ); xSimpleFileAccess->setReadOnly(sUrl, sal_True); } else { xNativeTempFile->setPropertyValue("RemoveFile", uno::makeAny(sal_True)); } #else (void) xFactory; (void) xObjectStream; #endif return sUrl; } } //---------------------------------------------- void SAL_CALL OleEmbeddedObject::doVerb( sal_Int32 nVerbID ) throw ( lang::IllegalArgumentException, embed::WrongStateException, embed::UnreachableStateException, uno::Exception, uno::RuntimeException ) { SAL_INFO( "embeddedobj.ole", "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( OUString( "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; } } 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 const& e) { SAL_WARN("embeddedobj.ole", "OleEmbeddedObject::doVerb: " "-9 fallback path: exception caught: " << e.Message); } } 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.isEmpty()) m_aTempDumpURL = lcl_ExtractObject(m_xFactory, m_xObjectStream); if (!m_aTempDumpURL.isEmpty()) { uno::Reference< ::com::sun::star::system::XSystemShellExecute > xSystemShellExecute( ::com::sun::star::system::SystemShellExecute::create(comphelper::getComponentContext(m_xFactory)) ); xSystemShellExecute->execute(m_aTempDumpURL, OUString(), ::com::sun::star::system::SystemShellExecuteFlags::URIS_ONLY); } else throw embed::UnreachableStateException(); } } else { throw embed::UnreachableStateException(); } } } //---------------------------------------------- uno::Sequence< embed::VerbDescriptor > SAL_CALL OleEmbeddedObject::getSupportedVerbs() throw ( embed::WrongStateException, uno::RuntimeException ) { SAL_INFO( "embeddedobj.ole", "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( OUString( "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( OUString( "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( OUString( "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( OUString( "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 SAL_WARN_IF( m_nUpdateMode != embed::EmbedUpdateModes::ALWAYS_UPDATE, "embeddedobj.ole", "Unknown update mode!" ); } } //---------------------------------------------- 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( OUString( "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( OUString( "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 ) { 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 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; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */