#include "pch.hpp"
//===========================================================================//
// File:	 ErrorDialog.cpp												 //
// Project:  GameOS					                                         //
// Contents: Error Dialogs (Windows resources)								 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 12/19/98  AG     Created													 // 
//																			 //
//---------------------------------------------------------------------------//
// Copyright (C) 1999 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#include "ErrorHandler.hpp"
#include "Windows.hpp"
#include "Registry.hpp"
#include "raid.hpp"



bool SavedOrSent;						// Set true when report has been saved or sent
bool bScreenDump=0;
bool bLogDump=0;
int ScreenImageSize=0;
int LogFileSize=0;
extern DWORD HitScrollLock;

const int ErrorBufferSize=MAX_MESSAGE_SIZE;
extern char BugNotes[MAX_BUG_NOTES];
extern DWORD gLanguageDLL;

int nCopyAnsiToWideChar(LPWORD lpWCStr, LPSTR lpAnsiIn);
LPWORD lpwAlign( LPWORD lpIn);

char* ConvertToCRLF( char* String );

BOOL CALLBACK SimpleErrorDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
BOOL CALLBACK DetailedErrorDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
BOOL CALLBACK RaidDetailProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
static WORD SetDialogFont(LPWORD lpWCStr, UINT uResId = GOS_STR_DIALOG_FONT, char* pszDefFaceName = "MS Sans Serif");
static WORD DialogFontSize();
static WORD SetDialogButton(LPWORD lpWCStr, UINT uButtonId, char* pszDefStr = "<error>");
static char* MyGetResourceString(UINT uId, char* pszDefStr);

WORD DefaultButton;


extern HINSTANCE LibODBC;

#define BUTTON1			0x03e8		// More Details...     More Details...
#define BUTTON2			0x03e9		// Continue            Retry
#define BUTTON3			0x03ea		// Exit                Abort
#define DIALOG_TEXT		0x03eb

BOOL (WINAPI* _GetSaveFileName)( LPOPENFILENAME lpofn );

//
//
// Simple error message dialog - More Detail, Continue or Exit buttons
//
//
BOOL CALLBACK RaidDetailProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch (uMsg)
    {
        case WM_INITDIALOG:
		{
//
// Set tab stops (in dialog units - must be tweaked by hand...)
//
			char Buffer[256];
//
// Generate title of the bug (start bug with app name)
//
			sprintf( Buffer, "%s: %s",ApplicationName,ErrorExceptionText );
			SetWindowText( hDlg, "Enter RAID bug title/description" );
			SetWindowText( GetDlgItem(hDlg,IDC_NOTES), Buffer );
//
// Generate description of the bug
//
			if(Environment.RaidDescTemplate)
			{
				char Buf2[1024];
				Buf2[0] = 0;
				strcpy(Buf2,ConvertToCRLF(Environment.RaidDescTemplate));	
				SetDlgItemText( hDlg, IDC_RAIDDESC,Buf2);
			}

			SetFocus(GetDlgItem(hDlg,IDC_NOTES));
			
			return 0;
		}
//
// Deal with button presses
//
		case WM_COMMAND:                      
		{
			if( LOWORD(wParam)==BUTTON1 || wParam==1 )
			{
				static char Buffer[200];
				static char Buf2[1024];
				GetDlgItemText( hDlg, IDC_NOTES, Buffer, sizeof(Buffer));
				GetDlgItemText( hDlg, IDC_RAIDDESC, Buf2, sizeof(Buf2));
				char* ppParams[2];
				ppParams[0] = Buffer;
				ppParams[1] = Buf2;
				EndDialog( hDlg, (int)ppParams);
			}
			if( LOWORD(wParam)==BUTTON2 )
			{
				EndDialog(hDlg, 0);
			}
 			return 1;
		}
	}
    return FALSE;
}

