#include "CTWMD.h"

LRESULT CALLBACK CTWMDHookProc(INT nCode, WPARAM wParam, LPARAM lParam)
{   
	if(((LPMSG)lParam)->message == WV_CTWMDM)
	{
		((LPCTWMD)(((LPMSG)lParam)->lParam))->lResult = SendMessage(
			((LPCTWMD)(((LPMSG)lParam)->lParam))->hWnd,
			((LPCTWMD)(((LPMSG)lParam)->lParam))->uMsg,
			((LPCTWMD)(((LPMSG)lParam)->lParam))->wParam,
			((LPCTWMD)(((LPMSG)lParam)->lParam))->lParam);
		SetEvent(((LPCTWMD)(((LPMSG)lParam)->lParam))->hMsgProcessed);
		return TRUE;
	}
	else
		return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LPCTWMD CreateCTWMD()
{
	LPCTWMD lpCtwmd = (LPCTWMD)DefAlloc(sizeof(CTWMD));

	lpCtwmd->dwOwnerId		= GetCurrentThreadId();
	lpCtwmd->hMsgProcessed	= CreateEvent(NULL, TRUE, FALSE, NULL);
	if(lpCtwmd->hMsgProcessed == NULL)
	{
		DefFree(lpCtwmd);
		return NULL;
	}

	InitializeCriticalSection(&lpCtwmd->cs);
	lpCtwmd->hhMsgFilter = SetWindowsHookEx(WH_MSGFILTER, CTWMDHookProc, g_hInstance, lpCtwmd->dwOwnerId); 
	return lpCtwmd;
}

LRESULT	SendCTMessage(LPCTWMD lpCtwmd, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	LRESULT lr;	

	EnterCriticalSection(&lpCtwmd->cs);
	lpCtwmd->hWnd	= hWnd;
	lpCtwmd->uMsg	= uMsg;
	lpCtwmd->wParam	= wParam;
	lpCtwmd->lParam	= lParam;
	ResetEvent(lpCtwmd->hMsgProcessed);

	PostThreadMessage(lpCtwmd->dwOwnerId, WV_CTWMDM, 0, (LPARAM)lpCtwmd);
	WaitForSingleObject(lpCtwmd->hMsgProcessed, INFINITE);	

	lr = lpCtwmd->lResult;
	LeaveCriticalSection(&lpCtwmd->cs);

	return lr;
}

BOOL DestroyCTWMD(LPCTWMD lpCtwmd)
{
	if(lpCtwmd->dwOwnerId != GetCurrentThreadId())
		return FALSE;

	UnhookWindowsHookEx(lpCtwmd->hhMsgFilter);

	DeleteCriticalSection(&lpCtwmd->cs);
	CloseHandle(lpCtwmd->hMsgProcessed);

	DefFree(lpCtwmd);
	
	return TRUE;
}