// ImplDispatch.cpp (IDispatch for Extending Dynamic HTML Object Model)

#include "stdafx.h"
#include "ImpIDispatch.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Hardcoded information for extending the Object Model 
// Typically this would be supplied through a TypeInfo
// In this case the name "xxyyzz" maps to DISPID_Extend 
const WCHAR pszExtend[10]=L"xxyyzz";

#define DISPID_Extend 12345

CImpIDispatch::CImpIDispatch(void)
{
	m_cRef = 0;
}

CImpIDispatch::~CImpIDispatch(void)
{
	ASSERT(m_cRef == 0);
}

STDMETHODIMP CImpIDispatch::QueryInterface(REFIID riid, void **ppv)
{
	*ppv = NULL;

	if (IID_IDispatch == riid)
		*ppv = this;

	if (NULL != *ppv) {
		((LPUNKNOWN)*ppv)->AddRef();
		return NOERROR;
	}

	return E_NOINTERFACE;
}


STDMETHODIMP_(ULONG) CImpIDispatch::AddRef(void)
{
	return ++m_cRef;
}

STDMETHODIMP_(ULONG) CImpIDispatch::Release(void)
{
	return --m_cRef;
}

STDMETHODIMP CImpIDispatch::GetTypeInfoCount(UINT* /*pctinfo*/)
{
	return E_NOTIMPL;
}

STDMETHODIMP CImpIDispatch::GetTypeInfo(
	/* [in] */ UINT /*iTInfo*/,
	/* [in] */ LCID /*lcid*/,
	/* [out] */ ITypeInfo** /*ppTInfo*/)
{
	return E_NOTIMPL;
}

STDMETHODIMP CImpIDispatch::GetIDsOfNames(
	/* [in] */ REFIID riid,
	/* [size_is][in] */ OLECHAR** rgszNames,
	/* [in] */ UINT cNames,
	/* [in] */ LCID lcid,
	/* [size_is][out] */ DISPID* rgDispId)
{
	HRESULT hr = NOERROR;

	// Hardcoded mapping for this sample
	// A more usual procedure would be to use a TypeInfo
	for (UINT i = 0; i < cNames; i++) {
		if (2 == CompareString(lcid, NORM_IGNOREWIDTH, (char*)pszExtend, 3, (char*)rgszNames[i], 3)) {
			rgDispId[i] = DISPID_Extend;
		}
		else {
			// One or more are unknown so set the return code accordingly
			hr = ResultFromScode(DISP_E_UNKNOWNNAME);
			rgDispId[i] = DISPID_UNKNOWN;
		}
	}

	return hr;
}

STDMETHODIMP CImpIDispatch::Invoke(
	/* [in] */ DISPID dispIdMember,
	/* [in] */ REFIID /*riid*/,
	/* [in] */ LCID /*lcid*/,
	/* [in] */ WORD wFlags,
	/* [out][in] */ DISPPARAMS* pDispParams,
	/* [out] */ VARIANT* pVarResult,
	/* [out] */ EXCEPINFO* /*pExcepInfo*/,
	/* [out] */ UINT* puArgErr)
{
	// For this sample we only support a Property Get on DISPID_Extend
	// returning a BSTR with "Wibble" as the value
	if (dispIdMember == DISPID_Extend) {
		if (wFlags & DISPATCH_PROPERTYGET) {
			if (pVarResult != NULL) {
				WCHAR buff[10] = L"Wibble";
				BSTR bstrRet = SysAllocString(buff);
				VariantInit(pVarResult);
				V_VT(pVarResult)   = VT_BSTR;
				V_BSTR(pVarResult) = bstrRet;
			}
		}
	}

	return S_OK;
}
