/*---------------------------------------------------------------------------*/
//       Author : hiyohiyo
//         Mail : hiyohiyo@crystalmark.info
//          Web : https://crystalmark.info/
//      License : MIT License
/*---------------------------------------------------------------------------*/

#include "stdafx.h"
#include "CrystalMark.h"
#include "CrystalMarkDlg.h"
#include "CrystalMarkRetroDlg.h"
#include "DiskBenchRetro.h"

#include <afxmt.h>
#include <winioctl.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")

#pragma warning(disable : 4996)

static CString TestFilePath;
static CString TestFileDir;
static CString DiskSpdExe;

static HANDLE hFile;
static int DiskTestCount;
static UINT64 DiskTestSize;
static int BenchType[2];
static int BenchSize[2];
static int BenchQueues[2];
static int BenchThreads[2];
// static int Affinity;
static int MixRatio;

static void ShowErrorMessage(CString message);
static void Interval(void* dlg);

static BOOL Init(void* dlg);
static void DiskSpd(void* dlg, DISK_SPD_CMD cmd);

static UINT Exit(void* dlg, BOOL forceExit);
static void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
static volatile BOOL WaitFlag;

extern BOOL BenchmarkAll;

#define DISK_SPD_EXE_9X_NT        _T("Resource\\Benchmark\\DiskSpd\\DiskSpd9xNT.exe")

#define DISK_SPD_EXE_32           _T("Resource\\Benchmark\\DiskSpd\\DiskSpd32.exe")
#define DISK_SPD_EXE_64           _T("Resource\\Benchmark\\DiskSpd\\DiskSpd64.exe")
#define DISK_SPD_EXE_32_LEGACY    _T("Resource\\Benchmark\\DiskSpd\\DiskSpd32L.exe")
#define DISK_SPD_EXE_64_LEGACY    _T("Resource\\Benchmark\\DiskSpd\\DiskSpd64L.exe")
#define DISK_SPD_EXE_ARM32        _T("Resource\\Benchmark\\DiskSpd\\DiskSpdA32.exe")
#define DISK_SPD_EXE_ARM64        _T("Resource\\Benchmark\\DiskSpd\\DiskSpdA64.exe")

extern PROCESS_INFORMATION pi;

int ExecAndWait(TCHAR *pszCmd, BOOL bNoWindow, double *latency)
{
	DWORD Code = 0;
	BOOL bSuccess = FALSE;
	STARTUPINFO si;

	memset(&si, 0, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);

	if (bNoWindow) {
		si.dwFlags = STARTF_USESHOWWINDOW;
		si.wShowWindow = SW_HIDE;
	}

	CString name;
	name.Format(_T("CrystalDiskMark%08X"), GetCurrentProcessId());
	DWORD size = 8;

	HANDLE hSharedMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, NULL, size, (LPCTSTR)name);
	if (hSharedMemory != NULL)
	{
		double* pMemory = (double*)MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, size);
		if (pMemory != NULL)
		{
			bSuccess = CreateProcess(NULL, pszCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
			if (bSuccess != TRUE)
			{
				UnmapViewOfFile(pMemory);
				CloseHandle(hSharedMemory);
				return 0;
			}

			WaitForInputIdle(pi.hProcess, INFINITE);
			WaitForSingleObject(pi.hProcess, INFINITE);
			GetExitCodeProcess(pi.hProcess, &Code);

			CloseHandle(pi.hThread);
			CloseHandle(pi.hProcess);

			pi.hProcess = NULL;

			*latency = (double)*pMemory * 1000; // milli sec to micro sec

			UnmapViewOfFile(pMemory);
			CloseHandle(hSharedMemory);
		}
	}

	return Code;
}

void ShowErrorMessage(CString message)
{
	DWORD lastErrorCode = GetLastError();
	CString errorMessage;
	LPVOID lpMessageBuffer = {0};
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, lastErrorCode, 
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL);
	errorMessage.Format(_T("0x%08X:%s"), lastErrorCode, (LPTSTR) lpMessageBuffer);

	AfxMessageBox(message + _T("\r\n") + errorMessage);
	LocalFree( lpMessageBuffer );
}

