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