//*****************************************************************************
//*  DllCom.cpp                                                               *
//*****************************************************************************
//*                                                                           *
//* This file contains the communication functions for the TUT dll            *
//*                                                                           *
//*****************************************************************************
//* Author : Alexis Vaisse                                                    *
//*****************************************************************************


#include "stdafx.h"
#include "afxdllx.h"    

#include "ACP_Base.h"
#include "ITF.h"
#include "..\..\..\Main\Inc\_EditID.h"

#include "TUT.h"
#include "TutInter.hpp"
#include "..\TutLib\Inc\Tut_Mngr.hpp"


//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------

static char	*                           gs_p_szCPAVersion   = C_szCPAVersion;
static AFX_EXTENSION_MODULE NEAR        extensionDLL        = { NULL, NULL };

#ifdef DLL_ONLY_ONE_INSTANCE
static TUT_Interface *                  gs_p_oTUT_Interface = NULL;
#endif 

static CList<CPA_DLLBase*,CPA_DLLBase*> g_oListOfInstances;


//-----------------------------------------------------------------------------
// functions that are present in all DLL :
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// fn_p_szGetCPAVersion : Get current CPA version
//-----------------------------------------------------------------------------
extern "C" char __declspec(dllexport) *fn_p_szGetCPAVersion(void)
{
    return gs_p_szCPAVersion;
}

//-----------------------------------------------------------------------------
// fn_p_stGetDLLIdentity : Get type of this DLL
//-----------------------------------------------------------------------------
extern "C" tdstDLLIdentity __declspec (dllexport) * fn_p_stGetDLLIdentity (void)
{
    g_stTUT_Identity . eType               = TOOL_DLL;
    g_stTUT_Identity . csName              = C_szDLLTutorialName; 
    g_stTUT_Identity . hModule             = NULL;
    g_stTUT_Identity . p_oListOfInstances  = & g_oListOfInstances;

	return & g_stTUT_Identity;
}

//-----------------------------------------------------------------------------
// fn_vInitDll : DLL init function
//-----------------------------------------------------------------------------
extern "C" void __declspec(dllexport) fn_vInitDll (void)
{
	new CDynLinkLibrary (extensionDLL);
}

//-----------------------------------------------------------------------------
// DllMain : DLL entry point
//-----------------------------------------------------------------------------
extern "C" int __stdcall DllMain (HINSTANCE hInstance , DWORD dwReason , LPVOID lpReserved)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{
		if (! AfxInitExtensionModule (extensionDLL , hInstance))  return 0;
	}
	return 1;
}

//-----------------------------------------------------------------------------
// fn_p_oGetDLL : Get the DLL
//-----------------------------------------------------------------------------
extern "C" CPA_DLLBase __declspec(dllexport) * fn_p_oGetDLL (long lKey)
{
#ifdef DLL_ONLY_ONE_INSTANCE

	switch(lKey)
	{
	case 0:	// the game world
		if (gs_p_oTUT_Interface == NULL)
		{
			gs_p_oTUT_Interface = new TUT_Interface ();
			ASSERT(gs_p_oTUT_Interface != NULL);
		}
		return gs_p_oTUT_Interface;
		break;

	default:
		return NULL;
	}

#else //DLL_ONLY_ONE_INSTANCE

	switch(lKey)
	{
	case 0:	// the game world
		return new TUT_Interface ();
		break;

	default:
		return NULL;
	}

#endif //DLL_ONLY_ONE_INSTANCE
}

#undef DLL_ONLY_ONE_INSTANCE

//-----------------------------------------------------------------------------
// fn_vRegisterControl : Register a control
//-----------------------------------------------------------------------------
void __declspec(dllexport) fn_vRegisterControl (HWND _hWnd , const CString _csName , TUT_tdeControlType _eType)
{
    TUT_g_oTutorialManager . m_fn_vRegisterWnd (_hWnd , _csName , (TUT_tdeWndType) _eType);
}

//-----------------------------------------------------------------------------
// fn_bUnregisterControl : Unregister a control
//-----------------------------------------------------------------------------
BOOL __declspec(dllexport) fn_bUnregisterControl (HWND _hWnd)
{
    return TUT_g_oTutorialManager . m_fn_bUnregisterWnd (_hWnd);
}

/*****************************************************************************\
* SpyGetMsgProc
*
* The Get Message hook function.
*
\*****************************************************************************/
LRESULT CALLBACK SpyGetMsgProc(INT hc, WPARAM wParam, LPARAM lParam)
{
    PMSG pmsg;

    pmsg = (PMSG)lParam;

    if (hc >= 0 && pmsg && pmsg->hwnd)
    {
        return TUT_g_oTutorialManager . m_fn_bHookMsgProc(pmsg->hwnd, pmsg->message, pmsg->wParam, pmsg->lParam);
    }

    //
    // Note that CallNextHookEx ignores the first parameter (hhook) so
    // it is acceptable (barely) to pass in a NULL.
    //
    return CallNextHookEx(NULL, hc, wParam, lParam);
}

/*****************************************************************************\
* SpyGetMsgProc
*
* The Get Message hook function.
*
\*****************************************************************************/
LRESULT CALLBACK SpyGetWndProc(INT hc, WPARAM wParam, LPARAM lParam)
{
    PCWPSTRUCT pcwps;

    pcwps = (PCWPSTRUCT)lParam;

    if (hc >= 0 && pcwps && pcwps->hwnd)
    {
        return TUT_g_oTutorialManager . m_fn_bHookWndProc(pcwps->hwnd, pcwps->message, pcwps->wParam, pcwps->lParam);
    }

    //
    // Note that CallNextHookEx ignores the first parameter (hhook) so
    // it is acceptable (barely) to pass in a NULL.
    //
    return CallNextHookEx(NULL, hc, wParam, lParam);
}

/*****************************************************************************\
* SpyGetMsgProc
*
* The Get Message hook function.
*
\*****************************************************************************/
LRESULT CALLBACK SpyGetWndProcRet(INT hc, WPARAM wParam, LPARAM lParam)
{
    PCWPRETSTRUCT pcwpret;

    pcwpret = (PCWPRETSTRUCT)lParam;

    if (hc >= 0 && pcwpret && pcwpret->hwnd)
    {
        return TUT_g_oTutorialManager . m_fn_bHookWndProcRet(pcwpret->hwnd, pcwpret->message, pcwpret->wParam, pcwpret->lParam);
    }

    //
    // Note that CallNextHookEx ignores the first parameter (hhook) so
    // it is acceptable (barely) to pass in a NULL.
    //
    return CallNextHookEx(NULL, hc, wParam, lParam);
}
