/**************************************************************
 *
 * 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 <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/embed/WrongStateException.hpp>
#include <com/sun/star/embed/UnreachableStateException.hpp>
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/io/XTruncate.hpp>
#include <com/sun/star/awt/XRequestCallback.hpp>

#include <platform.h>
#include <cppuhelper/interfacecontainer.h>
#include <comphelper/mimeconfighelper.hxx>
#include <comphelper/storagehelper.hxx>
#include <osl/file.hxx>
#include <rtl/ref.hxx>

#include <olecomponent.hxx>
#include <olewrapclient.hxx>
#include <advisesink.hxx>
#include <oleembobj.hxx>
#include <mtnotification.hxx>

using namespace ::com::sun::star;
using namespace ::comphelper;
#define     MAX_ENUM_ELE     20
#define		FORMATS_NUM		 3

// ============ class ComSmart =====================
namespace {

template< class T > class ComSmart
{
    T* m_pInterface;

    void OwnRelease()
    {
        if ( m_pInterface )
        {
            T* pInterface = m_pInterface;
            m_pInterface = NULL;
            pInterface->Release();
        }
    }

public:
    ComSmart()
    : m_pInterface( NULL )
    {}

    ComSmart( const ComSmart<T>& rObj )
    : m_pInterface( rObj.m_pInterface )
    {
        if ( m_pInterface != NULL )
            m_pInterface->AddRef();
    }

    ComSmart( T* pInterface )
    : m_pInterface( pInterface )
    {
         if ( m_pInterface != NULL )
            m_pInterface->AddRef();
    }

	~ComSmart()
	{
        OwnRelease();
	}

    ComSmart& operator=( const ComSmart<T>& rObj )
    {
        OwnRelease();

        m_pInterface = rObj.m_pInterface;

        if ( m_pInterface != NULL )
            m_pInterface->AddRef();

        return *this;
    }

    ComSmart<T>& operator=( T* pInterface )
    {
        OwnRelease();

        m_pInterface = pInterface;

        if ( m_pInterface != NULL )
            m_pInterface->AddRef();

        return *this;
    }

    operator T*() const
    {
        return m_pInterface;
    }

    T& operator*() const
    {
        return *m_pInterface;
    }

    T** operator&()
    {
        OwnRelease();

        m_pInterface = NULL;

        return &m_pInterface;
    }

    T* operator->() const
    {
        return m_pInterface;
    }

    BOOL operator==( const ComSmart<T>& rObj ) const
    {
        return ( m_pInterface == rObj.m_pInterface );
    }

    BOOL operator!=( const ComSmart<T>& rObj ) const
    {
        return ( m_pInterface != rObj.m_pInterface );
    }

    BOOL operator==( const T* pInterface ) const
    {
        return ( m_pInterface == pInterface );
    }

    BOOL operator!=( const T* pInterface ) const
    {
        return ( m_pInterface != pInterface );
    }
};

}

// ============ class ComSmart =====================

sal_Bool ConvertBufferToFormat( void* pBuf,
								sal_uInt32 nBufSize,
								const ::rtl::OUString& aFormatShortName,
								uno::Any& aResult );

::rtl::OUString GetNewTempFileURL_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) throw( io::IOException );

typedef ::std::vector< FORMATETC* > FormatEtcList;

FORMATETC pFormatTemplates[FORMATS_NUM] = {
					{ CF_ENHMETAFILE, NULL, 0, -1, TYMED_ENHMF },
					{ CF_METAFILEPICT, NULL, 0, -1, TYMED_MFPICT },
					{ CF_BITMAP, NULL, 0, -1, TYMED_GDI } };


struct OleComponentNative_Impl {
	ComSmart< IUnknown > m_pObj;
	ComSmart< IOleObject > m_pOleObject;
	ComSmart< IViewObject2 > m_pViewObject2;
	ComSmart< IStorage > m_pIStorage;
	FormatEtcList m_aFormatsList;
	uno::Sequence< datatransfer::DataFlavor > m_aSupportedGraphFormats;

	OleComponentNative_Impl()
	{
		// TODO: Extend format list
		m_aSupportedGraphFormats.realloc( 5 );

		m_aSupportedGraphFormats[0] = datatransfer::DataFlavor(
            ::rtl::OUString::createFromAscii( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ),
			::rtl::OUString::createFromAscii( "Windows Enhanced Metafile" ),
			getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );

		m_aSupportedGraphFormats[1] = datatransfer::DataFlavor(
            ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ),
			::rtl::OUString::createFromAscii( "Windows Metafile" ),
			getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );

		m_aSupportedGraphFormats[2] = datatransfer::DataFlavor(
            ::rtl::OUString::createFromAscii( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ),
			::rtl::OUString::createFromAscii( "Bitmap" ),
			getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );

		m_aSupportedGraphFormats[3] = datatransfer::DataFlavor(
			::rtl::OUString::createFromAscii( "image/png" ),
			::rtl::OUString::createFromAscii( "PNG" ),
			getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );

		m_aSupportedGraphFormats[0] = datatransfer::DataFlavor(
            ::rtl::OUString::createFromAscii( "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"" ),
			::rtl::OUString::createFromAscii( "GDIMetafile" ),
			getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
	}

	void AddSupportedFormat( const FORMATETC& aFormatEtc );

	FORMATETC* GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect );

	sal_Bool ConvertDataForFlavor( const STGMEDIUM& aMedium,
									const datatransfer::DataFlavor& aFlavor,
									uno::Any& aResult );

	sal_Bool GraphicalFlavor( const datatransfer::DataFlavor& aFlavor );

	uno::Sequence< datatransfer::DataFlavor > GetFlavorsForAspects( sal_uInt32 nSupportedAspects );
};

//----------------------------------------------
DWORD GetAspectFromFlavor( const datatransfer::DataFlavor& aFlavor )
{
	if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=THUMBNAIL" ) ) != -1 )
		return DVASPECT_THUMBNAIL;
	else if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=ICON" ) ) != -1 )
		return DVASPECT_ICON;
	else if ( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( ";Aspect=DOCPRINT" ) ) != -1 )
		return DVASPECT_DOCPRINT;
	else
		return DVASPECT_CONTENT;
}

//----------------------------------------------
::rtl::OUString GetFlavorSuffixFromAspect( DWORD nAsp )
{
	::rtl::OUString aResult;

	if ( nAsp == DVASPECT_THUMBNAIL )
		aResult = ::rtl::OUString::createFromAscii( ";Aspect=THUMBNAIL" );
	else if ( nAsp == DVASPECT_ICON )
		aResult = ::rtl::OUString::createFromAscii( ";Aspect=ICON" );
	else if ( nAsp == DVASPECT_DOCPRINT )
		aResult = ::rtl::OUString::createFromAscii( ";Aspect=DOCPRINT" );

	// no suffix for DVASPECT_CONTENT

	return aResult;
}

//----------------------------------------------
HRESULT OpenIStorageFromURL_Impl( const ::rtl::OUString& aURL, IStorage** ppIStorage )
{
	OSL_ENSURE( ppIStorage, "The pointer must not be empty!" );

	::rtl::OUString aFilePath;
	if ( !ppIStorage || ::osl::FileBase::getSystemPathFromFileURL( aURL, aFilePath ) != ::osl::FileBase::E_None )
		throw uno::RuntimeException(); // TODO: something dangerous happened

	return StgOpenStorage( reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
							 NULL,
							 STGM_READWRITE | STGM_TRANSACTED, // | STGM_DELETEONRELEASE,
							 NULL,
							 0,
							 ppIStorage );
}

//----------------------------------------------
sal_Bool OleComponentNative_Impl::ConvertDataForFlavor( const STGMEDIUM& aMedium,
														const datatransfer::DataFlavor& aFlavor,
														uno::Any& aResult )
{
	sal_Bool bAnyIsReady = sal_False;

	// try to convert data from Medium format to specified Flavor format
	if ( aFlavor.DataType == getCppuType( ( const uno::Sequence< sal_Int8 >* ) 0 ) )
	{
		// first the GDI-metafile must be generated

		unsigned char* pBuf = NULL;
		sal_uInt32 nBufSize = 0;
		::rtl::OUString aFormat;

		if ( aMedium.tymed == TYMED_MFPICT ) // Win Metafile
		{
			aFormat = ::rtl::OUString::createFromAscii("image/x-wmf");
			METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict );
			if ( pMF )
			{
				nBufSize = GetMetaFileBitsEx( pMF->hMF, 0, NULL ) + 22;
				pBuf = new unsigned char[nBufSize];


				// TODO/LATER: the unit size must be calculated correctly
				*( (long* )pBuf ) = 0x9ac6cdd7L;
				*( (short* )( pBuf+6 )) = ( SHORT ) 0;
				*( (short* )( pBuf+8 )) = ( SHORT ) 0;
				*( (short* )( pBuf+10 )) = ( SHORT ) pMF->xExt;
				*( (short* )( pBuf+12 )) = ( SHORT ) pMF->yExt;
				*( (short* )( pBuf+14 )) = ( USHORT ) 2540;


				if ( nBufSize && nBufSize == GetMetaFileBitsEx( pMF->hMF, nBufSize - 22, pBuf + 22 ) )
				{
                    if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"", 57 ) )
					{
						aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
						bAnyIsReady = sal_True;
					}
				}

				GlobalUnlock( aMedium.hMetaFilePict );
			}
		}
		else if ( aMedium.tymed == TYMED_ENHMF ) // Enh Metafile
		{
			aFormat = ::rtl::OUString::createFromAscii("image/x-emf");
			nBufSize = GetEnhMetaFileBits( aMedium.hEnhMetaFile, 0, NULL );
			pBuf = new unsigned char[nBufSize];
			if ( nBufSize && nBufSize == GetEnhMetaFileBits( aMedium.hEnhMetaFile, nBufSize, pBuf ) )
			{
                if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-emf;windows_formatname=\"Image EMF\"", 57 ) )
				{
					aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
					bAnyIsReady = sal_True;
				}
			}
		}
		else if ( aMedium.tymed == TYMED_GDI ) // Bitmap
		{
			aFormat = ::rtl::OUString::createFromAscii("image/x-MS-bmp");
			nBufSize = GetBitmapBits( aMedium.hBitmap, 0, NULL );
			pBuf = new unsigned char[nBufSize];
			if ( nBufSize && nBufSize == sal::static_int_cast< ULONG >( GetBitmapBits( aMedium.hBitmap, nBufSize, pBuf ) ) )
			{
                if ( aFlavor.MimeType.matchAsciiL( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"", 54 ) )
				{
					aResult <<= uno::Sequence< sal_Int8 >( ( sal_Int8* )pBuf, nBufSize );
					bAnyIsReady = sal_True;
				}
			}
		}

		if ( pBuf && !bAnyIsReady )
		{
			for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
 				if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType )
				  && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType
				  && aFlavor.DataType == getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) )
			{
				bAnyIsReady = ConvertBufferToFormat( ( void* )pBuf, nBufSize, aFormat, aResult );
				break;
			}
		}

		delete[] pBuf;
	}

	return bAnyIsReady;
}

//----------------------------------------------
sal_Bool OleComponentNative_Impl::GraphicalFlavor( const datatransfer::DataFlavor& aFlavor )
{
	// Actually all the required graphical formats must be supported
	for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
 		if ( aFlavor.MimeType.match( m_aSupportedGraphFormats[nInd].MimeType )
		  && aFlavor.DataType == m_aSupportedGraphFormats[nInd].DataType )
			return sal_True;

	return sal_False;
}

//----------------------------------------------
sal_Bool GetClassIDFromSequence_Impl( uno::Sequence< sal_Int8 > aSeq, CLSID& aResult )
{
	if ( aSeq.getLength() == 16 )
	{
		aResult.Data1 = ( ( ( ( ( ( sal_uInt8 )aSeq[0] << 8 ) + ( sal_uInt8 )aSeq[1] ) << 8 ) + ( sal_uInt8 )aSeq[2] ) << 8 ) + ( sal_uInt8 )aSeq[3];
		aResult.Data2 = ( ( sal_uInt8 )aSeq[4] << 8 ) + ( sal_uInt8 )aSeq[5];
		aResult.Data3 = ( ( sal_uInt8 )aSeq[6] << 8 ) + ( sal_uInt8 )aSeq[7];
		for( int nInd = 0; nInd < 8; nInd++ )
			aResult.Data4[nInd] = ( sal_uInt8 )aSeq[nInd+8];

		return sal_True;
	}

	return sal_False;
}

//----------------------------------------------
::rtl::OUString WinAccToVcl_Impl( const sal_Unicode* pStr )
{
	::rtl::OUString aResult;

	if( pStr )
	{
		while ( *pStr )
		{
			if ( *pStr == '&' )
			{
				aResult += ::rtl::OUString::createFromAscii( "~" );
				while( *( ++pStr ) == '&' );
			}
			else
			{
				aResult += ::rtl::OUString( pStr, 1 );
				pStr++;
			}
		}
	}

	return aResult;
}

//----------------------------------------------
OleComponent::OleComponent( const uno::Reference< lang::XMultiServiceFactory >& xFactory, OleEmbeddedObject* pUnoOleObject )
: m_pInterfaceContainer( NULL )
, m_bDisposed( sal_False )
, m_bModified( sal_False )
, m_pNativeImpl( new OleComponentNative_Impl() )
, m_xFactory( xFactory )
, m_pOleWrapClientSite( NULL )
, m_pImplAdviseSink( NULL )
, m_pUnoOleObject( pUnoOleObject )
, m_nOLEMiscFlags( 0 )
, m_nAdvConn( 0 )
, m_bOleInitialized( sal_False )
, m_bWorkaroundActive( sal_False )
{
	OSL_ENSURE( m_pUnoOleObject, "No owner object is provided!" );

	HRESULT hr = OleInitialize( NULL );
	OSL_ENSURE( hr == S_OK || hr == S_FALSE, "The ole can not be successfully initialized\n" );
	if ( hr == S_OK || hr == S_FALSE )
		m_bOleInitialized = sal_True;

	m_pOleWrapClientSite = new OleWrapperClientSite( ( OleComponent* )this );
	m_pOleWrapClientSite->AddRef();

	m_pImplAdviseSink = new OleWrapperAdviseSink( ( OleComponent* )this );
	m_pImplAdviseSink->AddRef();

}

//----------------------------------------------
OleComponent::~OleComponent()
{
	OSL_ENSURE( !m_pOleWrapClientSite && !m_pImplAdviseSink && !m_pInterfaceContainer && !m_bOleInitialized,
				"The object was not closed successfully! DISASTER is possible!" );

	if ( m_pOleWrapClientSite || m_pImplAdviseSink || m_pInterfaceContainer || m_bOleInitialized )
	{
		::osl::MutexGuard aGuard( m_aMutex );
		m_refCount++;
		try {
			Dispose();
		} catch( uno::Exception& ) {}
	}

	for ( FormatEtcList::iterator aIter = m_pNativeImpl->m_aFormatsList.begin();
		  aIter != m_pNativeImpl->m_aFormatsList.end();
		  aIter++ )
	{
		delete (*aIter);
		(*aIter) = NULL;
	}
	m_pNativeImpl->m_aFormatsList.clear();

	delete m_pNativeImpl;
}

//----------------------------------------------
void OleComponentNative_Impl::AddSupportedFormat( const FORMATETC& aFormatEtc )
{
	FORMATETC* pFormatToInsert = new FORMATETC( aFormatEtc );
	m_aFormatsList.push_back( pFormatToInsert );
}

//----------------------------------------------
FORMATETC* OleComponentNative_Impl::GetSupportedFormatForAspect( sal_uInt32 nRequestedAspect )
{
	for ( FormatEtcList::iterator aIter = m_aFormatsList.begin();
		  aIter != m_aFormatsList.end();
		  aIter++ )
		if ( (*aIter) && (*aIter)->dwAspect == nRequestedAspect )
			return (*aIter);

	return NULL;
}

//----------------------------------------------
void OleComponent::Dispose()
{
	// the mutex must be locked before this method is called
	if ( m_bDisposed )
		return;

	CloseObject();

	if ( m_pOleWrapClientSite )
	{
		m_pOleWrapClientSite->disconnectOleComponent();
		m_pOleWrapClientSite->Release();
		m_pOleWrapClientSite = NULL;
	}

	if ( m_pImplAdviseSink )
	{
		m_pImplAdviseSink->disconnectOleComponent();
		m_pImplAdviseSink->Release();
		m_pImplAdviseSink = NULL;
	}

	if ( m_pInterfaceContainer )
	{
		lang::EventObject aEvent( static_cast< ::cppu::OWeakObject* >( this ) );
		m_pInterfaceContainer->disposeAndClear( aEvent );

		delete m_pInterfaceContainer;
		m_pInterfaceContainer = NULL;
	}

	if ( m_bOleInitialized )
	{
		// since the disposing can happen not only from main thread but also from a clipboard
		// the deinitialization might lead to a disaster, SO7 does not deinitialize OLE at all
		// so currently the same approach is selected as workaround
		// OleUninitialize();
		m_bOleInitialized = sal_False;
	}

	m_bDisposed = sal_True;
}

//----------------------------------------------
void OleComponent::disconnectEmbeddedObject()
{
	// must not be called from destructor of UNO OLE object!!!
	osl::MutexGuard aGuard( m_aMutex );
	m_pUnoOleObject = NULL;
}

//----------------------------------------------
void OleComponent::CreateNewIStorage_Impl()
{
	// TODO: in future a global memory could be used instead of file.

	// write the stream to the temporary file
	::rtl::OUString aTempURL;

	OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
	if ( m_pUnoOleObject )
		aTempURL = m_pUnoOleObject->CreateTempURLEmpty_Impl();
	else
		aTempURL = GetNewTempFileURL_Impl( m_xFactory );

	if ( !aTempURL.getLength() )
		throw uno::RuntimeException(); // TODO

	// open an IStorage based on the temporary file
	::rtl::OUString aTempFilePath;
	if ( ::osl::FileBase::getSystemPathFromFileURL( aTempURL, aTempFilePath ) != ::osl::FileBase::E_None )
		throw uno::RuntimeException(); // TODO: something dangerous happened

	HRESULT hr = StgCreateDocfile( reinterpret_cast<LPCWSTR>(aTempFilePath.getStr()), STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED | STGM_DELETEONRELEASE, 0, &m_pNativeImpl->m_pIStorage );
	if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
		throw io::IOException(); // TODO: transport error code?
}

//----------------------------------------------
uno::Sequence< datatransfer::DataFlavor > OleComponentNative_Impl::GetFlavorsForAspects( sal_uInt32 nSupportedAspects )
{
	uno::Sequence< datatransfer::DataFlavor > aResult;
	for ( sal_uInt32 nAsp = 1; nAsp <= 8; nAsp *= 2 )
		if ( ( nSupportedAspects & nAsp ) == nAsp )
		{
			::rtl::OUString aAspectSuffix = GetFlavorSuffixFromAspect( nAsp );

			sal_Int32 nLength = aResult.getLength();
			aResult.realloc( nLength + m_aSupportedGraphFormats.getLength() );

			for ( sal_Int32 nInd = 0; nInd < m_aSupportedGraphFormats.getLength(); nInd++ )
			{
				aResult[nLength + nInd].MimeType = m_aSupportedGraphFormats[nInd].MimeType + aAspectSuffix;
				aResult[nLength + nInd].HumanPresentableName = m_aSupportedGraphFormats[nInd].HumanPresentableName;
				aResult[nLength + nInd].DataType = m_aSupportedGraphFormats[nInd].DataType;
			}
		}

	return aResult;
}

//----------------------------------------------
void OleComponent::RetrieveObjectDataFlavors_Impl()
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	if ( !m_aDataFlavors.getLength() )
	{
		ComSmart< IDataObject > pDataObject;
		HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
		if ( SUCCEEDED( hr ) && pDataObject )
		{
			ComSmart< IEnumFORMATETC > pFormatEnum;
			hr = pDataObject->EnumFormatEtc( DATADIR_GET, &pFormatEnum );
			if ( SUCCEEDED( hr ) && pFormatEnum )
			{
				FORMATETC pElem[ MAX_ENUM_ELE ];
				ULONG nNum = 0;

				// if it is possible to retrieve at least one supported graphical format for an aspect
				// this format can be converted to other supported formats
				sal_uInt32 nSupportedAspects = 0;
				do
				{
					HRESULT hr = pFormatEnum->Next( MAX_ENUM_ELE, pElem, &nNum );
					if( hr == S_OK || hr == S_FALSE )
					{
						for( sal_uInt32 nInd = 0; nInd < FORMATS_NUM; nInd++ )
							{
							if ( pElem[nInd].cfFormat == pFormatTemplates[nInd].cfFormat
					  		&& pElem[nInd].tymed == pFormatTemplates[nInd].tymed )
								nSupportedAspects |= pElem[nInd].dwAspect;
						}
					}
					else
						break;
				}
				while( nNum == MAX_ENUM_ELE );

				m_aDataFlavors = m_pNativeImpl->GetFlavorsForAspects( nSupportedAspects );
			}
		}

		if ( !m_aDataFlavors.getLength() )
		{
			// TODO:
			// for any reason the object could not provide this information
			// try to get access to the cached representation
		}
	}
}

//----------------------------------------------
sal_Bool OleComponent::InitializeObject_Impl()
// There will be no static objects!
{
	if ( !m_pNativeImpl->m_pObj )
		return sal_False;

	// the linked object will be detected here
	ComSmart< IOleLink > pOleLink;
	HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink );
	OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
	if ( m_pUnoOleObject )
		m_pUnoOleObject->SetObjectIsLink_Impl( sal_Bool( pOleLink != NULL ) );


	hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IViewObject2, (void**)&m_pNativeImpl->m_pViewObject2 );
	if ( FAILED( hr ) || !m_pNativeImpl->m_pViewObject2 )
		return sal_False;

	// not really needed for now, since object is updated on saving
	// m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink );

	// remove all the caches
	IOleCache* pIOleCache = NULL;
	if ( SUCCEEDED( m_pNativeImpl->m_pObj->QueryInterface( IID_IOleCache, (void**)&pIOleCache ) ) && pIOleCache )
	{
		IEnumSTATDATA* pEnumSD = NULL;
		HRESULT hr = pIOleCache->EnumCache( &pEnumSD );

		if ( SUCCEEDED( hr ) && pEnumSD )
		{
			pEnumSD->Reset();
			STATDATA aSD;
			DWORD nNum;
			while( SUCCEEDED( pEnumSD->Next( 1, &aSD, &nNum ) ) && nNum == 1 )
				hr = pIOleCache->Uncache( aSD.dwConnection );
		}

		// No IDataObject implementation, caching must be used instead
		DWORD nConn;
		FORMATETC aFormat = { 0, 0, DVASPECT_CONTENT, -1, TYMED_MFPICT };
		hr = pIOleCache->Cache( &aFormat, ADVFCACHE_ONSAVE, &nConn );

		pIOleCache->Release();
		pIOleCache = NULL;
	}

	hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IOleObject, (void**)&m_pNativeImpl->m_pOleObject );
	if ( FAILED( hr ) || !m_pNativeImpl->m_pOleObject )
		return sal_False; // Static objects are not supported, they should be inserted as graphics

	m_pNativeImpl->m_pOleObject->GetMiscStatus( DVASPECT_CONTENT, ( DWORD* )&m_nOLEMiscFlags );
	// TODO: use other misc flags also
	// the object should have drawable aspect even in case it supports only iconic representation
	// if ( m_nOLEMiscFlags & OLEMISC_ONLYICONIC )

	m_pNativeImpl->m_pOleObject->SetClientSite( m_pOleWrapClientSite );

	// the only need in this registration is workaround for close notification
	m_pNativeImpl->m_pOleObject->Advise( m_pImplAdviseSink, ( DWORD* )&m_nAdvConn );
    m_pNativeImpl->m_pViewObject2->SetAdvise( DVASPECT_CONTENT, 0, m_pImplAdviseSink );

	OleSetContainedObject( m_pNativeImpl->m_pOleObject, TRUE );

	return sal_True;
}

//----------------------------------------------
void OleComponent::LoadEmbeddedObject( const ::rtl::OUString& aTempURL )
{
	if ( !aTempURL.getLength() )
		throw lang::IllegalArgumentException(); // TODO

	if ( m_pNativeImpl->m_pIStorage )
		throw io::IOException(); // TODO the object is already initialized or wrong initialization is done

	// open an IStorage based on the temporary file
	HRESULT hr = OpenIStorageFromURL_Impl( aTempURL, &m_pNativeImpl->m_pIStorage );

	if ( FAILED( hr ) || !m_pNativeImpl->m_pIStorage )
		throw io::IOException(); // TODO: transport error code?

	hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj );
	if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
	{
		// STATSTG aStat;
		// m_pNativeImpl->m_pIStorage->Stat( &aStat, STATFLAG_NONAME );
		throw uno::RuntimeException();
	}

	if ( !InitializeObject_Impl() )
		throw uno::RuntimeException(); // TODO
}

//----------------------------------------------
void OleComponent::CreateObjectFromClipboard()
{
	if ( m_pNativeImpl->m_pIStorage )
		throw io::IOException(); // TODO:the object is already initialized

	CreateNewIStorage_Impl();
	if ( !m_pNativeImpl->m_pIStorage )
		throw uno::RuntimeException(); // TODO

	IDataObject * pDO = NULL;
	HRESULT hr = OleGetClipboard( &pDO );
	if( SUCCEEDED( hr ) && pDO )
	{
		hr = OleQueryCreateFromData( pDO );
		if( S_OK == GetScode( hr ) )
		{
			hr = OleCreateFromData( pDO,
									IID_IUnknown,
									OLERENDER_DRAW, // OLERENDER_FORMAT
									NULL, 			// &aFormat,
									NULL,
									m_pNativeImpl->m_pIStorage,
									(void**)&m_pNativeImpl->m_pObj );
		}
		else
		{
			// Static objects are not supported
			pDO->Release();
		}
	}

	if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
		throw uno::RuntimeException();

	if ( !InitializeObject_Impl() )
		throw uno::RuntimeException(); // TODO
}

//----------------------------------------------
void OleComponent::CreateNewEmbeddedObject( const uno::Sequence< sal_Int8 >& aSeqCLSID )
{
	CLSID aClsID;

	if ( !GetClassIDFromSequence_Impl( aSeqCLSID, aClsID ) )
		throw lang::IllegalArgumentException(); // TODO

	if ( m_pNativeImpl->m_pIStorage )
		throw io::IOException(); // TODO:the object is already initialized

	CreateNewIStorage_Impl();
	if ( !m_pNativeImpl->m_pIStorage )
		throw uno::RuntimeException(); // TODO

	// FORMATETC aFormat = { CF_METAFILEPICT, NULL, nAspect, -1, TYMED_MFPICT }; // for OLE..._DRAW should be NULL

	HRESULT hr = OleCreate( aClsID,
							IID_IUnknown,
							OLERENDER_DRAW, // OLERENDER_FORMAT
							NULL, 			// &aFormat,
							NULL,
							m_pNativeImpl->m_pIStorage,
							(void**)&m_pNativeImpl->m_pObj );

	if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
		throw uno::RuntimeException(); // TODO

	if ( !InitializeObject_Impl() )
		throw uno::RuntimeException(); // TODO

	// TODO: getExtent???
}

//----------------------------------------------
void OleComponent::CreateObjectFromData( const uno::Reference< datatransfer::XTransferable >& )
// Static objects are not supported, they should be inserted as graphics
{
	// TODO: May be this call is useless since there are no static objects
	//		 and nonstatic objects will be created based on OLEstorage ( stream ).
	//		 ???

	// OleQueryCreateFromData...
}

//----------------------------------------------
void OleComponent::CreateObjectFromFile( const ::rtl::OUString& aFileURL )
{
	if ( m_pNativeImpl->m_pIStorage )
		throw io::IOException(); // TODO:the object is already initialized

	CreateNewIStorage_Impl();
	if ( !m_pNativeImpl->m_pIStorage )
		throw uno::RuntimeException(); // TODO:

	::rtl::OUString aFilePath;
	if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None )
		throw uno::RuntimeException(); // TODO: something dangerous happened

	HRESULT hr = OleCreateFromFile( CLSID_NULL,
									reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
									IID_IUnknown,
									OLERENDER_DRAW, // OLERENDER_FORMAT
									NULL,
									NULL,
									m_pNativeImpl->m_pIStorage,
									(void**)&m_pNativeImpl->m_pObj );

	if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
		throw uno::RuntimeException(); // TODO

	if ( !InitializeObject_Impl() )
		throw uno::RuntimeException(); // TODO
}

//----------------------------------------------
void OleComponent::CreateLinkFromFile( const ::rtl::OUString& aFileURL )
{
	if ( m_pNativeImpl->m_pIStorage )
		throw io::IOException(); // TODO:the object is already initialized

	CreateNewIStorage_Impl();
	if ( !m_pNativeImpl->m_pIStorage )
		throw uno::RuntimeException(); // TODO:

	::rtl::OUString aFilePath;
	if ( ::osl::FileBase::getSystemPathFromFileURL( aFileURL, aFilePath ) != ::osl::FileBase::E_None )
		throw uno::RuntimeException(); // TODO: something dangerous happened

	HRESULT hr = OleCreateLinkToFile( reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
										IID_IUnknown,
										OLERENDER_DRAW, // OLERENDER_FORMAT
										NULL,
										NULL,
										m_pNativeImpl->m_pIStorage,
										(void**)&m_pNativeImpl->m_pObj );

	if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
		throw uno::RuntimeException(); // TODO

	if ( !InitializeObject_Impl() )
		throw uno::RuntimeException(); // TODO
}

//----------------------------------------------
void OleComponent::InitEmbeddedCopyOfLink( OleComponent* pOleLinkComponent )
{
	if ( !pOleLinkComponent || !pOleLinkComponent->m_pNativeImpl->m_pObj )
		throw lang::IllegalArgumentException(); // TODO

	if ( m_pNativeImpl->m_pIStorage )
		throw io::IOException(); // TODO:the object is already initialized

	ComSmart< IDataObject > pDataObject;
	HRESULT hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
	if ( SUCCEEDED( hr ) && pDataObject && SUCCEEDED( OleQueryCreateFromData( pDataObject ) ) )
	{
		// the object must be already disconnected from the temporary URL
		CreateNewIStorage_Impl();
		if ( !m_pNativeImpl->m_pIStorage )
			throw uno::RuntimeException(); // TODO:

		hr = OleCreateFromData( pDataObject,
								IID_IUnknown,
								OLERENDER_DRAW,
								NULL,
								NULL,
								m_pNativeImpl->m_pIStorage,
								(void**)&m_pNativeImpl->m_pObj );
	}

	if ( !m_pNativeImpl->m_pObj )
	{
		ComSmart< IOleLink > pOleLink;
		hr = pOleLinkComponent->m_pNativeImpl->m_pObj->QueryInterface( IID_IOleLink, (void**)&pOleLink );
		if ( FAILED( hr ) || !pOleLink )
			throw io::IOException(); // TODO: the object doesn't support IOleLink

		ComSmart< IMoniker > pMoniker;
		hr = pOleLink->GetSourceMoniker( &pMoniker );
		if ( FAILED( hr ) || !pMoniker )
			throw io::IOException(); // TODO: can not retrieve moniker

		// In case of file moniker life is easy : )
		DWORD aMonType = 0;
		hr = pMoniker->IsSystemMoniker( &aMonType );
		if ( SUCCEEDED( hr ) && aMonType == MKSYS_FILEMONIKER )
		{
			ComSmart< IMalloc > pMalloc;
			CoGetMalloc( 1, &pMalloc ); // if fails there will be a memory leak
			OSL_ENSURE( pMalloc, "CoGetMalloc() failed!" );

			LPOLESTR pOleStr = NULL;
			hr = pOleLink->GetSourceDisplayName( &pOleStr );
			if ( SUCCEEDED( hr ) && pOleStr )
			{
				::rtl::OUString aFilePath( ( sal_Unicode* )pOleStr );
				if ( pMalloc )
					pMalloc->Free( ( void* )pOleStr );

				hr = OleCreateFromFile( CLSID_NULL,
										reinterpret_cast<LPCWSTR>(aFilePath.getStr()),
										IID_IUnknown,
										OLERENDER_DRAW, // OLERENDER_FORMAT
										NULL,
										NULL,
										m_pNativeImpl->m_pIStorage,
										(void**)&m_pNativeImpl->m_pObj );
			}
		}

		// in case of other moniker types the only way is to get storage
		if ( !m_pNativeImpl->m_pObj )
		{
			ComSmart< IBindCtx > pBindCtx;
			hr = CreateBindCtx( 0, ( LPBC FAR* )&pBindCtx );
			if ( SUCCEEDED( hr ) && pBindCtx )
			{
				ComSmart< IStorage > pObjectStorage;
				hr = pMoniker->BindToStorage( pBindCtx, NULL, IID_IStorage, (void**)&pObjectStorage );
				if ( SUCCEEDED( hr ) && pObjectStorage )
				{
					hr = pObjectStorage->CopyTo( 0, NULL, NULL, m_pNativeImpl->m_pIStorage );
					if ( SUCCEEDED( hr ) )
						hr = OleLoad( m_pNativeImpl->m_pIStorage, IID_IUnknown, NULL, (void**)&m_pNativeImpl->m_pObj );
				}
			}
		}
	}

	// If object could not be created the only way is to use graphical representation
	if ( FAILED( hr ) || !m_pNativeImpl->m_pObj )
		throw uno::RuntimeException(); // TODO

	if ( !InitializeObject_Impl() )
		throw uno::RuntimeException(); // TODO
}

//----------------------------------------------
void OleComponent::RunObject()
{
	OSL_ENSURE( m_pNativeImpl->m_pOleObject, "The pointer can not be set to NULL here!\n" );
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	if ( !OleIsRunning( m_pNativeImpl->m_pOleObject ) )
	{
		HRESULT hr = S_OK;
		try
		{
			hr = OleRun( m_pNativeImpl->m_pObj );
		}
		catch( ... )
		{
			int i = 0;
			i++;
		}

		if ( FAILED( hr ) )
		{
			if ( hr == REGDB_E_CLASSNOTREG )
				throw embed::UnreachableStateException(); // the object server is not installed
			else
				throw io::IOException();
		}
	}
}

//----------------------------------------------
awt::Size OleComponent::CalculateWithFactor( const awt::Size& aSize,
											const awt::Size& aMultiplier,
											const awt::Size& aDivisor )
{
	awt::Size aResult;

	sal_Int64 nWidth = (sal_Int64)aSize.Width * (sal_Int64)aMultiplier.Width / (sal_Int64)aDivisor.Width;
	sal_Int64 nHeight = (sal_Int64)aSize.Height * (sal_Int64)aMultiplier.Height / (sal_Int64)aDivisor.Height;
	OSL_ENSURE( nWidth < SAL_MAX_INT32 && nWidth > SAL_MIN_INT32
			 && nHeight < SAL_MAX_INT32 && nHeight > SAL_MIN_INT32,
			 "Unacceptable result size!" );

	aResult.Width = (sal_Int32)nWidth;
	aResult.Height = (sal_Int32)nHeight;

	return aResult;
}

//----------------------------------------------
void OleComponent::CloseObject()
{
	if ( m_pNativeImpl->m_pOleObject && OleIsRunning( m_pNativeImpl->m_pOleObject ) )
		m_pNativeImpl->m_pOleObject->Close( OLECLOSE_NOSAVE ); // must be saved before
}

//----------------------------------------------
uno::Sequence< embed::VerbDescriptor > OleComponent::GetVerbList()
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	if( !m_aVerbList.getLength() )
	{
		ComSmart< IEnumOLEVERB > pEnum;
		if( SUCCEEDED( m_pNativeImpl->m_pOleObject->EnumVerbs( &pEnum ) ) )
		{
			OLEVERB     szEle[ MAX_ENUM_ELE ];
			ULONG       nNum = 0;
			sal_Int32	nSeqSize = 0;

			do
			{
				HRESULT hr = pEnum->Next( MAX_ENUM_ELE, szEle, &nNum );
				if( hr == S_OK || hr == S_FALSE )
				{
					m_aVerbList.realloc( nSeqSize += nNum );
					for( sal_uInt32 nInd = 0; nInd < nNum; nInd++ )
					{
						m_aVerbList[nSeqSize-nNum+nInd].VerbID = szEle[ nInd ].lVerb;
						m_aVerbList[nSeqSize-nNum+nInd].VerbName = WinAccToVcl_Impl( reinterpret_cast<const sal_Unicode*>(szEle[ nInd ].lpszVerbName) );
						m_aVerbList[nSeqSize-nNum+nInd].VerbFlags = szEle[ nInd ].fuFlags;
						m_aVerbList[nSeqSize-nNum+nInd].VerbAttributes = szEle[ nInd ].grfAttribs;
					}
				}
				else
					break;
			}
			while( nNum == MAX_ENUM_ELE );
		}
	}

	return m_aVerbList;
}

//----------------------------------------------
void OleComponent::ExecuteVerb( sal_Int32 nVerbID )
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO

	HRESULT hr = OleRun( m_pNativeImpl->m_pOleObject );
	if ( FAILED( hr ) )
		throw io::IOException(); // TODO: a specific exception that transport error code can be thrown here

	// TODO: probably extents should be set here and stored in aRect
	// TODO: probably the parent window also should be set
	hr = m_pNativeImpl->m_pOleObject->DoVerb( nVerbID, NULL, m_pOleWrapClientSite, 0, NULL, NULL );

	if ( FAILED( hr ) )
		throw io::IOException(); // TODO

	// TODO/LATER: the real names should be used here
	m_pNativeImpl->m_pOleObject->SetHostNames( L"app name", L"untitled" );
}

//----------------------------------------------
void OleComponent::SetHostName( const ::rtl::OUString&,
								const ::rtl::OUString& )
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	// TODO: use aContName and aEmbDocName in m_pNativeImpl->m_pOleObject->SetHostNames()
}

//----------------------------------------------
void OleComponent::SetExtent( const awt::Size& aVisAreaSize, sal_Int64 nAspect )
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects

	SIZEL aSize = { aVisAreaSize.Width, aVisAreaSize.Height };
	HRESULT hr = m_pNativeImpl->m_pOleObject->SetExtent( nMSAspect, &aSize );

	if ( FAILED( hr ) )
	{
		// TODO/LATER: is it correct? In future user code probably should be ready for the exception.
		// if the object is running but not activated, RPC_E_SERVER_DIED error code is returned by OLE package
		// in this case just do nothing
		// Also Visio returns E_FAIL on resize if it is in running state
		// if ( hr != RPC_E_SERVER_DIED )
		throw io::IOException(); // TODO
	}
}

//----------------------------------------------
awt::Size OleComponent::GetExtent( sal_Int64 nAspect )
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
	awt::Size aSize;
	sal_Bool bGotSize = sal_False;

	if ( nMSAspect == DVASPECT_CONTENT )
	{
		// Try to get the size from the replacement image first
		ComSmart< IDataObject > pDataObject;
		HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
		if ( SUCCEEDED( hr ) || pDataObject )
		{
			STGMEDIUM aMedium;
			FORMATETC aFormat = pFormatTemplates[1]; // use windows metafile format
			aFormat.dwAspect = nMSAspect;

			hr = pDataObject->GetData( &aFormat, &aMedium );
			if ( SUCCEEDED( hr ) && aMedium.tymed == TYMED_MFPICT ) // Win Metafile
			{
				METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( aMedium.hMetaFilePict );
				if ( pMF )
				{
					// the object uses 0.01 mm as unit, so the metafile size should be converted to object unit
					sal_Int64 nMult = 1;
					sal_Int64 nDiv = 1;
					switch( pMF->mm )
					{
						case MM_HIENGLISH:
							nMult = 254;
							nDiv = 100;
							break;

						case MM_LOENGLISH:
							nMult = 254;
							nDiv = 10;
							break;

						case MM_LOMETRIC:
							nMult = 10;
							break;

						case MM_TWIPS:
							nMult = 254;
							nDiv = 144;
							break;

						case MM_ISOTROPIC:
						case MM_ANISOTROPIC:
						case MM_HIMETRIC:
							// do nothing
							break;
					}

					sal_Int64 nX = ( (sal_Int64)abs( pMF->xExt ) ) * nMult / nDiv;
					sal_Int64 nY = ( (sal_Int64)abs( pMF->yExt ) ) * nMult / nDiv;
					if (  nX < SAL_MAX_INT32 && nY < SAL_MAX_INT32 )
					{
						aSize.Width = ( sal_Int32 )nX;
						aSize.Height = ( sal_Int32 )nY;
						bGotSize = sal_True;
					}
					else
						OSL_ENSURE( sal_False, "Unexpected size is provided!" );
				}
			}
			// i113605, to release storge medium
			if ( SUCCEEDED( hr ) )
				::ReleaseStgMedium(&aMedium);
		}
	}

	if ( !bGotSize )
		throw lang::IllegalArgumentException();

	return aSize;
}

//----------------------------------------------
awt::Size OleComponent::GetCachedExtent( sal_Int64 nAspect )
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
	SIZEL aSize;

	HRESULT hr = m_pNativeImpl->m_pViewObject2->GetExtent( nMSAspect, -1, NULL, &aSize );

	if ( FAILED( hr ) )
	{
		// TODO/LATER: is it correct?
		// if there is no appropriate cache for the aspect, OLE_E_BLANK error code is returned
		// if ( hr == OLE_E_BLANK )
		//	throw lang::IllegalArgumentException();
		//else
		//	throw io::IOException(); // TODO

		throw lang::IllegalArgumentException();
	}

	return awt::Size( aSize.cx, aSize.cy );
}

//----------------------------------------------
awt::Size OleComponent::GetReccomendedExtent( sal_Int64 nAspect )
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	DWORD nMSAspect = ( DWORD )nAspect; // first 32 bits are for MS aspects
	SIZEL aSize;
	HRESULT hr = m_pNativeImpl->m_pOleObject->GetExtent( nMSAspect, &aSize );
	if ( FAILED( hr ) )
		throw lang::IllegalArgumentException();

	return awt::Size( aSize.cx, aSize.cy );
}

//----------------------------------------------
sal_Int64 OleComponent::GetMiscStatus( sal_Int64 nAspect )
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	sal_uInt32 nResult;
	m_pNativeImpl->m_pOleObject->GetMiscStatus( ( DWORD )nAspect, ( DWORD* )&nResult );
	return ( sal_Int64 )nResult; // first 32 bits are for MS flags
}

//----------------------------------------------
uno::Sequence< sal_Int8 > OleComponent::GetCLSID()
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	GUID aCLSID;
	HRESULT hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
	if ( FAILED( hr ) )
		throw io::IOException(); // TODO:

	return  MimeConfigurationHelper::GetSequenceClassID( aCLSID.Data1, aCLSID.Data2, aCLSID.Data3,
								aCLSID.Data4[0], aCLSID.Data4[1],
								aCLSID.Data4[2], aCLSID.Data4[3],
								aCLSID.Data4[4], aCLSID.Data4[5],
								aCLSID.Data4[6], aCLSID.Data4[7] );
}

//----------------------------------------------
sal_Bool OleComponent::IsDirty()
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	if ( IsWorkaroundActive() )
		return sal_True;

	ComSmart< IPersistStorage > pPersistStorage;
	HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage );
	if ( FAILED( hr ) || !pPersistStorage )
		throw io::IOException(); // TODO

	hr = pPersistStorage->IsDirty();
	return ( hr != S_FALSE );
}

//----------------------------------------------
void OleComponent::StoreOwnTmpIfNecessary()
{
	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	ComSmart< IPersistStorage > pPersistStorage;
	HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IPersistStorage, (void**)&pPersistStorage );
	if ( FAILED( hr ) || !pPersistStorage )
		throw io::IOException(); // TODO

	if ( m_bWorkaroundActive || pPersistStorage->IsDirty() != S_FALSE )
	{
		hr = OleSave( pPersistStorage, m_pNativeImpl->m_pIStorage, TRUE );
		if ( FAILED( hr ) )
		{
			// Till now was required only for AcrobatReader7.0.8
			GUID aCLSID;
			hr = m_pNativeImpl->m_pOleObject->GetUserClassID( &aCLSID );
			if ( FAILED( hr ) )
				throw io::IOException(); // TODO

			hr = WriteClassStg( m_pNativeImpl->m_pIStorage, aCLSID );
			if ( FAILED( hr ) )
				throw io::IOException(); // TODO

			// the result of the following call is not checked because some objects, for example AcrobatReader7.0.8
			// return error even in case the saving was done correctly
			hr = pPersistStorage->Save( m_pNativeImpl->m_pIStorage, TRUE );

			// another workaround for AcrobatReader7.0.8 object, this object might think that it is not changed
			// when it has been created from file, although it must be saved
			m_bWorkaroundActive = sal_True;
		}

		hr = m_pNativeImpl->m_pIStorage->Commit( STGC_DEFAULT );
		if ( FAILED( hr ) )
			throw io::IOException(); // TODO

		hr = pPersistStorage->SaveCompleted( NULL );
		if ( FAILED( hr ) && hr != E_UNEXPECTED )
			throw io::IOException(); // TODO

		// STATSTG aStat;
		// m_pNativeImpl->m_pIStorage->Stat( &aStat, STATFLAG_NONAME );
	}
}

//----------------------------------------------
sal_Bool OleComponent::SaveObject_Impl()
{
	sal_Bool bResult = sal_False;
	OleEmbeddedObject* pLockObject = NULL;

	{
		osl::MutexGuard aGuard( m_aMutex );
		if ( m_pUnoOleObject )
		{
			pLockObject = m_pUnoOleObject;
			pLockObject->acquire();
		}
	}

	if ( pLockObject )
	{
		bResult = pLockObject->SaveObject_Impl();
		pLockObject->release();
	}

	return bResult;
}

//----------------------------------------------
sal_Bool OleComponent::OnShowWindow_Impl( bool bShow )
{
	sal_Bool bResult = sal_False;
	OleEmbeddedObject* pLockObject = NULL;

	{
		osl::MutexGuard aGuard( m_aMutex );

		if ( m_pUnoOleObject )
		{
			pLockObject = m_pUnoOleObject;
			pLockObject->acquire();
		}
	}

	if ( pLockObject )
	{
		bResult = pLockObject->OnShowWindow_Impl( bShow );
		pLockObject->release();
	}

	return bResult;
}

//----------------------------------------------
void OleComponent::OnViewChange_Impl( sal_uInt32 dwAspect )
{
	// TODO: check if it is enough or may be saving notifications are required for Visio2000
	::rtl::Reference< OleEmbeddedObject > xLockObject;

	{
		osl::MutexGuard aGuard( m_aMutex );
		if ( m_pUnoOleObject )
			xLockObject = m_pUnoOleObject;
	}

	if ( xLockObject.is() )
	{
		uno::Reference < awt::XRequestCallback > xRequestCallback(
			m_xFactory->createInstance(
			 ::rtl::OUString::createFromAscii("com.sun.star.awt.AsyncCallback") ),
			 uno::UNO_QUERY );
		xRequestCallback->addCallback( new MainThreadNotificationRequest( xLockObject, OLECOMP_ONVIEWCHANGE, dwAspect ), uno::Any() );
	}
}

//----------------------------------------------
void OleComponent::OnClose_Impl()
{
	::rtl::Reference< OleEmbeddedObject > xLockObject;

	{
		osl::MutexGuard aGuard( m_aMutex );
		if ( m_pUnoOleObject )
			xLockObject = m_pUnoOleObject;
	}

	if ( xLockObject.is() )
	{
		uno::Reference < awt::XRequestCallback > xRequestCallback(
			m_xFactory->createInstance(
			 ::rtl::OUString::createFromAscii("com.sun.star.awt.AsyncCallback") ),
			 uno::UNO_QUERY );
		xRequestCallback->addCallback( new MainThreadNotificationRequest( xLockObject, OLECOMP_ONCLOSE ), uno::Any() );
	}
}

// XCloseable
//----------------------------------------------
void SAL_CALL OleComponent::close( sal_Bool bDeliverOwnership )
	throw ( util::CloseVetoException,
			uno::RuntimeException )
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

    uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) );
    lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );

	if ( m_pInterfaceContainer )
	{
    	::cppu::OInterfaceContainerHelper* pContainer =
			m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) );
    	if ( pContainer != NULL )
		{
        	::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
        	while ( pIterator.hasMoreElements() )
        	{
            	try
            	{
                	( (util::XCloseListener* )pIterator.next() )->queryClosing( aSource, bDeliverOwnership );
            	}
            	catch( uno::RuntimeException& )
            	{
                	pIterator.remove();
            	}
        	}
		}

    	pContainer = m_pInterfaceContainer->getContainer(
									::getCppuType( ( const uno::Reference< util::XCloseListener >* ) NULL ) );
    	if ( pContainer != NULL )
		{
        	::cppu::OInterfaceIteratorHelper pCloseIterator( *pContainer );
        	while ( pCloseIterator.hasMoreElements() )
        	{
            	try
            	{
                	( (util::XCloseListener* )pCloseIterator.next() )->notifyClosing( aSource );
            	}
            	catch( uno::RuntimeException& )
            	{
                	pCloseIterator.remove();
            	}
        	}
		}
	}

	Dispose();
}

//----------------------------------------------
void SAL_CALL OleComponent::addCloseListener( const uno::Reference< util::XCloseListener >& xListener )
	throw ( uno::RuntimeException )
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( !m_pInterfaceContainer )
		m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );

	m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ), xListener );
}

//----------------------------------------------
void SAL_CALL OleComponent::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener )
	throw ( uno::RuntimeException )
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( m_pInterfaceContainer )
		m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XCloseListener >* )0 ),
												xListener );
}

// XTransferable
//----------------------------------------------
uno::Any SAL_CALL OleComponent::getTransferData( const datatransfer::DataFlavor& aFlavor )
	throw ( datatransfer::UnsupportedFlavorException,
			io::IOException,
			uno::RuntimeException )
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	uno::Any aResult;
	sal_Bool bSupportedFlavor = sal_False;

	if ( m_pNativeImpl->GraphicalFlavor( aFlavor ) )
	{
		DWORD nRequestedAspect = GetAspectFromFlavor( aFlavor );
		// if own icon is set and icon aspect is requested the own icon can be returned directly

		ComSmart< IDataObject > pDataObject;
		HRESULT hr = m_pNativeImpl->m_pObj->QueryInterface( IID_IDataObject, (void**)&pDataObject );
		if ( FAILED( hr ) || !pDataObject )
			throw io::IOException(); // TODO: transport error code

		// The following optimization does not make much sense currently just because
		// only one aspect is supported, and only three formats for the aspect are supported
		// and moreover it is not guarantied that the once returned format will be supported further
		// example - i52106
		// TODO/LATER: bring the optimization back when other aspects are supported

		// FORMATETC* pFormatEtc = m_pNativeImpl->GetSupportedFormatForAspect( nRequestedAspect );
		// if ( pFormatEtc )
		// {
		// 	STGMEDIUM aMedium;
		// 	hr = pDataObject->GetData( pFormatEtc, &aMedium );
		// 	if ( SUCCEEDED( hr ) )
		// 		bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
		// }
		// else
		{
			// the supported format of the application is still not found, find one
			for ( sal_Int32 nInd = 0; nInd < FORMATS_NUM; nInd++ )
			{
				STGMEDIUM aMedium;
				FORMATETC aFormat = pFormatTemplates[nInd];
				aFormat.dwAspect = nRequestedAspect;

				hr = pDataObject->GetData( &aFormat, &aMedium );
				if ( SUCCEEDED( hr ) )
                {
                    bSupportedFlavor = m_pNativeImpl->ConvertDataForFlavor( aMedium, aFlavor, aResult );
                    ::ReleaseStgMedium(&aMedium);     // i113605, to release storge medium
                    if ( bSupportedFlavor )
                    {
                        // TODO/LATER: bring the optimization back when other aspects are supported
                        // m_pNativeImpl->AddSupportedFormat( aFormat );
                        break;
                    }
				}
			}
		}

		// If the replacement could not be retrieved, the cached representaion should be used
		// currently it is not necessary to retrieve it here, so it is implemented in the object itself
	}
	// TODO: Investigate if there is already the format name
	// 		 and whether this format is really required
	else if ( aFlavor.DataType == getCppuType( ( const uno::Reference< io::XInputStream >* ) 0 )
			&& aFlavor.MimeType.equalsAscii( "application/x-openoffice-contentstream" ) )
	{
		// allow to retrieve stream-representation of the object persistence
		bSupportedFlavor = sal_True;
		uno::Reference < io::XStream > xTempFileStream(
			m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
			uno::UNO_QUERY );

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

		uno::Reference< io::XOutputStream > xTempOutStream = xTempFileStream->getOutputStream();
		uno::Reference< io::XInputStream > xTempInStream = xTempFileStream->getInputStream();
		if ( xTempOutStream.is() && xTempInStream.is() )
		{
			OSL_ENSURE( m_pUnoOleObject, "Unexpected object absence!" );
			if ( !m_pUnoOleObject )
			throw uno::RuntimeException();

			m_pUnoOleObject->StoreObjectToStream( xTempOutStream );

			xTempOutStream->closeOutput();
			xTempOutStream = uno::Reference< io::XOutputStream >();
		}
		else
			throw io::IOException(); // TODO:

		aResult <<= xTempInStream;
	}

	if ( !bSupportedFlavor )
		throw datatransfer::UnsupportedFlavorException();

	return aResult;
}

//----------------------------------------------
uno::Sequence< datatransfer::DataFlavor > SAL_CALL OleComponent::getTransferDataFlavors()
	throw ( uno::RuntimeException )
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	RetrieveObjectDataFlavors_Impl();

	return m_aDataFlavors;
}

//----------------------------------------------
sal_Bool SAL_CALL OleComponent::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
	throw ( uno::RuntimeException )
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( !m_pNativeImpl->m_pOleObject )
		throw embed::WrongStateException(); // TODO: the object is in wrong state

	if ( !m_aDataFlavors.getLength() )
	{
		RetrieveObjectDataFlavors_Impl();
	}

	for ( sal_Int32 nInd = 0; nInd < m_aDataFlavors.getLength(); nInd++ )
		if ( m_aDataFlavors[nInd].MimeType.equals( aFlavor.MimeType ) && m_aDataFlavors[nInd].DataType == aFlavor.DataType )
			return sal_True;

	return sal_False;
}

void SAL_CALL OleComponent::dispose() throw (::com::sun::star::uno::RuntimeException)
{
    try
    {
        close( sal_True );
    }
    catch ( uno::Exception& )
    {
    }
}

void SAL_CALL OleComponent::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
	throw ( uno::RuntimeException )
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( !m_pInterfaceContainer )
		m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );

    m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ), xListener );
}

//----------------------------------------------
void SAL_CALL OleComponent::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
	throw ( uno::RuntimeException )
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( m_pInterfaceContainer )
        m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< lang::XEventListener >* )0 ),
												xListener );
}

sal_Int64 SAL_CALL OleComponent::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException)
{
    try
    {
        uno::Sequence < sal_Int8 > aCLSID = GetCLSID();
        if ( MimeConfigurationHelper::ClassIDsEqual( aIdentifier, aCLSID ) )
            return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj;

        // compatibility hack for old versions: CLSID was used in wrong order (SvGlobalName order)
        sal_Int32 nLength = aIdentifier.getLength();
        if ( nLength == 16 )
        {
            for ( sal_Int32 n=8; n<16; n++ )
                if ( aIdentifier[n] != aCLSID[n] )
                    return 0;
            if ( aIdentifier[7] == aCLSID[6] &&
                 aIdentifier[6] == aCLSID[7] &&
                 aIdentifier[5] == aCLSID[4] &&
                 aIdentifier[4] == aCLSID[5] &&
                 aIdentifier[3] == aCLSID[0] &&
                 aIdentifier[2] == aCLSID[1] &&
                 aIdentifier[1] == aCLSID[2] &&
                 aIdentifier[0] == aCLSID[3] )
                return (sal_Int64) (IUnknown*) m_pNativeImpl->m_pObj;
        }
	}
    catch ( uno::Exception& )
    {
    }

    return 0;
}

sal_Bool SAL_CALL OleComponent::isModified() throw (::com::sun::star::uno::RuntimeException)
{
    return m_bModified;
}

void SAL_CALL OleComponent::setModified( sal_Bool bModified )
        throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException)
{
    m_bModified = bModified;

    if ( bModified && m_pInterfaceContainer )
	{
    	::cppu::OInterfaceContainerHelper* pContainer =
            m_pInterfaceContainer->getContainer( ::getCppuType( ( const uno::Reference< util::XModifyListener >* ) NULL ) );
    	if ( pContainer != NULL )
		{
            ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
            while ( pIterator.hasMoreElements() )
        	{
            	try
            	{
                    lang::EventObject aEvent( (util::XModifiable*) this );
                    ((util::XModifyListener*)pIterator.next())->modified( aEvent );
            	}
            	catch( uno::RuntimeException& )
            	{
                    pIterator.remove();
            	}
        	}
		}
	}
}

void SAL_CALL OleComponent::addModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener ) throw(::com::sun::star::uno::RuntimeException)
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( !m_pInterfaceContainer )
		m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );

    m_pInterfaceContainer->addInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ), xListener );
}

void SAL_CALL OleComponent::removeModifyListener( const com::sun::star::uno::Reference < com::sun::star::util::XModifyListener >& xListener) throw(::com::sun::star::uno::RuntimeException)
{
	::osl::MutexGuard aGuard( m_aMutex );
	if ( m_bDisposed )
		throw lang::DisposedException(); // TODO

	if ( m_pInterfaceContainer )
        m_pInterfaceContainer->removeInterface( ::getCppuType( ( const uno::Reference< util::XModifyListener >* )0 ),
												xListener );
}
