/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/


#if defined(_MSC_VER) && (_MSC_VER > 1310)
#pragma warning(disable : 4917 4555)
#endif

#include "stdafx.h"
#include "servprov.hxx"
#include "embeddoc.hxx"
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <cppuhelper/typeprovider.hxx>
#include <osl/mutex.hxx>
#include <osl/thread.h>

using namespace com::sun::star;

const GUID* guidList[ SUPPORTED_FACTORIES_NUM ] = {
	&OID_WriterTextServer,
	&OID_WriterOASISTextServer,
	&OID_CalcServer,
	&OID_CalcOASISServer,
	&OID_DrawingServer,
	&OID_DrawingOASISServer,
	&OID_PresentationServer,
	&OID_PresentationOASISServer,
	&OID_MathServer,
	&OID_MathOASISServer
};

class CurThreadData
{
	public:
		CurThreadData();
		virtual ~CurThreadData();

		sal_Bool SAL_CALL setData(void *pData);

		void* SAL_CALL getData();

	protected:
		oslThreadKey m_hKey;
};

CurThreadData::CurThreadData()
{
	m_hKey = osl_createThreadKey( (oslThreadKeyCallbackFunction)NULL );
}

CurThreadData::~CurThreadData()
{
	osl_destroyThreadKey(m_hKey);
}

sal_Bool CurThreadData::setData(void *pData)
{
	OSL_ENSURE( m_hKey, "No thread key!\n" );
	return (osl_setThreadKeyData(m_hKey, pData));
}

void *CurThreadData::getData()
{
	OSL_ENSURE( m_hKey, "No thread key!\n" );
	return (osl_getThreadKeyData(m_hKey));
}


// CoInitializeEx *
typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *ptrCoInitEx)( LPVOID, DWORD);
// CoInitialize *
typedef DECLSPEC_IMPORT HRESULT (STDAPICALLTYPE *ptrCoInit)( LPVOID);

void o2u_attachCurrentThread()
{
    static CurThreadData oleThreadData;

    if ( oleThreadData.getData() != 0 )
    {
        HINSTANCE inst=	LoadLibrary( _T("ole32.dll"));
        if( inst )
        {
            HRESULT hr;
            ptrCoInitEx initFuncEx= (ptrCoInitEx)GetProcAddress( inst, _T("CoInitializeEx"));
            if( initFuncEx)
                hr= initFuncEx( NULL, COINIT_MULTITHREADED);
            else
            {
                ptrCoInit initFunc= (ptrCoInit)GetProcAddress( inst,_T("CoInitialize"));
                if( initFunc)
                    hr= initFunc( NULL);
            }
        }
        oleThreadData.setData((void*)sal_True);
    }
}


//===============================================================================
// EmbedServer_Impl

EmbedServer_Impl::EmbedServer_Impl( const uno::Reference<lang::XMultiServiceFactory>& xFactory):
	m_xFactory( xFactory)
{
	for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
	{
		m_pOLEFactories[nInd] = new EmbedProviderFactory_Impl( m_xFactory, guidList[nInd] );
		m_pOLEFactories[nInd]->registerClass();
	}
}

EmbedServer_Impl::~EmbedServer_Impl()
{
	for( int nInd = 0; nInd < SUPPORTED_FACTORIES_NUM; nInd++ )
	{
		if ( m_pOLEFactories[nInd] )
			m_pOLEFactories[nInd]->deregisterClass();
	}
}

// XInterface --------------------------------------------------
uno::Any SAL_CALL
EmbedServer_Impl::queryInterface(
	const uno::Type& aType )
	throw(
		uno::RuntimeException
	)
{
	uno::Any a=
		::cppu::queryInterface(
			aType, static_cast<lang::XTypeProvider*>(this));
	if( a == uno::Any())
		return OWeakObject::queryInterface( aType);
	else
		return a;
}

void SAL_CALL EmbedServer_Impl::acquire(  ) throw(uno::RuntimeException)
{
	OWeakObject::acquire();
}

