/*
**************************************************************************
	Copyright (C) 1995

	Rolling Thunder Computing, Inc.
	25 Heartbreak Rd
	Ipswich MA 01938

  e-mail 73540.3430@compuserve.com
*****************************************************************************
*/


/*
*****************************************************************************
System header files
*****************************************************************************
*/

#include <windows.h>		    /* required for all Windows applications */


/*
*****************************************************************************
Application header files
*****************************************************************************
*/

#include "main.h"
#include "resource.h"
#include "cadvsink.h"

/*
*****************************************************************************
Function prototype files
*****************************************************************************
*/

/*
*****************************************************************************
Global Variables defined here
*****************************************************************************
*/

LPDATAOBJECT lpd = NULL ;
CAdviseSink *pAdvSink = NULL ;
DWORD dwAdviseConnection ;
DWORD LoadTime = 0, TransferTime = 0 ;
					
SYSTEMTIME st ;
DWORD g_AuthenticationLevel, g_ImpersonationLevel ;

                               
/*
*****************************************************************************
EXTERNS ofglobal variables defined in other files
*****************************************************************************
*/

extern HWND	hMainWnd ;
extern HINSTANCE hInst ;


/****************************************************************************

    FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)

    PURPOSE:  Processes messages


****************************************************************************/


UINT cfTimeData, cfTimeTest ;
WCHAR wServerName [256] = L"" ;

static const GUID GUID_TimeData = 
{ 0x3943b650, 0xe0f3, 0x11d0, { 0x91, 0x35, 0x0, 0x60, 0x8c, 0x86, 0xb8, 0x9c } };

