#include "headers.h"

// ClassFactory

ClassFactory::ClassFactory()
{
    m_cref = 1;
}

ClassFactory::~ClassFactory()
{
}

HRESULT ClassFactory::Create(ClassFactory * * ppFactory)
{
    AssertOutPtr(ppFactory);
    *ppFactory = new ClassFactory();
    if (NULL == *ppFactory)
        return E_OUTOFMEMORY;
    return S_OK;
}

// IUnknown

STDMETHODIMP ClassFactory::QueryInterface(REFIID riid, void** ppv)
{
    if (ppv == NULL)
        return E_POINTER;
       
    AssertOutPtr(ppv);

    *ppv = NULL;

    if (IsEqualIID(riid, IID_IUnknown))
        *ppv = (IUnknown *) this;
    else if (IsEqualIID(riid, IID_IClassFactory))
        *ppv = (IClassFactory *) this;
    else
        return E_NOINTERFACE;

    this->AddRef();
    return S_OK;
}

STDMETHODIMP_(ULONG) ClassFactory::AddRef(void)
{
    return InterlockedIncrement(&this->m_cref);
}

STDMETHODIMP_(ULONG) ClassFactory::Release(void)
{
    long cref = InterlockedDecrement(&this->m_cref);
    if (0 == cref)
        delete this;
    return cref;
}

// IClassFactory

STDMETHODIMP ClassFactory::LockServer(BOOL fLock)
{
    if (fLock)
        DLLAddLock();
    else
        DLLReleaseLock();
    return S_OK;
}

STDMETHODIMP ClassFactory::CreateInstance(IUnknown * punkOuter, REFIID riid, void * * ppv)
{
    HRESULT hr;
   
    ScriptEngine * pEngine = NULL;

    if (NULL == ppv)
        return E_POINTER;

    AssertOutPtr(ppv);
       
    *ppv = NULL;

    // The engine does not support aggregation
    if (NULL != punkOuter)
        return E_INVALIDARG;

    hr = ScriptEngine::Create(&pEngine);
    if (FAILED(hr))
        goto LError;
   
    hr = pEngine->QueryInterface(riid, ppv);
    if (FAILED(hr))
        goto LError;

    hr = S_OK;

LError:

    if (NULL != pEngine)
        pEngine->Release();

    return hr;
}