char* DoRaidDetail( HWND Parent)
{
	WORD*	pDialog=(WORD*)LocalAlloc(LPTR, 2048);
	WORD*	save=pDialog;
	DWORD	style=DS_MODALFRAME|DS_SETFONT|DS_3DLOOK|DS_SETFOREGROUND|DS_CENTER|WS_POPUP|WS_CAPTION;

	*pDialog++ = LOWORD (style);	// Style (Starts at resource file offset 0x40)
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0;					// LOWORD (lExtendedStyle)
	*pDialog++ = 0;					// HIWORD (lExtendedStyle)
	*pDialog++ = 4;					// NumberOfItems
	*pDialog++ = 0;					// x
	*pDialog++ = 0;					// y
	*pDialog++ = 376;				// cx
	*pDialog++ = 97;				// cy
	*pDialog++ = 0;					// Menu
	*pDialog++ = 0;					// Class
//
// Title of dialog
//
	*pDialog++ = 0;
//
// Font
//
	*pDialog++ = DialogFontSize();			// Size
	WORD nchar = SetDialogFont(pDialog);
	pDialog += nchar;
//
//
	DefaultButton=BUTTON1;
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x0000;	// 
	*pDialog++ = 0x5001;	// WS_CHILD | WS_VISIBLE | WS_TABSTOP
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 296;		// x
	*pDialog++ = 4;			// y
	*pDialog++ = 0x0024;	// cx
	*pDialog++ = 12;		// cy
	*pDialog++ = BUTTON1;
	*pDialog++ = 0xffff;	//
	*pDialog++ = 0x0080;	// Type 'Button'
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("OK"));	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	DefaultButton=BUTTON1;
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x0000;
	*pDialog++ = 0x5001;	// WS_CHILD | WS_VISIBLE | WS_TABSTOP
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 336;		// x
	*pDialog++ = 4;			// y
	*pDialog++ = 0x0024;	// cx
	*pDialog++ = 12;		// cy
	*pDialog++ = BUTTON2;
	*pDialog++ = 0xffff;	//
	*pDialog++ = 0x0080;	// Type 'Button'
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("CANCEL"));	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x10c0;	// ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL
	*pDialog++ = 0x5081;	// WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 2;			// x
	*pDialog++ = 4;			// y
	*pDialog++ = 290;		// cx
	*pDialog++ = 12;		// cy
	*pDialog++ = IDC_NOTES;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Edit"));	// Class of item
	pDialog += nchar;
	*pDialog++ = 0;			// Default text
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD

	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x10c4	;	// ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE
	*pDialog++ = 0x50a1;	// WS_CHILD | WS_VISIBLE | WS_BORDER  | WS_VSCROLL | WS_TABSTOP       
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 2;			// x
	*pDialog++ = 20;		// y
	*pDialog++ = 290;		// cx
	*pDialog++ = 64;			// cy
	*pDialog++ = IDC_RAIDDESC;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Edit"));	// Class of item
	pDialog += nchar;
	*pDialog++ = 0;			// Default text
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD

	int result=DialogBoxIndirect( hInstance,(DLGTEMPLATE*)save, Parent, RaidDetailProc );
	LocalFree(LocalHandle(save));
	return (char*)result;
}

//
//
// Color dialog, when not 16 or 32 bit desktop, user is prompted for FullScreen, Continue, Exit
//
//
void DoColorDialog()
{
	WORD*	pDialog=(WORD*)LocalAlloc(LPTR, 2048);
	WORD*	save=pDialog;
	DWORD	style=DS_MODALFRAME|DS_SETFONT|DS_3DLOOK|DS_SETFOREGROUND|DS_CENTER|WS_POPUP;

	*pDialog++ = LOWORD (style);	// Style (Starts at resource file offset 0x40)
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0;					// LOWORD (lExtendedStyle)
	*pDialog++ = 0;					// HIWORD (lExtendedStyle)
	*pDialog++ = 4;					// NumberOfItems
	*pDialog++ = 0;					// x
	*pDialog++ = 0;					// y
	*pDialog++ = 0x18d;				// cx
	*pDialog++ = 0x36;				// cy
	*pDialog++ = 0;					// Menu
	*pDialog++ = 0;					// Class
//
// Title of dialog
//
	*pDialog++ = 0;
//
// Font
//
	*pDialog++ = DialogFontSize();			// Size
	WORD nchar = SetDialogFont(pDialog);
	pDialog += nchar;
//
// Start of items
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x0000;
	*pDialog++ = 0x5001;
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 0x0059;	// x
	*pDialog++ = 0x0025;	// y
	*pDialog++ = 0x0032;	// cx
	*pDialog++ = 0x000e;	// cy
	*pDialog++ = BUTTON2;
	*pDialog++ = 0xffff;	//
	*pDialog++ = 0x0080;	// Type 'Button'
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_FULLSCREEN, "Full Screen");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	DefaultButton=BUTTON1;
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x0000;
	*pDialog++ = 0x5001;
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 0x00ad;	// x
	*pDialog++ = 0x0025;	// y
	*pDialog++ = 0x0032;	// cx
	*pDialog++ = 0x000e;	// cy
	*pDialog++ = BUTTON1;
	*pDialog++ = 0xffff;	//
	*pDialog++ = 0x0080;	// Type 'Button'
	if( ErrorFlags&gos_ErrorRetry )
		nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_RETRY, "Retry");	// Text of item
	else
		nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_CONTINUE, "Continue");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x0000;
	*pDialog++ = 0x5001;
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 0x0101;	// x
	*pDialog++ = 0x0025;	// y
	*pDialog++ = 0x0032;	// cx
	*pDialog++ = 0x000e;	// cy
	*pDialog++ = BUTTON3;
	*pDialog++ = 0xffff;	//
	*pDialog++ = 0x0080;	// Type 'Button'
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_EXIT, "Exit");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
// Text
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x1281;
	*pDialog++ = 0x5002;
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 0x0007;	// x
	*pDialog++ = 0x0007;	// y
	*pDialog++ = 0x017f;	// cx
	*pDialog++ = 0x0018;	// cy
	*pDialog++ = DIALOG_TEXT;	// IDTEXT
	*pDialog++ = 0xffff;	// 
	*pDialog++ = 0x0082;	// Type 'Static Text'
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Static"));	// Class of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	ErrorFlags=0;
	DialogBoxIndirect( hInstance,(DLGTEMPLATE*)save, hWindow, SimpleErrorDialogProc );
	LocalFree(LocalHandle(save));
}






