/*
*********************************************************************
*
*	The Essence of OLE
*
*	Source code sample
*
*	Copyright (c) 1996, Rolling Thunder Computing, Ipswich MA
*
*	e-mail: essence@rollthunder.com
*	CompuServe: 73540,3430
*	Web: http://www.rollthunder.com
*
*	File Name:	CHANLWND.CPP
*
*	Purpose: Main Window Response Function for Custon Interface Client
*
*********************************************************************
*/

#define _WIN32_DCOM

#include <windows.h>
#include <comdef.h>

#include "resource.h"
#include "elizacl.h"
#include "eliza.h"
#include "dualeliza.h"
#include "typelibmarshaled.h"

extern HINSTANCE hInst ;

HWND hOutWnd, hInWnd, hSend ;

IEliza *pEliza = NULL ;

CLSID CLSID_Eliza ;
CLSID CLSID_CustomEliza ;

UINT nReps = 1000 ;
BOOL bUseEliza = FALSE ;
BOOL bTypeLibMarshaled = FALSE ;
BOOL bDual = FALSE ;
BOOL bInProc = FALSE ;


LONG CALLBACK MainWndProc (HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{

	switch (Message)
	{
		case WM_CREATE:
		{
				
/*
Get class ID of Eliza object from registry by name.
*/

			CLSIDFromProgID (L"EssenceOfCOM.Eliza", &CLSID_Eliza) ;
//			CLSIDFromProgID (L"EssenceOfCOM.DualEliza", &CLSID_DualEliza) ;
//			CLSIDFromProgID (L"EssenceOfCOM.TypeLibMarshaledEliza", &CLSID_TypeLibMarshaled) ;

/*
Create windows to record conversations
*/

			hOutWnd = CreateWindow (TEXT("edit"), TEXT(""), 
				WS_CHILD | WS_BORDER | WS_VISIBLE | ES_AUTOHSCROLL,
				20, 30, 450, 30, 
				hWnd, (HMENU) IDC_OUTGOING, hInst, NULL) ;
			SetFocus (hOutWnd) ;

			hInWnd = CreateWindow (TEXT("edit"), TEXT(""),
				WS_CHILD | WS_BORDER | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
				20, 90, 450, 200,
				hWnd, (HMENU) IDC_INCOMING, hInst, NULL) ;

			hSend = CreateWindow (TEXT("button"), TEXT("&Send"), 
				WS_CHILD |  WS_VISIBLE | WS_DISABLED | BS_PUSHBUTTON,
				500, 30, 60, 20,
				hWnd, (HMENU) IDC_SEND, hInst, NULL) ;

			return 0 ;

		}

		case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{

				case ID_ELIZA_CREATEINPROC:
				{
					HRESULT hr ;

					hr = CoCreateInstance (
						CLSID_Eliza, 	// Eliza object ID from registry
						NULL, 			// no aggregation
						CLSCTX_INPROC_SERVER, 	// in-proc server
						IID_IEliza,		// IEliza custom interface ID
						(LPVOID *) &pEliza) ;	// output variable

					if (!SUCCEEDED(hr))
					{
						MessageBox (hWnd, TEXT("Couldn't create in-proc Eliza"), TEXT("Error"), MB_ICONSTOP) ;
					}
					else
					{
						EnableWindow (hSend, TRUE) ;
					}
					bInProc = TRUE ;
					return 0 ;
				}

				case ID_ELIZA_CREATELOCAL:
				{
					HRESULT hr ;

					hr = CoCreateInstance (
						CLSID_Eliza, 	// Eliza object ID
						NULL, 			// no aggregation
						CLSCTX_LOCAL_SERVER, 	// local server
						IID_IEliza,		// IEliza custom interface ID
						(LPVOID *) &pEliza) ;	// output variable

					if (!SUCCEEDED(hr))
					{
						MessageBox (hWnd, TEXT("Couldn't create local Eliza"), TEXT("Error"), MB_ICONSTOP) ;
					}
					else
					{
						EnableWindow (hSend, TRUE) ;
					}
					return 0 ;
				}



				case ID_ELIZA_CREATETYPELIBRARYMARSHALED:
				{
					HRESULT hr ;

					hr = CoCreateInstance (
						CLSID_TypeLibMarshaledEliza, 	// Eliza object ID
						NULL, 			// no aggregation
						CLSCTX_LOCAL_SERVER, 	// local server
						IID_ITypeLibMarshaledEliza,		// IEliza custom interface ID
						(LPVOID *) &pEliza) ;	// output variable

					if (!SUCCEEDED(hr))
					{
						MessageBox (hWnd, TEXT("Couldn't create type library marshaled Eliza"), TEXT("Error"), MB_ICONSTOP) ;
					}
					else
					{
						EnableWindow (hSend, TRUE) ;
						bTypeLibMarshaled = TRUE ;
					}
					return 0 ;
				}

				case ID_ELIZA_CREATEDUAL:
				{
					HRESULT hr ;

					hr = CoCreateInstance (
						CLSID_DualEliza, 	// Eliza object ID
						NULL, 			// no aggregation
						CLSCTX_LOCAL_SERVER, 	// local server
						IID_IDualEliza,		// IEliza custom interface ID
						(LPVOID *) &pEliza) ;	// output variable

					if (!SUCCEEDED(hr))
					{
						MessageBox (hWnd, TEXT("Couldn't create dual Eliza"), TEXT("Error"), MB_ICONSTOP) ;
					}
					else
					{
						EnableWindow (hSend, TRUE) ;
						bDual = TRUE ;
					}
					return 0 ;
				}

				case ID_ELIZA_RELEASE:
				{
					if (pEliza)
					{
						pEliza->Release( ) ;
					}
					pEliza = NULL ;
					EnableWindow (hSend, FALSE) ;
					bTypeLibMarshaled = FALSE ;
					bDual = FALSE ;
					bInProc = FALSE ;

					return 0 ;
				}


				case IDC_SEND:
				{
					TCHAR WinText [256], out [256], in [256]  ;
					int length ;
				
					if (pEliza)
					{
						length = GetWindowText (hOutWnd, WinText, sizeof(WinText)) ;

						wsprintf (out, TEXT("You: %s%c%c"), WinText, 0x0D, 0x0A) ;
						SendMessage (hInWnd, EM_SETSEL, (WPARAM) -1, (LPARAM)-1) ;
						SendMessage (hInWnd, EM_REPLACESEL, 0, (LPARAM) out) ;

						if (bTypeLibMarshaled == TRUE)
						{
							_bstr_t bstrOut = WinText ;
							_bstr_t bstrIn ; 
							BSTR pbstrIn = NULL ;
							HRESULT hre = ((ITypeLibMarshaledEliza *)pEliza)->Complain (bstrOut, &pbstrIn) ;

							bstrIn = pbstrIn ;
							lstrcpy (in, (char *)bstrIn) ;
							SysFreeString (pbstrIn) ;
						}
						else if (bDual == TRUE)
						{
							_bstr_t bstrOut = WinText ;
							_bstr_t bstrIn ;
							BSTR pbstrIn = NULL ;
							HRESULT hre = ((IDualEliza *)pEliza)->Complain (bstrOut, &pbstrIn) ;
							bstrIn = pbstrIn ;
							lstrcpy (in, bstrIn) ;
							SysFreeString (pbstrIn) ;
						}
						else
						{
							HRESULT hr ;
							WCHAR *pwResponse, wComplaint [256]  ;

							MultiByteToWideChar (CP_ACP, 0, WinText, -1, wComplaint, sizeof (wComplaint)) ;

							hr = pEliza->Complain (wComplaint, &pwResponse) ;
							
/*
If call fails for some reason, check to see if there is extended
error information available.
*/
							
							if (hr != S_OK) 
							{

/*
Query for ISupportErrorInfo. If found, ask if the IEliza interface 
provides said error information.
*/
								ISupportErrorInfo *pSEI ;
								if (pEliza->QueryInterface (IID_ISupportErrorInfo, (void **)&pSEI) == S_OK)
								{
									if (pSEI->InterfaceSupportsErrorInfo (IID_IEliza) == S_OK)
									{
/*
Get error info object
*/
										IErrorInfo *pEI ;
										GetErrorInfo (0, &pEI) ;

/*
Get strings from error info and show to user.
*/
										
										BSTR pDesc ;
										BSTR pSrc ;

										pEI->GetDescription (&pDesc) ;
										pEI->GetSource (&pSrc) ;

										_bstr_t descr = pDesc ;
										_bstr_t source = pSrc ;
						
										MessageBox (NULL, (char *) descr, (char *) source, 0) ;

										pEI->Release ( ) ;
										SysFreeString (pDesc) ;
										SysFreeString (pSrc) ;
									}

									pSEI->Release ( ) ;
								}
								return 0 ;
							}

							WideCharToMultiByte (CP_ACP, 0, pwResponse, -1, in, sizeof(in), NULL, NULL) ;
							CoTaskMemFree (pwResponse) ;
						}
																
						SendMessage (hInWnd, EM_SETSEL, (WPARAM) -1, (LPARAM)-1) ;
						SendMessage (hInWnd, EM_REPLACESEL, 0, (LPARAM) in) ;
					}
					
					return 0 ;
				}

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

			return 0 ;
		}

		case WM_INITMENU:
		{
			HMENU hMenu = GetMenu (hWnd) ;

			if (pEliza == NULL)
			{
				EnableMenuItem (hMenu, ID_ELIZA_CREATELOCAL, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_ELIZA_CREATEINPROC, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_ELIZA_CREATETYPELIBRARYMARSHALED, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_ELIZA_CREATEDUAL, MF_ENABLED) ;
				EnableMenuItem (hMenu, ID_ELIZA_RELEASE, MF_GRAYED) ;
			}
			else
			{
				EnableMenuItem (hMenu, ID_ELIZA_CREATELOCAL, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_ELIZA_CREATEINPROC, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_ELIZA_CREATETYPELIBRARYMARSHALED, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_ELIZA_CREATEDUAL, MF_GRAYED) ;
				EnableMenuItem (hMenu, ID_ELIZA_RELEASE, MF_ENABLED) ;
			}

			return 0 ;
		}

		case WM_PAINT:
		{
			HDC hDC ;
			PAINTSTRUCT ps ;

			hDC = BeginPaint (hWnd, &ps) ;

			TextOut (hDC, 10, 10, TEXT("Outgoing Text"), 13) ;
			TextOut (hDC, 10, 70, TEXT("Incoming Text"), 13) ;

			EndPaint (hWnd, &ps) ;
			return 0 ;

		}

		case WM_DESTROY:
		{
			PostQuitMessage (0) ;
			return 0;
		}

		default:
		{
			return DefWindowProc (hWnd, Message, wParam, lParam) ;
		}
	}
}


