// ThunderMk.cpp : Implementation of CThunderMk
#include "stdafx.h"
#include "Thundermoniker.h"
#include "ThunderMk.h"

/////////////////////////////////////////////////////////////////////////////
// CThunderMk


// IMoniker methods

HRESULT STDMETHODCALLTYPE CThunderMk::BindToObject(IBindCtx  *pbc, IMoniker  *pmkToLeft,
		REFIID riidResult, void  **ppvResult)
{
	MessageBox (NULL, L"IMoniker::BindToObject", L"", 0) ;

/*
Parse display name into tokens.
*/

/*
The next token is of the form "PropName=PropVal", no spaces allowed.
The token before the = sign is the name of the property, that after
is the string value of the property.
*/
	
	WCHAR *pPropName, *pPropValue, *pProgID ;

	CComBSTR StringToHack = m_DisplayName ;
	pProgID = wcstok (StringToHack, L" =") ;
	pPropName = wcstok (NULL, L" =") ;
	pPropValue = wcstok (NULL, L" =") ;

	
/*
The first token in the string should be the progID.
Convert to a CLSID and create the object, asking for the IDispatch interface.
*/

	CLSID clsid ;
	CLSIDFromProgID(pProgID, &clsid) ;

	IDispatch *pDisp ;

	HRESULT hr = CoCreateInstance (clsid, NULL, CLSCTX_SERVER, IID_IDispatch, (void **) &pDisp) ;

/*
Call IDispatch::GetIDsOfNames to get the dispatch ID of the property.
*/

	long dwDispatchID ;

	hr = pDisp->GetIDsOfNames (
		IID_NULL,					// reserved
		&pPropName,					// Array of names to get IDs for
		1,        					// # of names in the array
		LOCALE_SYSTEM_DEFAULT,		// System locale
		&dwDispatchID) ;			// Array of IDs to fill on output

/*
Call IDispatch::Invoke to set the value of the property.
*/

	hr = _com_dispatch_propput (pDisp, dwDispatchID, VT_BSTR, CComBSTR (pPropValue)) ;

/*
Give back to caller.
*/

	pDisp->QueryInterface (riidResult, ppvResult) ;

	return S_OK ;
}

HRESULT STDMETHODCALLTYPE CThunderMk::GetDisplayName(IBindCtx  *pbc, IMoniker  *pmkToLeft,
	LPOLESTR  *ppszDisplayName)
{
	MessageBox (NULL, L"IMoniker::GetDisplayName", L"", 0) ;
	return S_OK ;
}
        
HRESULT STDMETHODCALLTYPE CThunderMk::ParseDisplayName(IBindCtx  *pbc,
	IMoniker  *pmkToLeft, LPOLESTR pszDisplayName, ULONG  *pchEaten, IMoniker  **ppmkOut)
{
	MessageBox (NULL, L"IMoniker::ParseDisplayName", L"", 0) ;

/*
Create a new moniker of our own class.
*/

	IThunderMk *pThunderMk = new CComObject <CThunderMk> ;

/*
Use our own custom interface to set its internal display name.
*/

	pThunderMk->put_DisplayName (CComBSTR(pszDisplayName)) ;

/*
Give back the new moniker. It was already AddRef'd by the constructor.
*/

	pThunderMk->QueryInterface (IID_IMoniker, (void**)ppmkOut) ;

/*
Tell the caller that we ate the whole thing.
*/
	*pchEaten = wcslen (pszDisplayName) ;
	return S_OK ;
}
        
        
HRESULT STDMETHODCALLTYPE CThunderMk::Reduce(IBindCtx  *pbc, DWORD dwReduceHowFar,
	IMoniker  * *ppmkToLeft, IMoniker  **ppmkReduced) 
{
	MessageBox (NULL, L"Unexpected CThunderMk::Reduce", L"", 0) ;
	*ppmkReduced = NULL ;
	return E_NOTIMPL ;
}

HRESULT STDMETHODCALLTYPE CThunderMk::ComposeWith( 
            /* [unique][in] */ IMoniker  *pmkRight,
            /* [in] */ BOOL fOnlyIfNotGeneric,
            /* [out] */ IMoniker  * *ppmkComposite) 
{
	MessageBox (NULL, L"IMoniker::ComposeWith", L"", 0) ;

	return S_OK ;
}
        
        
HRESULT STDMETHODCALLTYPE CThunderMk::IsEqual( 
            /* [unique][in] */ IMoniker  *pmkOtherMoniker) 
{
		MessageBox (NULL, L"IMoniker::IsEqual", L"", 0) ;

	return S_OK ;
}
        
HRESULT STDMETHODCALLTYPE CThunderMk::Hash( 
            /* [out] */ DWORD  *pdwHash)
{
		MessageBox (NULL, L"IMoniker::Hash", L"", 0) ;

	return S_OK ;
}
        