//
//
// Simple error dialog, with only More Detal, Continue or Exit buttons
//
//
void DoSimpleDialog()
{
	WORD*	pDialog=(WORD*)LocalAlloc(LPTR, 2048);
	WORD*	save=pDialog;
	DWORD	style=DS_MODALFRAME|DS_SETFONT|DS_3DLOOK|DS_SETFOREGROUND|DS_CENTER|WS_POPUP;

	*pDialog++ = LOWORD (style);	// Style (Starts at resource file offset 0x40)
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0;					// LOWORD (lExtendedStyle)
	*pDialog++ = 0;					// HIWORD (lExtendedStyle)
	*pDialog++ = 4;					// NumberOfItems
	*pDialog++ = 0;					// x
	*pDialog++ = 0;					// y
	*pDialog++ = 0x18d;				// cx
	*pDialog++ = 0x36;				// cy
	*pDialog++ = 0;					// Menu
	*pDialog++ = 0;					// Class
//
// Title of dialog
//
	*pDialog++ = 0;
//
// Font
//
	*pDialog++ = DialogFontSize();			// Size
	WORD nchar = SetDialogFont(pDialog);
	pDialog += nchar;
//
// Start of items
//
	DefaultButton=BUTTON1;
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x0000;
	*pDialog++ = 0x5001;
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 0x0059;	// x
	*pDialog++ = 0x0023;	// y
	*pDialog++ = 0x003e;	// cx
	*pDialog++ = 0x0010;	// cy
	*pDialog++ = BUTTON1;
	*pDialog++ = 0xffff;	//
	*pDialog++ = 0x0080;	// Type 'Button'
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_MORE_DETAILS, "More Details...");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x0000;
	*pDialog++ = 0x5001;
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 0x00ad;	// x
	*pDialog++ = 0x0023;	// y
	*pDialog++ = 0x003e;	// cx
	*pDialog++ = 0x0010;	// cy
	*pDialog++ = BUTTON2;
	*pDialog++ = 0xffff;	//
	*pDialog++ = 0x0080;	// Type 'Button'
	if( ErrorFlags&gos_ErrorRetry )
		nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_RETRY, "Retry");	// Text of item
	else
		nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_CONTINUE, "Continue");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x0000;
	*pDialog++ = 0x5001;
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 0x0101;	// x
	*pDialog++ = 0x0023;	// y
	*pDialog++ = 0x003e;	// cx
	*pDialog++ = 0x0010;	// cy
	*pDialog++ = BUTTON3;
	*pDialog++ = 0xffff;	//
	*pDialog++ = 0x0080;	// Type 'Button'
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_EXIT, "Exit");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = 0x1281;
	*pDialog++ = 0x5002;
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 0x0007;	// x
	*pDialog++ = 0x0007;	// y
	*pDialog++ = 0x017f;	// cx
	*pDialog++ = 0x0018;	// cy
	*pDialog++ = DIALOG_TEXT;	// IDTEXT
	*pDialog++ = 0xffff;	// 
	*pDialog++ = 0x0082;	// Type 'Static Text'
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Static"));	// Class of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	DialogBoxIndirect( hInstance,(DLGTEMPLATE*)save, hWindow, SimpleErrorDialogProc );
	LocalFree(LocalHandle(save));
}









//
//
// Simple error message dialog - More Detail, Continue or Exit buttons
//
//
BOOL CALLBACK SimpleErrorDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch (uMsg)
    {
        case WM_INITDIALOG:
		{
//
// Set tab stops (in dialog units - must be tweaked by hand...)
//
			SetWindowText( hDlg, "Error" );
			WORD wTabSpacing = 20;
			SendDlgItemMessage(hDlg, DIALOG_TEXT, EM_SETTABSTOPS, 1, (DWORD)&wTabSpacing);
// 
// Only allow a single line for the error message
//
			static char Buffer[256];
			char* Dest=Buffer;
			char* Source=ErrorMessageTitle;
			while( *Source )
			{
				if( *Source==0xa )							// Replace 10 with 13,10
					break;

				*Dest++=*Source;
				Source++;

				if( Dest>=&Buffer[250] )		// Do not allow message overruns
					break;
			}
			*Dest=0;
//
// Send the new text to the edit control
//
			SetDlgItemText( hDlg, DIALOG_TEXT, Buffer );
//
// Enable the Continue and ignore button if not a FATAL error
//
			if( ErrorFlags&gos_ErrorNoContinue )
			{
				EnableWindow(GetDlgItem(hDlg,BUTTON2),FALSE);
			}
//
// Set exit button as default
//
			SetFocus(GetDlgItem(hDlg,BUTTON1));
            return 0;
		}
//
// Deal with button presses
//
		case WM_COMMAND:                      
//
// Check for enter (ID_OK)
//
			if( LOWORD(wParam)==1 )
				wParam=(wParam&0xffff0000)+DefaultButton;
//
// More/Continue or Exit
//
			ErrorReturn=-1;
			if( LOWORD(wParam)==BUTTON1 )
				ErrorReturn=0;
			if( LOWORD(wParam)==BUTTON2 )
				ErrorReturn=1;
			if( LOWORD(wParam)==BUTTON3 )
				ErrorReturn=-1;
			EndDialog( hDlg,0 );
			return 1;
    }
    return FALSE;
}









