#include <windows.h>
#include "resource.h"
#include "main.h"
#include "cadvsink.h" 

extern UINT cfTimeData, cfThreadId ;
extern HINSTANCE hInst ;

extern CAdviseSink *pFreeAdvSink ;
extern IDataObject *pFreeObj ;

DWORD FreeTransferTime ;
DWORD FreeAdvSkinkReceivedThreadId ;
DWORD FreeNumAdvConnection ;

extern HWND  hMainWnd ;

MyOwnCreateFreeObject (CLSID clsid, DWORD clsctx, HWND hWndOwner)
{
	HRESULT hr ;


/*
Create the object using the specified class ID and context flags.
*/
	hr = CoCreateInstance (
		clsid,NULL,
		clsctx,
		IID_IDataObject,
		(void **) &pFreeObj) ;

/*
Signal failure to user, with error code.
*/
	if (hr != S_OK)
	{
		char out [256] ;
		wsprintf (out, "Couldn't create object\nError code == 0x%x", hr) ;
		MessageBox (hWndOwner, out, "Error", MB_ICONSTOP) ;
	}
/*
If successful, set up information structure about this object.
*/

	else
	{
		FreeTransferTime = 0 ;
		pFreeAdvSink = NULL ;
	}

	InvalidateAllChildWindows ( ) ;
	return 0 ;

}

long WINAPI FreeChildWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
				case ID_DATAOBJECT_CREATENONTHREADEDINPROC:
				{
					CLSID clsid ;
					CLSIDFromProgID (L"EssenceOfOLE.Data6.NonThreaded", &clsid) ;
					
					MyOwnCreateFreeObject (clsid, CLSCTX_INPROC_SERVER, hWnd) ;
					return 0 ;
				}
				case ID_DATAOBJECT_CREATEAPARTMENTTHREADEDINPORC:
				{
					CLSID clsid ;
					CLSIDFromProgID (L"EssenceOfOLE.Data6.ApartmentThreaded", &clsid) ;
					
					MyOwnCreateFreeObject (clsid, CLSCTX_INPROC_SERVER, hWnd) ;
					return 0 ;
				}
				case ID_DATAOBJECT_CREATEAPARTMENTTHREADEDLOCAL:
				{
					CLSID clsid ;
					CLSIDFromProgID (L"EssenceOfOLE.Data6.ApartmentThreadedLocal", &clsid) ;
					
					MyOwnCreateFreeObject (clsid, CLSCTX_LOCAL_SERVER, hWnd) ;
					return 0 ;
				}

				case ID_DATAOBJECT_CREATEFREETHREADEDINPROC:
				{
					CLSID clsid ;
					CLSIDFromProgID (L"EssenceOfOLE.Data6.FreeThreaded", &clsid) ;
					
					MyOwnCreateFreeObject (clsid, CLSCTX_INPROC_SERVER, hWnd) ;
					return 0 ;
				}

				case ID_DATAOBJECT_CREATEFREETHREADEDLOCAL:
				{
					CLSID clsid ;
					CLSIDFromProgID (L"EssenceOfOLE.Data6.FreeThreadedLocal", &clsid) ;
					
					MyOwnCreateFreeObject (clsid, CLSCTX_LOCAL_SERVER, hWnd) ;
					return 0 ;
				}

				case ID_DATAOBJECT_CREATEBOTHINPROC:
				{
					CLSID clsid ;
					CLSIDFromProgID (L"EssenceOfOLE.Data6.BothThreaded", &clsid) ;
					
					MyOwnCreateFreeObject (clsid, CLSCTX_INPROC_SERVER, hWnd) ;
					return 0 ;
				}

				case ID_DATAOBJECT_RELEASE:
				{
					if (pFreeObj != NULL)
					{
						pFreeObj->Release( ) ;
						pFreeObj = NULL ;
					}
					InvalidateAllChildWindows ( ) ;
					return 0 ;
				}

				case ID_DATAOBJECT_GETDATA:
				{
					
				}

				case ID_DATAOBJECT_TIMETEST:
				{
					DialogBoxParam (hInst, MAKEINTRESOURCE(IDD_DIALOG1) ,hWnd, (DLGPROC)TestDlgProc, TRUE) ;
					InvalidateRect (hWnd, NULL, TRUE) ;
					return 0 ;
				}

				case ID_DATAOBJECT_DADVISE:
				{
					CAdviseSink *pAdvSink = new CAdviseSink () ;
					pAdvSink->m_hWnd = hWnd ;
					SetWindowLong (hWnd, 4, (LPARAM)pAdvSink) ;

					FORMATETC fe ;
					fe.cfFormat = cfThreadId ;
					fe.ptd = NULL ;
					fe.dwAspect = DVASPECT_CONTENT ;
					fe.lindex = -1 ;
					fe.tymed = TYMED_HGLOBAL ;

					HRESULT hr = pFreeObj->DAdvise (&fe, 0, pAdvSink, &pAdvSink->m_NumAdvConnection) ;

					return 0 ;
				}

				case ID_DATAOBJECT_DUNADVISE:
				{
					CAdviseSink *pAdvSink = (CAdviseSink *) GetWindowLong (hWnd, 4) ;

					HRESULT hr = pFreeObj->DUnadvise (pAdvSink->m_NumAdvConnection) ;
					pAdvSink->Release ( ) ;
					SetWindowLong (hWnd, 4, 0) ;

					return 0 ;
				}
			}
		}

		
		case WM_PAINT:
		{
			PAINTSTRUCT ps ;
			HDC hDC ;
			char out [256] ;
			int length ;

			
			hDC = BeginPaint (hWnd, &ps) ;

			if (pFreeObj == NULL)
			{
				length = wsprintf (out, "<no object>") ;
				TextOut (hDC, 0, 0, out, length) ;
			}
			else
			{

/*
Call IDataObject::GetData() to make the object report the ID of the
thread on which it receives calls.
*/

				FORMATETC fe ; 	STGMEDIUM stm ;
				DWORD ThreadId = 0xFFFFFFFF, *pdw ;

				fe.cfFormat = cfThreadId ;
				fe.ptd = NULL ;
				fe.dwAspect = DVASPECT_CONTENT ;
				fe.lindex = -1 ;
				fe.tymed = TYMED_HGLOBAL ;

 				if (pFreeObj->GetData (&fe, &stm) == S_OK)
				{
					pdw = (DWORD *)GlobalLock (stm.hGlobal) ;
					ThreadId = *pdw ;
					GlobalUnlock (stm.hGlobal) ;
					ReleaseStgMedium (&stm) ;
				}

				length = wsprintf (out, "Object received last call from this "
					"window on thread ID == 0x%x", ThreadId) ;
				TextOut (hDC, 0, 0, out, length) ;

				length = wsprintf (out, "Transfer Time == %d ms", FreeTransferTime) ;
				TextOut (hDC, 0, 20, out, length) ;
			}
			EndPaint (hWnd, &ps) ;
			return 0 ;
		}

	}

	return DefMDIChildProc (hWnd, message, wParam, lParam) ;
}