/**************************************************************
 * 
 * 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 <oleembobj.hxx>
#include <com/sun/star/embed/EmbedStates.hpp>
#include <com/sun/star/embed/EmbedVerbs.hpp>
#include <com/sun/star/embed/EntryInitModes.hpp>
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/EmbedUpdateModes.hpp>
#include <com/sun/star/embed/Aspects.hpp>
#include <com/sun/star/embed/XOptimizedStorage.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <com/sun/star/io/XTruncate.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>

#include <rtl/logfile.hxx>

#include <comphelper/storagehelper.hxx>
#include <comphelper/mimeconfighelper.hxx>
#include <comphelper/classids.hxx>


#include <olecomponent.hxx>
#include <closepreventer.hxx>

using namespace ::com::sun::star;
using namespace ::comphelper;

//-------------------------------------------------------------------------
sal_Bool KillFile_Impl( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
{
	if ( !xFactory.is() )
		return sal_False;

	sal_Bool bRet = sal_False;

	try
	{
		uno::Reference < ucb::XSimpleFileAccess > xAccess(
				xFactory->createInstance (
						::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
				uno::UNO_QUERY );

		if ( xAccess.is() )
		{
			xAccess->kill( aURL );
			bRet = sal_True;
		}
	}
	catch( uno::Exception& )
	{
	}

	return bRet;
}

//----------------------------------------------
::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
{
	OSL_ENSURE( xFactory.is(), "No factory is provided!\n" );

	::rtl::OUString aResult;

	uno::Reference < beans::XPropertySet > xTempFile(
			xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
			uno::UNO_QUERY );

	if ( !xTempFile.is() )
		throw uno::RuntimeException(); // TODO

	try {
		xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) );
		uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
		aUrl >>= aResult;
	}
	catch ( uno::Exception& )
	{
	}

	if ( !aResult.getLength() )
		throw uno::RuntimeException(); // TODO: can not create tempfile

	return aResult;
}

//-----------------------------------------------
::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream,
									  const uno::Reference< lang::XMultiServiceFactory >& xFactory )
		throw ( io::IOException,
				uno::RuntimeException )
{
	OSL_ENSURE( xInStream.is() && xFactory.is(), "Wrong parameters are provided!\n" );

	::rtl::OUString aResult = GetNewTempFileURL_Impl( xFactory );

	if ( aResult.getLength() )
	{
		try {
			uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
							xFactory->createInstance (
									::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
							uno::UNO_QUERY );

			if ( !xTempAccess.is() )
				throw uno::RuntimeException(); // TODO:

			uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aResult );
			if ( xTempOutStream.is() )
			{
				// copy stream contents to the file
				::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
				xTempOutStream->closeOutput();
				xTempOutStream = uno::Reference< io::XOutputStream >();
			}
			else
				throw io::IOException(); // TODO:
		}
		catch( packages::WrongPasswordException& )
		{
       		KillFile_Impl( aResult, xFactory );
			throw io::IOException(); //TODO:
		}
		catch( io::IOException& )
		{
       		KillFile_Impl( aResult, xFactory );
			throw;
		}
		catch( uno::RuntimeException& )
		{
       		KillFile_Impl( aResult, xFactory );
			throw;
		}
		catch( uno::Exception& )
		{
       		KillFile_Impl( aResult, xFactory );
			aResult = ::rtl::OUString();
		}
	}

	return aResult;
}
#ifdef WNT
::rtl::OUString GetNewFilledTempFile_Impl( const uno::Reference< embed::XOptimizedStorage >& xParentStorage, const ::rtl::OUString& aEntryName, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
	throw( io::IOException, uno::RuntimeException )
{
	::rtl::OUString aResult;

	try
	{
		uno::Reference < beans::XPropertySet > xTempFile(
				xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
				uno::UNO_QUERY );
		uno::Reference < io::XStream > xTempStream( xTempFile, uno::UNO_QUERY_THROW );

		xParentStorage->copyStreamElementData( aEntryName, xTempStream );

		xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) );
		uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
		aUrl >>= aResult;
	}
	catch( uno::RuntimeException& )
	{
		throw;
	}
	catch( uno::Exception& )
	{
	}

	if ( !aResult.getLength() )
		throw io::IOException();

	return aResult;
}

//------------------------------------------------------
void SetStreamMediaType_Impl( const uno::Reference< io::XStream >& xStream, const ::rtl::OUString& aMediaType )
{
	uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY );
	if ( !xPropSet.is() )
		throw uno::RuntimeException(); // TODO: all the storage streams must support XPropertySet

	xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ), uno::makeAny( aMediaType ) );
}
#endif
//------------------------------------------------------
void LetCommonStoragePassBeUsed_Impl( const uno::Reference< io::XStream >& xStream )
{
	uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY );
	if ( !xPropSet.is() )
		throw uno::RuntimeException(); // Only StorageStreams must be provided here, they must implement the interface

	xPropSet->setPropertyValue( ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ),
								uno::makeAny( (sal_Bool)sal_True ) );
}
#ifdef WNT
//------------------------------------------------------
void VerbExecutionController::StartControlExecution()
{
	osl::MutexGuard aGuard( m_aVerbExecutionMutex );

	// the class is used to detect STAMPIT object, that can never be active
	if ( !m_bVerbExecutionInProgress && !m_bWasEverActive )
	{
		m_bVerbExecutionInProgress = sal_True;
		m_nVerbExecutionThreadIdentifier = osl_getThreadIdentifier( NULL );
		m_bChangedOnVerbExecution = sal_False;
	}
}

//------------------------------------------------------
sal_Bool VerbExecutionController::EndControlExecution_WasModified()
{
	osl::MutexGuard aGuard( m_aVerbExecutionMutex );

	sal_Bool bResult = sal_False;
	if ( m_bVerbExecutionInProgress && m_nVerbExecutionThreadIdentifier == osl_getThreadIdentifier( NULL ) )
	{
		bResult = m_bChangedOnVerbExecution;
		m_bVerbExecutionInProgress = sal_False;
	}

	return bResult;
}

//------------------------------------------------------
void VerbExecutionController::ModificationNotificationIsDone()
{
	osl::MutexGuard aGuard( m_aVerbExecutionMutex );

	if ( m_bVerbExecutionInProgress && osl_getThreadIdentifier( NULL ) == m_nVerbExecutionThreadIdentifier )
		m_bChangedOnVerbExecution = sal_True;
}
#endif
//-----------------------------------------------
void VerbExecutionController::LockNotification()
{
	osl::MutexGuard aGuard( m_aVerbExecutionMutex );
	if ( m_nNotificationLock < SAL_MAX_INT32 )
		m_nNotificationLock++;
}

//-----------------------------------------------
void VerbExecutionController::UnlockNotification()
{
	osl::MutexGuard aGuard( m_aVerbExecutionMutex );
	if ( m_nNotificationLock > 0 )
		m_nNotificationLock--;
}

//-----------------------------------------------
uno::Reference< io::XStream > OleEmbeddedObject::GetNewFilledTempStream_Impl( const uno::Reference< io::XInputStream >& xInStream )
		throw( io::IOException )
{
	OSL_ENSURE( xInStream.is(), "Wrong parameter is provided!\n" );

	uno::Reference < io::XStream > xTempFile(
			m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
			uno::UNO_QUERY_THROW );

	uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
	if ( xTempOutStream.is() )
	{
		::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
		xTempOutStream->flush();
	}
	else
		throw io::IOException(); // TODO:

	return xTempFile;
}

//------------------------------------------------------
uno::Reference< io::XStream > OleEmbeddedObject::TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream )
		throw ( uno::Exception )
{
	// TODO/LATER: Actually this should be done by a centralized component ( may be a graphical filter )
	if ( !m_xFactory.is() )
		throw uno::RuntimeException();

	uno::Reference< io::XInputStream > xInStream = xStream->getInputStream();
	if ( !xInStream.is() )
		throw uno::RuntimeException();

	uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
	xSeek->seek( 0 );

	uno::Sequence< sal_Int8 > aData( 8 );
	sal_Int32 nRead = xInStream->readBytes( aData, 8 );
	xSeek->seek( 0 );

	if ( ( nRead >= 2 && aData[0] == 'B' && aData[1] == 'M' )
	  || ( nRead >= 4 && aData[0] == 1 && aData[1] == 0 && aData[2] == 9 && aData[3] == 0 ) )
	{
		// it should be a bitmap or a Metafile
		return xStream;
	}

//	sal_Bool bSetSizeToRepl = sal_False;
//	awt::Size aSizeToSet;

	sal_uInt32 nHeaderOffset = 0;
	if ( ( nRead >= 8 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 )
	  && ( aData[4] == 2 || aData[4] == 3 || aData[4] == 14 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 )
	{
		nHeaderOffset = 40;
		xSeek->seek( 8 );

		// TargetDevice might be used in future, currently the cache has specified NULL
		uno::Sequence< sal_Int8 > aHeadData( 4 );
		nRead = xInStream->readBytes( aHeadData, 4 );
		sal_uInt32 nLen = 0;
		if ( nRead == 4 && aHeadData.getLength() == 4 )
			nLen = ( ( ( (sal_uInt32)aHeadData[3] * 0x100 + (sal_uInt32)aHeadData[2] ) * 0x100 ) + (sal_uInt32)aHeadData[1] ) * 0x100 + (sal_uInt32)aHeadData[0];
		if ( nLen > 4 )
		{
			xInStream->skipBytes( nLen - 4 );
			nHeaderOffset += nLen - 4;
		}

//		if ( aData[4] == 3 )
//		{
//			try
//			{
//
//				aSizeToSet = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
//				aSizeToSet.Width /= 364; //2540; // let the size be in inches, as wmf requires
//				aSizeToSet.Height /= 364; //2540; // let the size be in inches, as wmf requires
//				bSetSizeToRepl = sal_True;
//			}
//			catch( uno::Exception& )
//			{}
//		}
	}
	else if ( nRead > 4 )
	{
		// check whether the first bytes represent the size
		sal_uInt32 nSize = 0;
		for ( sal_Int32 nInd = 3; nInd >= 0; nInd-- )
			nSize = ( nSize << 8 ) + (sal_uInt8)aData[nInd];

		if ( nSize == xSeek->getLength() - 4 )
			nHeaderOffset = 4;
	}

	if ( nHeaderOffset )
	{
		// this is either a bitmap or a metafile clipboard format, retrieve the pure stream
		uno::Reference < io::XStream > xResult(
			m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
			uno::UNO_QUERY_THROW );
		uno::Reference < io::XSeekable > xResultSeek( xResult, uno::UNO_QUERY_THROW );
		uno::Reference < io::XOutputStream > xResultOut = xResult->getOutputStream();
		uno::Reference < io::XInputStream > xResultIn = xResult->getInputStream();
		if ( !xResultOut.is() || !xResultIn.is() )
			throw uno::RuntimeException();

		// if it is windows metafile the size must be provided
		// the solution is not used currently
//		if ( bSetSizeToRepl && abs( aSizeToSet.Width ) < 0xFFFF && abs( aSizeToSet.Height ) < 0xFFFF )
//		{
//			uno::Sequence< sal_Int8 > aHeader(22);
//			sal_uInt8* pBuffer = (sal_uInt8*)aHeader.getArray();
//
//			// write 0x9ac6cdd7L
//			pBuffer[0] = 0xd7;
//			pBuffer[1] = 0xcd;
//			pBuffer[2] = 0xc6;
//			pBuffer[3] = 0x9a;
//
//			// following data seems to have no value
//			pBuffer[4] = 0;
//			pBuffer[5] = 0;
//
//			// must be set to 0
//			pBuffer[6] = 0;
//			pBuffer[7] = 0;
//			pBuffer[8] = 0;
//			pBuffer[9] = 0;
//			
//			// width of the picture
//			pBuffer[10] = abs( aSizeToSet.Width ) % 0x100;
//			pBuffer[11] = ( abs( aSizeToSet.Width ) / 0x100 ) % 0x100;
//
//			// height of the picture
//			pBuffer[12] = abs( aSizeToSet.Height ) % 0x100;
//			pBuffer[13] = ( abs( aSizeToSet.Height ) / 0x100 ) % 0x100;
//
//			// write 2540
//			pBuffer[14] = 0x6c; //0xec;
//			pBuffer[15] = 0x01; //0x09;
//
//			// fill with 0
//			for ( sal_Int32 nInd = 16; nInd < 22; nInd++ )
//				pBuffer[nInd] = 0;
//
//			xResultOut->writeBytes( aHeader );
//		}
		
		xSeek->seek( nHeaderOffset ); // header size for these formats
		::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xResultOut );
		xResultOut->closeOutput();
		xResultSeek->seek( 0 );
		xSeek->seek( 0 );

		return xResult;
	}

	return uno::Reference< io::XStream >();
}

//------------------------------------------------------
void OleEmbeddedObject::InsertVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream,
												const uno::Reference< io::XStream >& xCachedVisualRepresentation )
		throw ( uno::Exception )
{
	OSL_ENSURE( xTargetStream.is() && xCachedVisualRepresentation.is(), "Invalid arguments!\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 argument!\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, analyzing" );

			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 construction
									}
									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 AOO 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
			// impossibility to initialize the object means error here
			CreateOleComponentFromClipboard_Impl( NULL );
			m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
			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 construction
			}
			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 construction

			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 somewhere
	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 its 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 AOO 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 AOO 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 AOO 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 AOO 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 AOO 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 AOO 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 representation 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 AOO 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 AOO 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 AOO 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 AOO 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 AOO 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;
}