//
// Error dialog box - described so we don't need to link with windows resources
//
//
void DoDetailedDialog()
{
//
// Boring dialog on Win9x, on Windows 2000 use smaller fonts
//
	WORD ERR_CX=355;
	WORD ERR_CY=186;
	WORD ERR_EDITX=351;
	WORD ERR_EDITY=116;
	WORD ERR_EDIT1Y=125;
	WORD ERR_EDIT1CX=351;
	WORD ERR_EDIT1CY=37;
	WORD ERR_BUTTONY=167;
	WORD ERR_BUTY=14;
#ifndef LAB_ONLY
	WORD ERR_RBUTTONX=78;
	WORD ERR_RBUTTONSTEP=78;
#else
	WORD ERR_BUTTONX=50;
	WORD ERR_BUTTONY1=174;
	WORD ERR_BUTTONSTEP=38;
	WORD ERR_BUTX=36;
	WORD ERR_SMX=44;
	WORD ERR_SMY=8;
#endif

/*	if( WindowsNT )
	{
		ERR_FONT="Terminal";
		ERR_SIZE=8;
		ERR_CX=410;
		ERR_CY=308;
		ERR_EDITX=406;
		ERR_EDITY=230;
		ERR_EDIT1Y=239;
		ERR_EDIT1CX=406;
		ERR_EDIT1CY=40;
		ERR_BUTTONY=284;
		ERR_BUTTONY1=296;
		ERR_BUTTONX=55;
		ERR_BUTTONSTEP=44;
#ifndef LAB_ONLY
		ERR_RBUTTONX=100;
		ERR_RBUTTONSTEP=84;
#endif
		ERR_BUTX=42;
		ERR_BUTY=21;
		ERR_SMX=48;
		ERR_SMY=10;
	}
*/
//
// Now resource data
//
	WORD*	pDialog=(WORD*)LocalAlloc(LPTR, 2048);
	WORD*	save=pDialog;
	DWORD	style=DS_MODALFRAME|DS_SETFONT|DS_3DLOOK|DS_SETFOREGROUND|DS_CENTER|WS_POPUP|WS_CAPTION;
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0;			// LOWORD (lExtendedStyle)
	*pDialog++ = 0;			// HIWORD (lExtendedStyle)
	#ifdef LAB_ONLY
	*pDialog++ = 12;		// NumberOfItems
	#else
	*pDialog++ = 5;			// NumberOfItems
	#endif
	*pDialog++ = 0;			// x
	*pDialog++ = 0;			// y
	*pDialog++ = ERR_CX;	// cx
	*pDialog++ = ERR_CY;	// cy
	*pDialog++ = 0;			// Menu
	*pDialog++ = 0;			// Class
//
// Title of dialog
//
	WORD nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Title 2"));
	pDialog += nchar;
//
// Font
//
	*pDialog++ = DialogFontSize();			// Size
	nchar = SetDialogFont(pDialog, GOS_STR_DIALOG_FONT_FIXED_PITCH, "Courier New");
	pDialog += nchar;
//
// Start of items
//
	#ifdef LAB_ONLY
//
//
	style	   = BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP;
	DefaultButton=IDC_SAVE;
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_BUTTONX+2*ERR_BUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = ERR_BUTX;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_SAVE;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_SAVE, "Save");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	style	   = BS_AUTOCHECKBOX|WS_VISIBLE|WS_CHILD|WS_TABSTOP|WS_GROUP;
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 2;			// x
	*pDialog++ = (WORD)(ERR_BUTTONY-1);		// y
	*pDialog++ = ERR_SMX;		// cx
	*pDialog++ = ERR_SMY;			// cy
	*pDialog++ = IDC_CAPTURESCREEN;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_SAVE_BITMAP, "Save bmp");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	style&=~WS_GROUP;
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 2;			// x
	*pDialog++ = ERR_BUTTONY1;		// y
	*pDialog++ = ERR_SMX;		// cx (72)
	*pDialog++ = ERR_SMY;			// cy
	*pDialog++ = IDC_LOGFILES;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_SAVE_LOG, "Save log");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	style	   = BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP;
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = ERR_BUTTONX;		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = ERR_BUTX;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_REPLAY;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_REPLAY, "Replay");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_BUTTONX+1*ERR_BUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = ERR_BUTX;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_RAID;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_RAID, "Raid");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_BUTTONX+3*ERR_BUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = ERR_BUTX;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_EMAIL;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_EMAIL, "Email");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_BUTTONX+4*ERR_BUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = ERR_BUTX;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_DEBUG;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_DEBUG, "Debug");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_BUTTONX+5*ERR_BUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = ERR_BUTX;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_IGNORE;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_IGNORE, "Ignore");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_BUTTONX+6*ERR_BUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = ERR_BUTX;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_CONTINUE;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	if( ErrorFlags&gos_ErrorRetry )
		nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_RETRY, "Retry");	// Text of item
	else
		nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_CONTINUE, "Continue");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_BUTTONX+7*ERR_BUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = ERR_BUTX;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_EXIT;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_EXIT, "Exit");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	#else
//
// Release version (no save log, no replay, no raid, no debug, no ignore)
//
	style	   = BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP|WS_GROUP;