void Interval(void* dlg)
{
	int intervalTime = ((CCrystalMarkRetroDlg*)dlg)->m_IntervalTime;
	static CString title;

	for (int i = 0; i < intervalTime; i++)
	{
		if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus)
		{
			return;
		}
		title.Format(_T("Interval Time %d/%d sec"), i, intervalTime);
		::PostMessage(((CCrystalMarkRetroDlg*) dlg)->GetSafeHwnd(), WM_UPDATE_MESSAGE, (WPARAM) &title, 0);
		Sleep(1000);
	}
}

UINT ExecDiskBenchAll(LPVOID dlg)
{
	int benchmark = ((CCrystalMarkRetroDlg*)dlg)->m_Benchmark;

	if(Init(dlg))
	{
		if (benchmark & BENCHMARK_READ)
		{
			if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus) { return Exit(dlg, TRUE); }
			DiskSpd(dlg, TEST_READ_0);
			if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus) { return Exit(dlg, TRUE); }
			Interval(dlg);
			if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus) { return Exit(dlg, TRUE); }
			DiskSpd(dlg, TEST_READ_1);
		}
		if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
		{
			if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus) { return Exit(dlg, TRUE); }
			Interval(dlg);
		}
		if (benchmark & BENCHMARK_WRITE)
		{
			if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus) { return Exit(dlg, TRUE); }
			DiskSpd(dlg, TEST_WRITE_0);
			if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus) { return Exit(dlg, TRUE); }
			Interval(dlg);
			if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus) { return Exit(dlg, TRUE); }
			DiskSpd(dlg, TEST_WRITE_1); 
		}
	}
	Exit(dlg, FALSE);
	return 1;
}