void SAL_CALL EmbedServer_Impl::release(  ) throw (uno::RuntimeException)
{
	OWeakObject::release();
}


// XTypeProvider --------------------------------------------------
uno::Sequence< uno::Type > SAL_CALL
EmbedServer_Impl::getTypes( )
	throw(
		uno::RuntimeException
	)
{
	static ::cppu::OTypeCollection *pCollection = 0;
	if( ! pCollection )
	{
		::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
		if( ! pCollection )
		{
			static ::cppu::OTypeCollection collection(
				getCppuType(
					reinterpret_cast<uno::Reference< uno::XWeak>*>(0)),
				getCppuType(
					reinterpret_cast<
					uno::Reference< lang::XTypeProvider>*>(0)));
			pCollection = &collection;
		}
	}
	return (*pCollection).getTypes();
}

uno::Sequence< sal_Int8 > SAL_CALL EmbedServer_Impl::getImplementationId() throw(uno::RuntimeException)
{
	static ::cppu::OImplementationId *pId = 0;
	if( ! pId )
	{
		::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
		if( ! pId )
		{
			static ::cppu::OImplementationId id( sal_False );
			pId = &id;
		}
	}
	return (*pId).getImplementationId();
}

//===============================================================================
// EmbedProviderFactory_Impl

EmbedProviderFactory_Impl::EmbedProviderFactory_Impl(const uno::Reference<lang::XMultiServiceFactory>& xFactory, const GUID* pGuid)
	: m_refCount( 0L )
	, m_xFactory( xFactory )
	, m_guid( *pGuid )
{
}

EmbedProviderFactory_Impl::~EmbedProviderFactory_Impl()
{
}

sal_Bool EmbedProviderFactory_Impl::registerClass()
{
	HRESULT hresult;
	
	o2u_attachCurrentThread();

	hresult = CoRegisterClassObject(				
			m_guid,
			this,
			CLSCTX_LOCAL_SERVER,
			REGCLS_MULTIPLEUSE,
			&m_factoryHandle);
			
	return (hresult == NOERROR);			
}	

sal_Bool EmbedProviderFactory_Impl::deregisterClass()
{
	HRESULT hresult = CoRevokeClassObject( m_factoryHandle );

	return (hresult == NOERROR);			
}	

STDMETHODIMP EmbedProviderFactory_Impl::QueryInterface(REFIID riid, void FAR* FAR* ppv)
{
    if(IsEqualIID(riid, IID_IUnknown))
	{
		AddRef();
		*ppv = (IUnknown*) (IClassFactory*) this;
		return NOERROR;
    } 
    else if (IsEqualIID(riid, IID_IClassFactory))
	{
		AddRef();
		*ppv = (IClassFactory*) this;
		return NOERROR;
	}

    *ppv = NULL;
    return ResultFromScode(E_NOINTERFACE);
}

STDMETHODIMP_(ULONG) EmbedProviderFactory_Impl::AddRef()
{
	return osl_incrementInterlockedCount( &m_refCount);
}

STDMETHODIMP_(ULONG) EmbedProviderFactory_Impl::Release()
{
	::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex());
	sal_Int32 nCount = --m_refCount;
	if ( nCount == 0 )
	{
		delete this;		
	}
	
    return nCount;
}

STDMETHODIMP EmbedProviderFactory_Impl::CreateInstance(IUnknown FAR* punkOuter,
                                                       REFIID riid,
                                                       void FAR* FAR* ppv)
{
    punkOuter = NULL;
	
    IUnknown* pEmbedDocument = (IUnknown*)(IPersistStorage*)( new EmbedDocument_Impl( m_xFactory, &m_guid ) );
    
    return pEmbedDocument->QueryInterface( riid, ppv );
}

STDMETHODIMP EmbedProviderFactory_Impl::LockServer( int /*fLock*/ )
{
    return NOERROR;
}

// Fix strange warnings about some 
// ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
// warning C4505: 'xxx' : unreferenced local function has been removed
#if defined(_MSC_VER)
#pragma warning(disable: 4505)
#endif