//
	DefaultButton=IDC_SAVE;
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = ERR_RBUTTONX;		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = 46;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_SAVE;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_SAVE, "Save");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	style&=~WS_GROUP;
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_RBUTTONX+ERR_RBUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = 46;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_CONTINUE;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	if( ErrorFlags&gos_ErrorRetry )
		nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_RETRY, "Retry");	// Text of item
	else
		nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_CONTINUE, "Continue");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = (WORD)(ERR_RBUTTONX+2*ERR_RBUTTONSTEP);		// x
	*pDialog++ = ERR_BUTTONY;		// y
	*pDialog++ = 46;		// cx
	*pDialog++ = ERR_BUTY;		// cy
	*pDialog++ = IDC_EXIT;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Button"));	// Class of item
	pDialog += nchar;
	nchar = SetDialogButton(pDialog, GOS_STR_DIALOG_EXIT, "Exit");	// Text of item
	pDialog += nchar;
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
//
	#endif
//
//
//
	style	= 0x50a008c4;
	style	|=WS_GROUP;
//
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0x204;		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 2;			// x
	*pDialog++ = 5;			// y
	*pDialog++ = ERR_EDITX;	// cx
	*pDialog++ = ERR_EDITY; // cy
	*pDialog++ = IDC_ERRORTEXT;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Edit"));	// Class of item
	pDialog += nchar;
	*pDialog++ = 0;			// Default text
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	style	   = 0x50a010c4;
//
	pDialog	= lpwAlign (pDialog);	// Align dialog to DWORD boundary
	*pDialog++ = LOWORD (style);
	*pDialog++ = HIWORD (style);
	*pDialog++ = 0; 		// LOWORD (lExtendedStyle)
	*pDialog++ = 0; 		// HIWORD (lExtendedStyle)
	*pDialog++ = 2;			// x
	*pDialog++ = ERR_EDIT1Y;		// y
	*pDialog++ = ERR_EDIT1CX;		// cx
	*pDialog++ = ERR_EDIT1CY;		// cy
	*pDialog++ = IDC_NOTES;	// ID
	nchar = (WORD)nCopyAnsiToWideChar(pDialog, TEXT("Edit"));	// Class of item
	pDialog += nchar;
	*pDialog++ = 0;			// Default text
	*pDialog++ = 0;			// advance pointer over nExtraStuff WORD
//
	DialogBoxIndirect( hInstance,(DLGTEMPLATE*)save, hWindow, DetailedErrorDialogProc );
	LocalFree(LocalHandle(save));
}