long WINAPI MainWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{

		case WM_CREATE:
		{
/*
Register private clipboard formats
*/

			cfTimeData = RegisterClipboardFormat ("TimeDataObject") ;
			cfTimeTest = RegisterClipboardFormat ("TimeTestDataObject") ;
/*
Read default impersonation and authorization levels from the registry.
Store in global variables.
*/
			HKEY hKey ;

			long l = RegOpenKey (HKEY_LOCAL_MACHINE,
				"Software\\Microsoft\\OLE",
				&hKey) ;

			if (l != ERROR_SUCCESS)
			{
				MessageBox (NULL, "Unsuccessful registry open. You must have administrator privileges.", "", 0) ;			
			}


			DWORD size = sizeof (DWORD);

			l = RegQueryValueEx(hKey, "LegacyImpersonationLevel", 
				NULL, NULL, (LPBYTE) &g_ImpersonationLevel, &size) ;
			if (l != ERROR_SUCCESS)
			{
				g_ImpersonationLevel = RPC_C_IMP_LEVEL_IDENTIFY ;
			}


			size = sizeof (DWORD);

			l = RegQueryValueEx(hKey, "LegacyAuthenticationLevel", 
				NULL, NULL, (LPBYTE) &g_AuthenticationLevel, &size) ;
			if (l != ERROR_SUCCESS)
			{
				g_AuthenticationLevel = RPC_C_AUTHN_LEVEL_DEFAULT ;
			}


			return 0 ;
		}

/*
WM_COMMAND is a command from the application menu
*/

		case WM_COMMAND:
		{
                    
			switch (wParam)
			{
				case ID_DATAOBJECT_CREATE:
				{
					HRESULT hr ;

				  	DWORD InitTickCount = GetTickCount ( ) ;

					hr = CoCreateInstance (
						GUID_TimeData,
						NULL,
						CLSCTX_LOCAL_SERVER,
						IID_IDataObject,
						(void **) &lpd) ;

					LoadTime = GetTickCount( ) - InitTickCount ;
					InvalidateRect (hWnd, NULL, TRUE) ;

					if (!SUCCEEDED(hr))
					{
						MessageBox (hWnd, "Couldn't create object", "Error", MB_ICONSTOP) ;
					}
					return 0 ;
				}

				case ID_DATAOBJECT_CREATEDLL:
				{
					HRESULT hr ;

/*
Read class ID from registry key.
*/
					CLSID clsid ;
					hr = CLSIDFromProgID (L"EssenceofOLE.Data3", &clsid) ;
					
					DWORD InitTickCount = GetTickCount ( ) ;

					hr = CoCreateInstance (
						clsid,
						NULL,
						CLSCTX_INPROC_SERVER,
						IID_IDataObject,
						(void **) &lpd) ;

					LoadTime = GetTickCount( ) - InitTickCount ;
					InvalidateRect (hWnd, NULL, TRUE) ;

					if (!SUCCEEDED(hr))
					{
						MessageBox (hWnd, "Couldn't create object", "Error", MB_ICONSTOP) ;
					}
					return 0 ;
				}

				case ID_DATAOBJECT_CREATEFROMREMOTESERVER:
				{
					HRESULT hr ;
				  	DWORD InitTickCount = GetTickCount ( ) ;

					COSERVERINFO si ;

					si.pwszName = wServerName ;
					si.dwReserved1 = 0 ;
					si.pAuthInfo = NULL ; 
					si.dwReserved2 = 0;


					MULTI_QI mqi [1] ;

					mqi [0].pIID = &IID_IDataObject ; 
					mqi [0].pItf = NULL ;
					mqi [0].hr = 0 ;

					hr = CoCreateInstanceEx (
						GUID_TimeData,
						NULL,
						CLSCTX_REMOTE_SERVER,
						&si,
						1,
						mqi) ;

					LoadTime = GetTickCount( ) - InitTickCount ;
					InvalidateRect (hWnd, NULL, TRUE) ;

					if (hr != S_OK)
					{
						MessageBox (hWnd, "Couldn't create object", "Error", MB_ICONSTOP) ;
					}
					else
					{
						lpd = (LPDATAOBJECT) mqi [0].pItf ;
					}
					return 0 ;
				}

				case ID_DATAOBJECT_CREATEFROMFILE:
				{
					OPENFILENAME of ;
					char File [256] ;

					ZeroMemory (&of, sizeof(of)) ;
					File [0] = 0x00 ;

					of.lStructSize = sizeof (of) ;
					of.hwndOwner = hWnd ;
					of.lpstrFile = File ;
					of.nMaxFile = sizeof (File) ;
					of.lpstrFilter = "All files\0*.*\0" ;

					if (GetOpenFileName (&of)) 
					{
						HRESULT hr ;
						
						MULTI_QI mqi [1] ;

						mqi [0].pIID = &IID_IDataObject ; 
						mqi [0].pItf = NULL ;
						mqi [0].hr = 0 ;

						WCHAR WideFileName [80] ;
						MultiByteToWideChar (CP_ACP, 0, File, -1, WideFileName, 80) ;

						hr = CoGetInstanceFromFile (
							NULL,			// remote system
							NULL,			// clsid
							NULL,			// IUnknown for agg
							CLSCTX_SERVER,	// context
							0,				// mode
							WideFileName,	// file name
							1,				// # of MQI
							mqi) ;			// array of MQI

						if (hr != S_OK)
						{
							MessageBox (NULL, "Can't get instance from file", "", 0) ;
						}
						else
						{
							lpd = (LPDATAOBJECT) mqi [0].pItf ;
						}
					}
					return 0 ;
				}

				case ID_DATAOBJECT_RELEASE:
				{
					if (lpd)
					{
						lpd->Release( ) ;
						lpd = NULL ;
					}

					InvalidateRect (hWnd, NULL, TRUE) ;
					return 0 ;
				}

				case ID_DATAOBJECT_SETREMOTESERVER:
				{
					DialogBox (hInst, MAKEINTRESOURCE (IDD_DIALOG2), hWnd, (DLGPROC) ServerNameDlgProc) ;
					return 0 ;
				}
				
				case ID_DATAOBJECT_SETSECURITY:
				{
					if (DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_DIALOG3), hWnd, (DLGPROC) SecurityDlgProc, NULL) == IDOK)
					{
						HRESULT hr = CoInitializeSecurity (
							NULL, -1, 
							NULL, 
							NULL,
							g_AuthenticationLevel,
							g_ImpersonationLevel,
							NULL, EOAC_NONE, NULL) ;

						if (hr != S_OK)
						{
							MessageBox (NULL, "Couldn't initialize security", "", 0) ;
						}

					}
					return 0 ;
				}

				case ID_DATAOBJECT_SETPROXYSECURITY:
				{
					HRESULT hr ;
					MYSECURITYDLGPARMS sdp ;

					hr = CoQueryProxyBlanket (
						lpd,				// proxy to query
						NULL, NULL, NULL,	// don't care about
						&sdp.AuthenticationLevel,	// output of auth level
						&sdp.ImpersonationLevel,	// output of impersonation level
						NULL, NULL) ;		// more don't care


					if (DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_DIALOG3), hWnd, (DLGPROC) SecurityDlgProc, (LPARAM)&sdp) == IDOK)
					{
						hr = CoSetProxyBlanket (
							lpd,
							RPC_C_AUTHN_WINNT,
							RPC_C_AUTHZ_NONE, 
							NULL, 
							sdp.AuthenticationLevel,
							sdp.ImpersonationLevel,
							NULL, 
							EOAC_NONE) ;
					}


					return 0 ;
				}

				case ID_DATAOBJECT_GETDATA:
				{
					if (lpd)
					{
						FORMATETC fe ;
						STGMEDIUM stm ;

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

					  	DWORD InitTickCount = GetTickCount ( ) ;
					 	if (SUCCEEDED(lpd->GetData (&fe, &stm)))
						{
							TransferTime = GetTickCount( ) -  InitTickCount ;
							InvalidateRect (hWnd, NULL, TRUE) ;

							char *cp ;
							cp = (char *)GlobalLock (stm.hGlobal) ;
							memmove (&st, cp, sizeof (st)) ;
							GlobalUnlock (stm.hGlobal) ;
							ReleaseStgMedium (&stm) ;
							InvalidateRect (hWnd, NULL, TRUE) ;
						}
					}

					return 0 ;
				}

				case ID_DATAOBJECT_TIMETEST:
				{
					DialogBox (hInst, MAKEINTRESOURCE(IDD_DIALOG1) ,hWnd, (DLGPROC)TestDlgProc) ;
					return 0 ;
				}

				case ID_DATAOBJECT_DADVISE:
				{
					FORMATETC fe ;
					HRESULT hr ;

					fe.cfFormat = cfTimeData ;
					fe.ptd = NULL ;
					fe.dwAspect = DVASPECT_CONTENT ;
					fe.lindex = -1 ;
					fe.tymed = TYMED_HGLOBAL ;
				
					pAdvSink = new CAdviseSink ( ) ;					
					hr = lpd->DAdvise (&fe, 0, pAdvSink, &dwAdviseConnection) ;

					if (hr != S_OK)
					{
						char out [256] ;
						wsprintf (out, "Advise failed, hr == 0x%x", hr) ;
						MessageBox (NULL, out, "", 0) ;
					}
					return 0 ;
				}

				case ID_DATAOBJECT_DUNADVISE:
				{
					lpd->DUnadvise (dwAdviseConnection) ;
					delete pAdvSink ;
					pAdvSink = NULL ;
					return 0 ;
				}

				case ID_DATAOBJECT_EXIT:
				{
					SendMessage (hWnd, WM_CLOSE, 0, 0L) ;        
					return 0 ;
				}
				
			}

			return 0 ;
		}


		case WM_INITMENU:
		{
			HMENU hMenu ;

			hMenu = GetMenu (hWnd) ;

			if (lpd)
			{
				EnableMenuItem (hMenu, ID_DATAOBJECT_CREATE, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_CREATEDLL, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_CREATEFROMREMOTESERVER, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_CREATEFROMFILE, MF_GRAYED) ;

				
				EnableMenuItem (hMenu, ID_DATAOBJECT_GETDATA, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_TIMETEST, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_RELEASE, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_SETPROXYSECURITY, MF_ENABLED) ;


				if (!pAdvSink)
				{
					EnableMenuItem (hMenu, ID_DATAOBJECT_DADVISE, MF_ENABLED) ;
					EnableMenuItem (hMenu, ID_DATAOBJECT_DUNADVISE, MF_GRAYED) ;
				}
				else
				{
 					EnableMenuItem (hMenu, ID_DATAOBJECT_DADVISE, MF_GRAYED) ;
					EnableMenuItem (hMenu, ID_DATAOBJECT_DUNADVISE, MF_ENABLED) ;
				}
			}
			else
			{
				EnableMenuItem (hMenu, ID_DATAOBJECT_CREATE, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_CREATEDLL, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_CREATEFROMFILE, MF_ENABLED) ;
				if (wServerName [0] != 0x00)
				{
 					EnableMenuItem (hMenu, ID_DATAOBJECT_CREATEFROMREMOTESERVER, MF_ENABLED) ;
				}
				else
				{
 					EnableMenuItem (hMenu, ID_DATAOBJECT_CREATEFROMREMOTESERVER, MF_GRAYED) ;
				}

				EnableMenuItem (hMenu, ID_DATAOBJECT_GETDATA, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_SETPROXYSECURITY, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_TIMETEST, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_DADVISE, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_DUNADVISE, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_DATAOBJECT_RELEASE, MF_GRAYED) ;
			}

			return 0 ;
		}


/*
Shutdown time.  
*/

		case WM_CLOSE:
		{
			DestroyWindow (hWnd) ;
			return 0 ;
		}

	
		case WM_DESTROY:
		{           
		  	PostQuitMessage (0) ;
		  	return 0 ;
		}
		
		case WM_PAINT:
		{
			PAINTSTRUCT ps ;
			HDC hDC ;
			char out [256] ;
			int length ;

			
			hDC = BeginPaint (hWnd, &ps) ;
			
			if (!lpd)
			{
				TextOut (hDC, 0, 0, "<no object>", 11) ;
			}
			else
			{
				length = wsprintf (out, "%2.2d:%2.2d:%2.2d", st.wHour, st.wMinute, st.wSecond) ;
				TextOut (hDC, 0, 0, out, length) ;
			} 

	
			length = wsprintf (out, "Load Time == %d ms", LoadTime) ;
			TextOut (hDC, 0, 100, out, length) ;
			length = wsprintf (out, "Transfer Time == %d ms", TransferTime) ;
			TextOut (hDC, 0, 120, out, length) ;

			EndPaint (hWnd, &ps) ;
			return 0 ;
		}

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