BOOL Init(void* dlg)
{
	BOOL FlagArc;
	BOOL result;
	static CString cstr;
	TCHAR drive;

	ULARGE_INTEGER freeBytesAvailableToCaller = {0};
	ULARGE_INTEGER totalNumberOfBytes = { 0 };
	ULARGE_INTEGER totalNumberOfFreeBytes = { 0 };

	// Init m_Ini
	TCHAR *ptrEnd;
	TCHAR temp[MAX_PATH];
	::GetModuleFileName(NULL, temp, MAX_PATH);
	if ((ptrEnd = _tcsrchr(temp, '\\')) != NULL)
	{
		*ptrEnd = '\0';
	}

	pi.hProcess = NULL;

	((CCrystalMarkRetroDlg*)dlg)->m_DiskSpdVersion = _T("DiskSpd 2.0.21a");
#ifdef _M_ARM
	DiskSpdExe.Format(_T("%s\\%s"), temp, DISK_SPD_EXE_ARM32);
#elif _M_ARM64
	DiskSpdExe.Format(_T("%s\\%s"), temp, DISK_SPD_EXE_ARM64);
#elif _M_X64
	if(IsWin8orLater())
	{
		DiskSpdExe.Format(_T("%s\\%s"), temp, DISK_SPD_EXE_64);
	}
	else
	{
		DiskSpdExe.Format(_T("%s\\%s"), temp, DISK_SPD_EXE_64_LEGACY);
		((CCrystalMarkRetroDlg*)dlg)->m_DiskSpdVersion = _T("DiskSpd 2.0.15a");
	}
#else
#if _MSC_VER > 1310
	if (IsWin8orLater())
	{
		DiskSpdExe.Format(_T("%s\\%s"), temp, DISK_SPD_EXE_32);
	}
	else
	{
		DiskSpdExe.Format(_T("%s\\%s"), temp, DISK_SPD_EXE_32_LEGACY);
		((CCrystalMarkRetroDlg*)dlg)->m_DiskSpdVersion = _T("DiskSpd 2.0.15a");
	}
#else
	DiskSpdExe.Format(_T("%s\\%s"), temp, DISK_SPD_EXE_9X_NT);
	((CCrystalMarkRetroDlg*)dlg)->m_DiskSpdVersion = _T("CrystalDiskSpd 1.0.0");
#endif
#endif

	/*
	if (! CheckCodeSign(CERTNAME_DISKSPD, DiskSpdExe))
	{
		AfxMessageBox(((CCrystalMarkRetroDlg*)dlg)->m_MesExeFileModified);
		Exit(dlg);
		return FALSE;
	}
	*/

	if (! IsFileExist(DiskSpdExe))
	{
		AfxMessageBox(((CCrystalMarkRetroDlg*)dlg)->m_MesDiskSpdNotFound);
		return Exit(dlg, TRUE);
	}
	DiskTestCount = ((CCrystalMarkRetroDlg*)dlg)->m_IndexTestCount;
	
	CString testSize = ((CCrystalMarkRetroDlg*)dlg)->m_ValueTestSize;

#if _MSC_VER > 1310
	if (testSize.Find(_T("M")) == -1) // GiB
	{
		DiskTestSize = (UINT64)_tstoi(testSize) * 1024;
	}
	else // MiB
	{
		DiskTestSize = (UINT64)_tstoi(testSize);
	}
	DiskTestCount = 1;
#else
	DiskTestSize = 32;
	DiskTestCount = 1;
#endif

	for (int i = 0; i < 2; i++)
	{
		BenchType[i] = ((CCrystalMarkRetroDlg*)dlg)->m_BenchType[i];
		BenchSize[i] = ((CCrystalMarkRetroDlg*)dlg)->m_BenchSize[i];
		BenchQueues[i] = ((CCrystalMarkRetroDlg*)dlg)->m_BenchQueues[i];
		BenchThreads[i] = ((CCrystalMarkRetroDlg*)dlg)->m_BenchThreads[i];
	}

	CString RootPath;
	// if(((CCrystalMarkRetroDlg*)dlg)->m_MaxIndexTestDrive != ((CCrystalMarkRetroDlg*)dlg)->m_IndexTestDrive)
	{
		drive = ((CCrystalMarkRetroDlg*)dlg)->m_ValueTestDrive.GetAt(0);
		cstr.Format(_T("%C:\\"), drive);
#if _MSC_VER > 1310
		GetDiskFreeSpaceEx(cstr, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes);
#else
		typedef BOOL (WINAPI* FuncGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
		FuncGetDiskFreeSpaceEx pGetDiskFreeSpaceEx = NULL;
		HMODULE hModule = GetModuleHandle(_T("kernel32.dll"));
		if (hModule)
		{
#ifdef UNICODE
			pGetDiskFreeSpaceEx = (FuncGetDiskFreeSpaceEx)GetProcAddress(hModule, "GetDiskFreeSpaceExW");
#else
			pGetDiskFreeSpaceEx = (FuncGetDiskFreeSpaceEx)GetProcAddress(hModule, "GetDiskFreeSpaceExA");
#endif
		}
		if(pGetDiskFreeSpaceEx != NULL)
		{
			pGetDiskFreeSpaceEx(cstr, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes);
		}
		else
		{
			DWORD sectorsPerCluster = 0, bytesPerSector = 0, numberOfFreeClusters = 0, totalNumberOfClusters = 0;
			GetDiskFreeSpace(cstr, &sectorsPerCluster, &bytesPerSector, &numberOfFreeClusters, &totalNumberOfClusters);
			totalNumberOfFreeBytes.QuadPart = (ULONGLONG)numberOfFreeClusters * (ULONGLONG)bytesPerSector * (ULONGLONG)sectorsPerCluster;
		}
#endif
		RootPath.Format(_T("%c:\\"), drive);
	}

	TestFileDir.Format(_T("%sCrystalDiskMark%08X"), (LPCTSTR)RootPath, timeGetTime());
	CreateDirectory(TestFileDir, NULL);
	TestFilePath.Format(_T("%s\\CrystalDiskMark%08X.tmp"), (LPCTSTR)TestFileDir, timeGetTime());

	DWORD FileSystemFlags;
	GetVolumeInformation(RootPath, NULL, NULL, NULL, NULL, &FileSystemFlags, NULL, NULL);
	if(FileSystemFlags & FS_VOL_IS_COMPRESSED)
	{
		FlagArc = TRUE;
	}
	else
	{
		FlagArc = FALSE;
	}

// Check Disk Capacity //
	OSVERSIONINFO osVersionInfo = { 0 };
	osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&osVersionInfo);

	/*
	ULARGE_INTEGER FreeBytesAvailableToCaller, TotalNumberOfBytes, TotalNumberOfFreeBytes;
#if _MSC_VER > 1310
	GetDiskFreeSpaceEx(RootPath, &FreeBytesAvailableToCaller, &TotalNumberOfBytes, &TotalNumberOfFreeBytes);
#else
	GetDiskFreeSpace(RootPath, NULL, NULL, &(TotalNumberOfBytes.LowPart), &(TotalNumberOfFreeBytes.LowPart));
#endif
	*/	

	if(DiskTestSize > totalNumberOfFreeBytes.QuadPart / 1024 / 1024 )
	{
		AfxMessageBox(((CCrystalMarkRetroDlg*)dlg)->m_MesDiskCapacityError);
		((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus = FALSE;
		return FALSE;
	}

	static CString title;
	title.Format(_T("Preparing... Create Test File"));
	::PostMessage(((CCrystalMarkRetroDlg*)dlg)->GetSafeHwnd(), WM_UPDATE_MESSAGE, (WPARAM)& title, 0);

// Preapare Test File
	hFile = ::CreateFile(TestFilePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN, NULL);

	if(hFile == INVALID_HANDLE_VALUE)
	{
		AfxMessageBox(((CCrystalMarkRetroDlg*)dlg)->m_MesDiskCreateFileError);
		((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus = FALSE;
		return FALSE;
	}

// Set End Of File to prevent fragmentation of test file
#if _MSC_VER > 1310
	LARGE_INTEGER nFileSize = {0};
	nFileSize.QuadPart = DiskTestSize * 1024 * 1024;

	LARGE_INTEGER nStart = {0};
	nStart.QuadPart = 0;

	SetFilePointerEx(hFile, nFileSize, NULL, FILE_BEGIN);
	SetEndOfFile(hFile);
	SetFilePointerEx(hFile, nStart, NULL, FILE_BEGIN);
#else
	LONG nFileSize = 1024 * 1024 * (LONG)DiskTestSize;
	LONG nStart = 0;

	SetFilePointer(hFile, (LONG)nFileSize, NULL, FILE_BEGIN);
	SetEndOfFile(hFile);
	SetFilePointer(hFile, (LONG)nStart, NULL, FILE_BEGIN);
#endif

// COMPRESSION_FORMAT_NONE
	USHORT lpInBuffer = COMPRESSION_FORMAT_NONE;
	DWORD lpBytesReturned = 0;
	DeviceIoControl(hFile, FSCTL_SET_COMPRESSION, (LPVOID) &lpInBuffer,
				sizeof(USHORT), NULL, 0, (LPDWORD)&lpBytesReturned, NULL);

// Fill Test Data
	char* buf = NULL;
	int BufSize;
	int Loop;
	DWORD writesize;
#if _MSC_VER > 1310
	BufSize = 1024 * 1024;
#else
	BufSize = 128 * 1024;
#endif
	Loop = (int)DiskTestSize;

	buf = (char*) VirtualAlloc(NULL, BufSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
	if (buf == NULL)
	{
		AfxMessageBox(_T("Failed VirtualAlloc()."));
		((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus = FALSE;
		return FALSE;
	}

	if (((CCrystalMarkRetroDlg*)dlg)->m_TestData == TEST_DATA_ALL0X00)
	{
		for (int i = 0; i < BufSize; i++)
		{
			buf[i] = 0;
		}
	}
	else
	{
		// Compatible with DiskSpd
		for (int i = 0; i < BufSize; i++)
		{
			buf[i] = (char) (rand() % 256);
		}
	}

	for (int i = 0; i < Loop; i++)
	{
		if (((CCrystalMarkDlg*) dlg)->m_BenchStatus)
		{
			result = WriteFile(hFile, buf, BufSize, &writesize, NULL);
		}
		else
		{
			CloseHandle(hFile);
			VirtualFree(buf, 0, MEM_RELEASE);
			((CCrystalMarkDlg*) dlg)->m_BenchStatus = FALSE;
			return FALSE;
		}
	}
	VirtualFree(buf, 0, MEM_RELEASE);
	CloseHandle(hFile);

	return TRUE;
}

void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
	if(idEvent == TIMER_ID)
	{
		WaitFlag = FALSE;
		KillTimer(hwnd, idEvent);
	}
}

UINT Exit(void* dlg, BOOL forceExit)
{
	DeleteFile(TestFilePath);
	RemoveDirectory(TestFileDir);

	static CString cstr;
	cstr = _T("");

	if(((CCrystalMarkRetroDlg*)dlg)->m_TestData == TEST_DATA_ALL0X00)
	{
		cstr = ALL_0X00_0FILL;
	}

	::PostMessage(((CCrystalMarkRetroDlg*)dlg)->GetSafeHwnd(), WM_UPDATE_MESSAGE, (LPARAM)&cstr, NULL);

	if (! BenchmarkAll || forceExit)
	{
		::PostMessage(((CCrystalMarkRetroDlg*)dlg)->GetSafeHwnd(), WM_EXIT_BENCHMARK, 0, 0);
		((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus = FALSE;
		((CCrystalMarkRetroDlg*)dlg)->m_WinThread = NULL;
	}

	return 0;
}

void DiskSpd(void* dlg, DISK_SPD_CMD cmd)
{
	static CString cstr;
	int *maxScore = NULL;
	CString command;
	CString title;
	CString option;
	CString bufOption;

	int duration = 5;
	int index = 0;
	int j = 0;

	if (!((CCrystalMarkRetroDlg*)dlg)->m_BenchStatus)
	{
		return;
	}

#if _MSC_VER > 1310
	if (((CCrystalMarkRetroDlg*)dlg)->m_TestData == TEST_DATA_ALL0X00)
	{
		bufOption += _T(" -Z");
	}
	else
	{
		switch (cmd)
		{
		case TEST_WRITE_0:
		case TEST_WRITE_1:
			index = cmd - TEST_WRITE_0;
			cstr.Format(_T(" -Z%dK"), BenchSize[index]);
			bufOption += cstr;
			break;
		}
	}

	switch (cmd)
	{
	case TEST_READ_0:
	case TEST_READ_1:
		index = cmd - TEST_READ_0;
		if (BenchType[index])
		{
			title.Format(_T("Random Read"));
			option.Format(_T("-b%dK -o%d -t%d -W0 -S -w0 -r"), BenchSize[index], BenchQueues[index], BenchThreads[index]);
		}
		else
		{
			title.Format(_T("Sequential Read"));
			option.Format(_T("-b%dK -o%d -t%d -W0 -S -w0"), BenchSize[index], BenchQueues[index], BenchThreads[index]);
		}
		maxScore = (int*) &(((CCrystalMarkRetroDlg*)dlg)->m_Score[2][index + 1]);
		break;
	case TEST_WRITE_0:
	case TEST_WRITE_1:
		index = cmd - TEST_WRITE_0;
		if (BenchType[index])
		{
			title.Format(_T("Random Write"));
			option.Format(_T("-b%dK -o%d -t%d -W0 -S -w100 -r"), BenchSize[index], BenchQueues[index], BenchThreads[index]);
		}
		else
		{
			title.Format(_T("Sequential Write"));
			option.Format(_T("-b%dK -o%d -t%d -W0 -S -w100"), BenchSize[index], BenchQueues[index], BenchThreads[index]);
		}
		option += bufOption;
		maxScore = (int*) &(((CCrystalMarkRetroDlg*)dlg)->m_Score[2][index + 3]);
		break;
	}

	option += _T(" -ag");
#else

	switch (cmd)
	{
	case TEST_READ_0:
	case TEST_READ_1:
		index = cmd - TEST_READ_0;
		if (BenchType[index])
		{
			title.Format(_T("Random Read"));
			option.Format(_T("1 %d"), DiskTestSize);
		}
		else
		{
			title.Format(_T("Sequential Read"));
			option.Format(_T("0 %d"), DiskTestSize);
		}
		maxScore = (int*)&(((CCrystalMarkRetroDlg*)dlg)->m_Score[2][index + 1]);
		break;
	case TEST_WRITE_0:
	case TEST_WRITE_1:
		index = cmd - TEST_WRITE_0;
		if (BenchType[index])
		{
			title.Format(_T("Random Write"));
			option.Format(_T("3 %d"), DiskTestSize);
		}
		else
		{
			title.Format(_T("Sequential Write"));
			option.Format(_T("2 %d"), DiskTestSize);
		}
		option += bufOption;
		maxScore = (int*)&(((CCrystalMarkRetroDlg*)dlg)->m_Score[2][index + 3]);
		break;
	}

#endif

	int score = 0;
	double latency = 0.0;

	if (maxScore == NULL)
	{
		return ;
	}
	*maxScore = 0;

	for (j = 0; j <= DiskTestCount; j++)
	{

#if _MSC_VER > 1310
		if (j == 0)
		{
			continue;
			// duration = 5;
			// cstr.Format(_T("Preparing... %s"), (LPCTSTR)title);
		}
		else
		{
			duration = ((CCrystalMarkRetroDlg*)dlg)->m_MeasureTime;
			cstr.Format(_T("%s (%d/%d)"), (LPCTSTR)title, j, DiskTestCount);
		}
#else
		if (j == 0)
		{
			continue;
		}
		else
		{
			duration = ((CCrystalMarkRetroDlg*)dlg)->m_MeasureTime;
			cstr.Format(_T("%s"), (LPCTSTR)title);
		}
#endif
		::PostMessage(((CCrystalMarkDlg*)dlg)->GetSafeHwnd(), WM_UPDATE_MESSAGE, (WPARAM)&cstr, 0);

#if _MSC_VER > 1310
		command.Format(_T("\"%s\" %s -d%d -A%d -L \"%s\""), (LPCTSTR)DiskSpdExe, (LPCTSTR)option, duration, GetCurrentProcessId(), (LPCTSTR)TestFilePath);
#else
		command.Format(_T("\"%s\" %s \"%s\""), (LPCTSTR)DiskSpdExe, (LPCTSTR)option, (LPCTSTR)TestFilePath);
#endif
		score = ExecAndWait((TCHAR*)((LPCTSTR)command), TRUE, &latency);
		if (score >= 1000)
		{
			score /= 1000;
		}
		else if(score >= 1)
		{
			score = 1;
		}
		else
		{
			score = 0;
		}

/*
		CString cstr;
		cstr.Format(_T("Score = %d"), score);
		AfxMessageBox(cstr);
*/
#if _MSC_VER > 1310
		if (j > 0 && score > *maxScore)
		{
			*maxScore = score;
			::PostMessage(((CCrystalMarkDlg*) dlg)->GetSafeHwnd(), WM_UPDATE_SCORE, 0, 0);
		}
#else
		*maxScore = score;
		::PostMessage(((CCrystalMarkDlg*)dlg)->GetSafeHwnd(), WM_UPDATE_SCORE, 0, 0);
#endif
		if (!((CCrystalMarkDlg*) dlg)->m_BenchStatus)
		{
			return;
		}
	}
	::PostMessage(((CCrystalMarkDlg*) dlg)->GetSafeHwnd(), WM_UPDATE_SCORE, 0, 0);
}