//
//
// Detailed error message dialog - Email, Debug, Continue, Ignore or Exit buttons
//
//
BOOL CALLBACK DetailedErrorDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch (uMsg)
    {
        case WM_INITDIALOG:
		{
//
// Set exit button as default
//
			SetFocus(GetDlgItem(hDlg,IDC_SAVE));
//
// Set the Screen dump and log dump boxes to their previous settings
//
			SavedOrSent=FALSE;
			#ifdef LAB_ONLY
			SendDlgItemMessage(hDlg, IDC_CAPTURESCREEN, BM_SETCHECK, bScreenDump ? BST_CHECKED : BST_UNCHECKED, 0);
			SendDlgItemMessage(hDlg, IDC_LOGFILES, BM_SETCHECK, bLogDump ? BST_CHECKED : BST_UNCHECKED, 0);
			if( 0!=LogMode )
				EnableWindow(GetDlgItem(hDlg,IDC_LOGFILES),FALSE);
			if( !GotScreenImage )
				EnableWindow(GetDlgItem(hDlg,IDC_CAPTURESCREEN),FALSE);
			if( !IsDebuggerAvailable() )
				EnableWindow(GetDlgItem(hDlg,IDC_DEBUG),FALSE);
			#endif
//
// Set tab stops (in dialog units - must be tweaked by hand...)
//
			SetWindowText( hDlg, "More Details..." );
			WORD wTabSpacing = 20;
			SendDlgItemMessage(hDlg, IDC_ERRORTEXT, EM_SETTABSTOPS, 1, (DWORD)&wTabSpacing);
// 
// Convert edit control text to include 13,10 at the end of each line
//
			static char Buffer[ErrorBufferSize];
			char* Dest=Buffer;
			char* Source=ErrorMessage;
			while( *Source )
			{
				if( *Source==0xa )							// Replace 10 with 13,10
				{
					*Dest++=13;
					*Dest++=10;
				}
				else
					*Dest++=*Source;
				Source++;
				if( Dest>=&Buffer[ErrorBufferSize-4] )		// Do not allow message overruns
					break;
			}
			*Dest=0;
//
// Send the main error text to the edit control
//
			SetDlgItemText( hDlg, IDC_ERRORTEXT, Buffer );
//
// Send any previous user error text to the edit control
//
			SetDlgItemText( hDlg, IDC_NOTES, BugNotes );
//
// Enable the Continue and ignore button if not a FATAL error
//
			if( ErrorFlags&gos_ErrorNoContinue )
			{
				EnableWindow(GetDlgItem(hDlg,IDC_CONTINUE),FALSE);
				EnableWindow(GetDlgItem(hDlg,IDC_IGNORE),FALSE);
			}
//
// Do not allow ignore when RETRY is also set
//
			if( ErrorFlags&gos_ErrorRetry )
			{
				EnableWindow(GetDlgItem(hDlg,IDC_IGNORE),FALSE);
			}
//
// See if on a network and MAPI is present on the machine
//
			char* Mapikey=ReadRegistry( "Software\\Microsoft\\Windows Messaging Subsystem", "MAPI", 1 );

			if( GetSystemMetrics(SM_NETWORK)&1 && Mapikey && *Mapikey=='1' )
				EnableWindow(GetDlgItem(hDlg,IDC_EMAIL),TRUE);
			else
				EnableWindow(GetDlgItem(hDlg,IDC_EMAIL),FALSE);
//
// See if raid feature will function on the machine
//
			//TODO: test for a SQL server driver I can use 
			//BUGBUG: assumption is that GameOS zeroes the environment structure before use
		
	#ifdef LAB_ONLY
			if( (Environment.RaidCustomFields != 0) &&
				(Environment.RaidDataSource != 0) &&
				(Environment.RaidFilePath != 0) &&
				( LibODBC ))
			{
				EnableWindow(GetDlgItem(hDlg,IDC_RAID),TRUE);
			}
			else
			{
				EnableWindow(GetDlgItem(hDlg,IDC_RAID),FALSE);
			}
	#else
			EnableWindow(GetDlgItem(hDlg,IDC_RAID),FALSE);
	#endif
//
// If not doing a game platform version, loggin is disabled
//
			if( Platform!=Platform_Game )
				EnableWindow(GetDlgItem(hDlg,IDC_REPLAY),FALSE);
            return 0;
		}
//
// Deal with button presses
//
		case WM_COMMAND:                      
//
// Check for enter (ID_OK)
//
			if( LOWORD(wParam)==1 )
				wParam=(wParam&0xffff0000)+DefaultButton;
//
// Send mail keeps dialog active
//
			if( LOWORD(wParam)==IDC_EMAIL )
			{
//
// Write out screen dump if requested
//
				bScreenDump=BST_CHECKED==SendDlgItemMessage(hDlg, IDC_CAPTURESCREEN, BM_GETCHECK, 0, 0);
				char*BitmapFile=0;
				if( bScreenDump && GotScreenImage )
				{
					static char BitmapName[MAX_PATH];			// Create bitmap in windows temp directory
					GetTempPath(MAX_PATH,BitmapName);
					strcat(BitmapName,"Screen.bmp");

					HANDLE hFile = CreateFile( BitmapName, GENERIC_WRITE, 0,NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL );
					if( hFile!=INVALID_HANDLE_VALUE )
					{
						DWORD temp=0;
						WriteFile( hFile, GotScreenImage, ScreenImageSize, &temp, NULL );
						CloseHandle( hFile );			// Write out bitmap
						if( temp==ScreenImageSize)
							BitmapFile=BitmapName;
					}
				}
//
// Write out log file if requested
//
				bLogDump=BST_CHECKED==SendDlgItemMessage(hDlg, IDC_LOGFILES, BM_GETCHECK, 0, 0);
				char*LogFile=0;
				if( bLogDump && 0==LogMode )
				{
					static char LogFileName[MAX_PATH];			// Create log file in windows temp directory
					GetTempPath(MAX_PATH,LogFileName);
					strcat(LogFileName,"LogFile.txt");

					if( WriteLogFile( LogFileName ) )
						LogFile=LogFileName;
				}
//
// Create subject for email
//
				char* Mess=GetFullErrorMessage( hDlg );	// Get Notes+Error message

				FixedLengthString Subject(MAX_SUBJECT_LENGTH);
				Subject << "BUG: ";						// ALL subjects start with BUG: for inbox assistant

				char* Notes=GetBugNotes( hDlg );		// 1st line of any notes entered
				if( Notes )
				{
					int Len=0;
					while( *(Notes+Len)!=0 && *(Notes+Len)!=0xd && *(Notes+Len)!=0xa )
						Len++;
					strncat( Subject, Notes, Len );
				}
				else
				{
					Subject << ErrorTitle << " (" << ErrorExceptionText << ")";
				}

//
// Email Error Message and Notes and maybe screen dump and logs
//
				static char CurrentPath[MAX_PATH+1];
				GetCurrentDirectory( MAX_PATH, CurrentPath );
				
				char* Result=SendMail( hDlg, Subject, Mess, BitmapFile, LogFile );

				SetCurrentDirectory( CurrentPath );

				free(Mess);								// Cleanup memory

				if( Result )
					MessageBox( hDlg,Result,"Did not send", MB_OK );
				else
					SavedOrSent=TRUE;
			}
//
// Save text keep dialog active
//
			if( LOWORD(wParam)==IDC_SAVE )
			{
				HINSTANCE LibControl = LoadLibrary( "comdlg32.dll" );

				if( !LibControl )
				{
					return 1;
				}

				_GetSaveFileName = (BOOL (WINAPI*)( LPOPENFILENAME lpofn ))GetProcAddress( LibControl, "GetSaveFileNameA" ); 
				
				bScreenDump=BST_CHECKED==SendDlgItemMessage(hDlg, IDC_CAPTURESCREEN, BM_GETCHECK, 0, 0);
				bLogDump=BST_CHECKED==SendDlgItemMessage(hDlg, IDC_LOGFILES, BM_GETCHECK, 0, 0);

				static OPENFILENAME OpenFileName;
				static TCHAR szFile[MAX_PATH] = "";
				OpenFileName.lStructSize       = sizeof(OPENFILENAME); 
				OpenFileName.hwndOwner         = hDlg; 

				if( (bScreenDump && GotScreenImage) && (bLogDump && 0==LogMode ))
					OpenFileName.lpstrFilter       = "Error Text,Bitmap and Log File (*.txt,*.bmp,*.log)\0*.txt\0\0"; 
				else
				if( bScreenDump && GotScreenImage )
					OpenFileName.lpstrFilter       = "Error Text and Bitmap File (*.txt,*.bmp)\0*.txt\0\0"; 
				else
				if( bLogDump && 0==LogMode )
					OpenFileName.lpstrFilter       = "Error Text and Log File (*.txt,*.log)\0*.txt\0\0"; 
				else
					OpenFileName.lpstrFilter       = "Error Text File (*.txt)\0*.txt\0\0"; 

				OpenFileName.lpstrCustomFilter = NULL;
				OpenFileName.nMaxCustFilter    = 0;
				OpenFileName.nFilterIndex      = 0; 
				OpenFileName.lpstrFile         = szFile; 
				OpenFileName.nMaxFile          = sizeof(szFile); 
				OpenFileName.lpstrFileTitle    = NULL; 
				OpenFileName.nMaxFileTitle     = 0; 
				OpenFileName.lpstrInitialDir   = NULL; 
				OpenFileName.lpstrTitle        = "Save error information"; 
				OpenFileName.nFileOffset       = 0;
				OpenFileName.nFileExtension    = 0; 
				OpenFileName.lpstrDefExt       = "txt"; 
				OpenFileName.Flags             = OFN_EXPLORER | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_LONGNAMES; 

				if (_GetSaveFileName(&OpenFileName)) 
				{ 
//
// Write out error information
//
					bool Failed=0;
					DWORD temp=0;
					HANDLE hFile = CreateFile( OpenFileName.lpstrFile, GENERIC_WRITE, 0,NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL );
					if( hFile!=INVALID_HANDLE_VALUE )
					{
						char* Em=GetFullErrorMessage( hDlg );
						char* EmCRLF=ConvertToCRLF(Em);
						int length=strlen(EmCRLF);				// Get Notes+Error message
						WriteFile( hFile, EmCRLF, length, &temp, NULL );
						free(EmCRLF);
						free(Em);
						CloseHandle( hFile );				// Write out Error information
						if( temp!=length)
							Failed=1;
					}
					else
						Failed=1;
//
// Write out screen dump if requested
//
					if( bScreenDump && GotScreenImage )
					{
						static char BitmapFile[MAX_PATH];
						static char drive[_MAX_DRIVE];
						static char dir[_MAX_DIR];					// Replace extension with .bmp
						static char fname[_MAX_FNAME];
						static char ext[_MAX_EXT];
   						_splitpath(OpenFileName.lpstrFile, drive, dir, fname, ext );
						wsprintf(BitmapFile,"%s%s%s.bmp",drive,dir,fname);

						HANDLE hFile = CreateFile( BitmapFile, GENERIC_WRITE, 0,NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL );
						if( hFile!=INVALID_HANDLE_VALUE )
						{
							WriteFile( hFile, GotScreenImage, ScreenImageSize, &temp, NULL );
							CloseHandle( hFile );			// Write out bitmap
							if( temp!=ScreenImageSize)
								Failed=1;
						}
						else
							Failed=1;
					}
//
// Write out logs if requested
//
					if( bLogDump && 0==LogMode )
					{
						static char LogFile[MAX_PATH];
						static char drive[_MAX_DRIVE];
						static char dir[_MAX_DIR];					// Replace extension with .bmp
						static char fname[_MAX_FNAME];
						static char ext[_MAX_EXT];
   						_splitpath(OpenFileName.lpstrFile, drive, dir, fname, ext );
						wsprintf(LogFile,"%s%s%s.log",drive,dir,fname);

						if( !WriteLogFile( LogFile ) )
							Failed=1;
					}
//
// Unload comdlg32.dll
//
					FreeLibrary( LibControl );
//
// Did any of the writes fail?
//
					if( Failed )
						MessageBox( hDlg, "Error - Not Saved","Save Information", MB_OK );
					else
						SavedOrSent=TRUE;
				}
			}

//
// Raid bug keeps dialog active
//
			if( LOWORD(wParam)==IDC_RAID )
			{
				static RAIDBUG bug;
				static CGOSRaid raid;
				
				//connect to the raid database
				if(raid.Open(Environment.RaidDataSource))
				{
//
// pop up detail window
//					
					char** ppParams = NULL;
					ppParams = (char**)DoRaidDetail(hDlg);

					if( !ppParams )
					{
						raid.Close();
						return true;
					}
					
						//prepare description and title
					static char szDescription[MAX_RAID_DESC];
					static char szTitle[256];

					strcpy(szTitle,ppParams[0]);
					strcpy(szDescription,ppParams[1]);

					//populate default fields
					bug.nAccessibility	= NO;
					bug.nHowFound		= ADHOCGEN;
					bug.nIssueType		= CODEDEF;
					bug.nPriority		= 3;
					bug.nSeverity		= 3;
					bug.nSource			= OTHERSOURCE;
					bug.pszLang			= "English";
					bug.pszOpenedBy		= bug.pszSourceID   = gosGetUserName();
					bug.pszOpenedRev	= Environment.version;
 					bug.pszEnvironment	= GetShortConfig();
					bug.pszTitle		= szTitle;

					//setup default and custom fields and description
					if( (raid.SetDefRaidFields(bug)) &&
						(raid.SetCustFields(Environment.RaidCustomFields)) &&
						(raid.SetDescription(szDescription)) )
					{

						//submit the bug to the raid database
						static char szSubmit[MAXBUFLEN];

						if(raid.Submit(szSubmit))
							MessageBox( hDlg,szSubmit, Environment.applicationName, MB_OK);
					}
				}
				
				//disconnect and clean up resources
				raid.Close();

				if(raid.getErrorString() != NULL)
					MessageBox(hDlg,raid.getErrorString(),"Raid bug submission failed. Details:", MB_OK | MB_ICONEXCLAMATION);

				SavedOrSent=TRUE;
			}
//
// Debug/Continue or Exit
//
			if( LOWORD(wParam)==IDC_DEBUG || 
				LOWORD(wParam)==IDC_CONTINUE || 
				LOWORD(wParam)==IDC_REPLAY || 
				LOWORD(wParam)==IDC_IGNORE || 
				LOWORD(wParam)==IDC_EXIT )
			{
				if( !SavedOrSent && GetBugNotes(hDlg) )
					if( IDNO==MessageBox( hDlg, 
						MyGetResourceString( GOS_STR_DIALOG_SAVE_CONFIRMATION, "Leave without saving or emailing?" ),
						MyGetResourceString( GOS_STR_DIALOG_SAVE_CONFIRMATION_TITLE, "Notes" ),
						MB_YESNO ))
						return 1;
				bScreenDump=BST_CHECKED==SendDlgItemMessage(hDlg, IDC_CAPTURESCREEN, BM_GETCHECK, 0, 0);
				bLogDump=BST_CHECKED==SendDlgItemMessage(hDlg, IDC_LOGFILES, BM_GETCHECK, 0, 0);
				ErrorReturn=LOWORD(wParam);
				EndDialog( hDlg,0 );
			}
			return 1;
    }
    return FALSE;
}

