/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_embeddedobj.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 sense 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.isEmpty() ) 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 persistent representation without initialization // if the object is loaded // it can switch persistent representation only without initialization throw embed::WrongStateException( ::rtl::OUString::createFromAscii( "Can't change persistent 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 successfully 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 meaningful 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.isEmpty() ) KillFile_Impl( m_aTempURL, m_xFactory ); m_aTempURL = aOldTempURL; throw; } try { GetRidOfComponent(); } catch( uno::Exception& ) { delete pNewOleComponent; if( !m_aTempURL.isEmpty() ) 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; }