// ThunderMk.h : Declaration of the CThunderMk

#ifndef __THUNDERMK_H_
#define __THUNDERMK_H_

#include "resource.h"       // main symbols

class CThunderMkFactory ;

/////////////////////////////////////////////////////////////////////////////
// CThunderMk
class ATL_NO_VTABLE CThunderMk : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CThunderMk, &CLSID_ThunderMk>,
	public IDispatchImpl<IThunderMk, &IID_IThunderMk, &LIBID_THUNDERMONIKERLib>,
	public IMoniker
{
public:
	CThunderMk()
	{
	}

	CComBSTR m_DisplayName ;

DECLARE_REGISTRY_RESOURCEID(IDR_THUNDERMK)

DECLARE_CLASSFACTORY_EX (CThunderMkFactory)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CThunderMk)
	COM_INTERFACE_ENTRY(IThunderMk)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IMoniker)
END_COM_MAP()

// IMoniker methods


    public:
        virtual HRESULT STDMETHODCALLTYPE BindToObject (IBindCtx  *pbc,
           IMoniker *pmkToLeft, REFIID riidResult, void  * *ppvResult) ;
        
        virtual HRESULT STDMETHODCALLTYPE BindToStorage (IBindCtx  *pbc, 
			IMoniker  *pmkToLeft, REFIID riid, void  * *ppvObj) ;
        
        virtual HRESULT STDMETHODCALLTYPE Reduce (IBindCtx  *pbc,
            DWORD dwReduceHowFar, IMoniker  * *ppmkToLeft, IMoniker  * *ppmkReduced) ;
        
        virtual HRESULT STDMETHODCALLTYPE ComposeWith (IMoniker  *pmkRight,
            BOOL fOnlyIfNotGeneric, IMoniker  **ppmkComposite) ;
        
        virtual HRESULT STDMETHODCALLTYPE Enum(BOOL fForward, IEnumMoniker  **ppenumMoniker) ;
        
        virtual HRESULT STDMETHODCALLTYPE IsEqual(IMoniker  *pmkOtherMoniker) ;
        
        virtual HRESULT STDMETHODCALLTYPE Hash(DWORD  *pdwHash) ;
        
        virtual HRESULT STDMETHODCALLTYPE IsRunning(IBindCtx  *pbc, IMoniker  *pmkToLeft,
            IMoniker  *pmkNewlyRunning) ;
        
        virtual HRESULT STDMETHODCALLTYPE GetTimeOfLastChange(IBindCtx  *pbc,
           IMoniker  *pmkToLeft, FILETIME  *pFileTime) ;
        
        virtual HRESULT STDMETHODCALLTYPE Inverse(IMoniker  **ppmk) ;
        
        virtual HRESULT STDMETHODCALLTYPE CommonPrefixWith(IMoniker  *pmkOther,
            IMoniker  **ppmkPrefix) ;
        
        virtual HRESULT STDMETHODCALLTYPE RelativePathTo(IMoniker  *pmkOther,
            IMoniker  **ppmkRelPath) ;
        
        virtual HRESULT STDMETHODCALLTYPE GetDisplayName(IBindCtx  *pbc,
            IMoniker  *pmkToLeft, LPOLESTR  *ppszDisplayName) ;
        
        virtual HRESULT STDMETHODCALLTYPE ParseDisplayName(IBindCtx  *pbc,
            IMoniker  *pmkToLeft, LPOLESTR pszDisplayName, ULONG  *pchEaten, IMoniker  **ppmkOut) ;
        
        virtual HRESULT STDMETHODCALLTYPE IsSystemMoniker(DWORD  *pdwMksys) ;


// IPersistStream methods

        virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID) ;
        virtual HRESULT STDMETHODCALLTYPE IsDirty( void) ;
        virtual HRESULT STDMETHODCALLTYPE Load (IStream *pStm) ;
        virtual HRESULT STDMETHODCALLTYPE Save (IStream *pStm, BOOL fClearDirty) ;
        virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize) ;

// IThunderMk
public:
	STDMETHOD(get_DisplayName)(/*[out, retval]*/ BSTR *pVal);
	STDMETHOD(put_DisplayName)(/*[in]*/ BSTR newVal);
};


class ATL_NO_VTABLE CThunderMkFactory : public CComClassFactory,
	public IParseDisplayName
{
public:
	CThunderMkFactory()
	{
	}


DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CThunderMkFactory)
	COM_INTERFACE_ENTRY(IParseDisplayName)
END_COM_MAP()

	HRESULT STDMETHODCALLTYPE ParseDisplayName(IBindCtx *pbc,     
		  LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
	{
		MessageBox (NULL, L"ParseDisplayName", L"", 0) ;

/*
Find the colon. Point to the character after it. Figure out how many
characters we've skipped. 
*/

		WCHAR *pAfterColon = wcschr (pszDisplayName, ':') + 1 ;
		ULONG nPrefixChars = pAfterColon - pszDisplayName ;

/*
Create a Thunder moniker.
*/

		IMonikerPtr pMoniker = new CComObject <CThunderMk> ( ) ;

/*
Pass the remaining display name string to the moniker. Give 
the resulting new moniker back to the caller. 
*/

		ULONG CharsEatenByMoniker ;
		pMoniker->ParseDisplayName(pbc, NULL, pAfterColon, &CharsEatenByMoniker, ppmkOut) ;

/*
Calculate the correct number of eaten characters and give that
back to the caller as well. 
*/
		*pchEaten = nPrefixChars + CharsEatenByMoniker ;
		return S_OK ;
	}
 
public:
};
#endif //__THUNDERMK_H_