//
// Helper routine for creating a dialog
//
LPWORD lpwAlign( LPWORD lpIn)
{
	ULONG ul;
	ul = (ULONG) lpIn;
	ul +=3;
	ul >>=2;
	ul <<=2;
	return (LPWORD) ul;
}

//
// Convert the string passed to wide ASNI charcters
//
int nCopyAnsiToWideChar(LPWORD lpWCStr, LPSTR lpAnsiIn)
{
	int cchAnsi = lstrlen(lpAnsiIn);
	return MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, lpAnsiIn, cchAnsi, lpWCStr, cchAnsi) + 1;
}

//
// Convert the string passed in to a string containing CR/LF pairs
//
char* ConvertToCRLF( char* String )
{
	char* Source=String;
	DWORD Characters=1;

	while( *Source!=0 )
	{
		if( *Source==0xa )			// Work out length of new string
			Characters++;
		Characters++;
		Source++;
	}

	char* Dest=(char*)malloc(Characters);
	char* Result=Dest;

	Source=String;
	while( *Source!=0 )
	{
		if( *Source==0xa )			// Copy string expanding CR/LF's
			*Dest++=0x0d;
		*Dest++=*Source++;
	}
	*Dest=0;

	return Result;
}

static WORD SetDialogFont(LPWORD lpWCStr, UINT uResId, char* pszDefFaceName)
{
	char szFaceName[LF_FACESIZE + 1];

	char* psz = MyGetResourceString( uResId, pszDefFaceName );
	gosASSERT(psz);
	if (!psz)
		pszDefFaceName = "MS Sans Serif";
	strncpy(szFaceName, psz, LF_FACESIZE);
	szFaceName[LF_FACESIZE] = 0;
	psz = (char*)_mbschr((unsigned char*)szFaceName, '.');
	if (psz)
		*psz = 0;
	return (WORD)nCopyAnsiToWideChar(lpWCStr, szFaceName);
}

static WORD DialogFontSize()
{
	WORD wSize = 0;

	char* psz = MyGetResourceString( GOS_STR_DIALOG_FONT_SIZE, "8" );
	gosASSERT(psz);
	if (!psz)
		return 8;
	wSize = (WORD)atoi(psz);
	if (wSize == 0)
		wSize = 8;
	return wSize;
}

static WORD SetDialogButton(LPWORD lpWCStr, UINT uButtonId, char* pszDefStr)
{
	char* psz = MyGetResourceString( uButtonId, pszDefStr );
	gosASSERT(psz);
	if (!psz)
		psz = gos_GetResourceString( gLanguageDLL, uButtonId );
	return (WORD)nCopyAnsiToWideChar(lpWCStr, psz);
}

static char* MyGetResourceString(UINT uId, char* pszDefStr)
{
	if (gLanguageDLL)
		return gos_GetResourceString( gLanguageDLL, uId );
	else
		return pszDefStr;
}