HRESULT STDMETHODCALLTYPE CThunderMk::IsRunning( 
            /* [unique][in] */ IBindCtx  *pbc,
            /* [unique][in] */ IMoniker  *pmkToLeft,
            /* [unique][in] */ IMoniker  *pmkNewlyRunning)
{
		MessageBox (NULL, L"IMoniker::IsRunning", L"", 0) ;

	return S_OK ;
};

/******************************************************************
Relatively simple and unintersting methods that I implemented only
because they were easy.
*******************************************************************/

        
/*
Caller is asking what type of system moniker we are. We aren't
any type of system moniker. Return the selection from the MKSYS
enumeration that indicates this.
*/

        
HRESULT STDMETHODCALLTYPE CThunderMk::IsSystemMoniker(DWORD  *pdwMksys) 
{
		MessageBox (NULL, L"IMoniker::IsSystemMoniker", L"", 0) ;

	*pdwMksys = MKSYS_NONE ;
	return S_OK ;
}

/*
Caller is asking for an enumerator of the internal sub-monikers making up this
moniker. As this moniker is not a composite, and therefore never has any such
things, we never have any to give out. The docs say that in this case, you should
return S_OK ("Yes, I understand your request and have complied") and set the
returned enumerator to NULL ("The answer to your request is 'No'."
*/


HRESULT STDMETHODCALLTYPE CThunderMk::Enum(BOOL fForward, IEnumMoniker  **ppenumMoniker)
{
	MessageBox (NULL, L"Unexpected CThunderMk::Enum", L"", 0) ;
	*ppenumMoniker = NULL ;
	return S_OK ;
}
        
/******************************************************************
Unimplemented methods that seem to deal only with the linking case.
******************************************************************/

HRESULT STDMETHODCALLTYPE CThunderMk::BindToStorage(IBindCtx  *pbc,
    IMoniker  *pmkToLeft, REFIID riid, void  **ppvObj)
{
	MessageBox (NULL, L"Unexpected CThunderMk::BindToStorage", L"", 0) ;
	*ppvObj = NULL ;
	return E_NOTIMPL ;
}

HRESULT STDMETHODCALLTYPE CThunderMk::GetTimeOfLastChange(IBindCtx  *pbc, IMoniker  *pmkToLeft,
	FILETIME  *pFileTime) 
{
	MessageBox (NULL, L"Unexpected CThunderMk::GetTimeOfLastChange", L"", 0) ;
	return E_NOTIMPL ;
}
        
HRESULT STDMETHODCALLTYPE CThunderMk::Inverse(IMoniker  * *ppmk)
{
	MessageBox (NULL, L"Unexpected CThunderMk::Inverse", L"", 0) ;
	return E_NOTIMPL ;
}
        
HRESULT STDMETHODCALLTYPE CThunderMk::CommonPrefixWith(IMoniker  *pmkOther, IMoniker  **ppmkPrefix)
{
	MessageBox (NULL, L"Unexpected CThunderMk::CommonPrefixWith", L"", 0) ;
	*ppmkPrefix = NULL ;
	return E_NOTIMPL ;
}
        
HRESULT STDMETHODCALLTYPE CThunderMk::RelativePathTo(IMoniker  *pmkOther, IMoniker  **ppmkRelPath)
{
	MessageBox (NULL, L"Unexpected CThunderMk::RelativePathTo", L"", 0) ;
	*ppmkRelPath = NULL ;
	return E_NOTIMPL ;
}


// IPersistStream Methods


HRESULT STDMETHODCALLTYPE CThunderMk::GetClassID(CLSID *pClassID)
{
		MessageBox (NULL, L"IMoniker::GetClassID", L"", 0) ;

	return E_NOTIMPL ;
}



HRESULT STDMETHODCALLTYPE CThunderMk::IsDirty( void)
{
		MessageBox (NULL, L"IMoniker::IsDirty", L"", 0) ;

	return E_NOTIMPL ;
}


HRESULT STDMETHODCALLTYPE CThunderMk::Load (IStream *pStm)
{
		MessageBox (NULL, L"IMoniker::Load", L"", 0) ;

	return E_NOTIMPL ;
}


HRESULT STDMETHODCALLTYPE CThunderMk::Save (IStream *pStm, BOOL fClearDirty)
{
		MessageBox (NULL, L"IMoniker::Save", L"", 0) ;

	return E_NOTIMPL ;
}


HRESULT STDMETHODCALLTYPE CThunderMk::GetSizeMax(ULARGE_INTEGER *pcbSize)
{
		MessageBox (NULL, L"IMoniker::GetSizeMax", L"", 0) ;

	return E_NOTIMPL ;
}



STDMETHODIMP CThunderMk::get_DisplayName(BSTR *pVal)
{
		MessageBox (NULL, L"IMoniker::GetDisplayName", L"", 0) ;

	*pVal = m_DisplayName ;
	return S_OK;
}

STDMETHODIMP CThunderMk::put_DisplayName(BSTR newVal)
{
		MessageBox (NULL, L"IMoniker::PutDisplayName", L"", 0) ;

	m_DisplayName = newVal ;
	return S_OK;
}
