#include "stdafx.h"
#include "solitairehighscore.h"
#include "aboutdlg.h"
#include "settingsdlg.h"
#include "ntray.h"
#include "MainFrm.h"
#include "usernamedlg.h"
#include "highscoredlg.h"
#include <afxdisp.h> // MFC Automation classes
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////// Implementation /////////////////////////////////
////////////////////////////////////// Message map /////////////////////////////////
BEGIN_MESSAGE_MAP(CSolitaireHighscoreApp, CWinAppEx)
//{{AFX_MSG_MAP(CSolitaireHighscoreApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
ON_COMMAND(ID_APP_CHECKHIGHSCORE, OnCheckHighscore)
ON_COMMAND(ID_APP_SHOWSCORES, OnShowHighscores)
ON_COMMAND(ID_APP_NOTSCORE, OnNotScore)
ON_COMMAND(ID_APP_HELP, OnHelp)
ON_COMMAND(ID_APP_SETTINGS, OnSettings)
ON_COMMAND(ID_APP_STARTSOLITAIRE, OnStartSolitaire)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////// Construction /////////////////////////////////
STHighscoreManager::InstPtr STHighscoreManager::sm_ptr;
CSolitaireHighscoreApp::CSolitaireHighscoreApp()
{
m_hsMgr = STHighscoreManager::Instance();
m_hsMgr->OnHighscoreCreatedEvent += new HighscoreEvent::T<CSolitaireHighscoreApp>(this, &CSolitaireHighscoreApp::OnHighscoreCreated);
m_hsMgr->OnNotHighscoreEvent += new HighscoreEvent::T<CSolitaireHighscoreApp>(this, &CSolitaireHighscoreApp::OnNotHighscore);
m_hsMgr->OnHighscoreDeletedEvent += new HighscoreEvent::T<CSolitaireHighscoreApp>(this, &CSolitaireHighscoreApp::OnHighscoreDeleted);
}
////////////////////////////////////// App instance /////////////////////////////////
CSolitaireHighscoreApp theApp;
BOOL CSolitaireHighscoreApp::InitInstance()
{
if(!CWinAppEx::InitInstance( _T("{AF7CDDE4-8CD4-4f87-8834-F83C72939EA0}")))
return FALSE;
CMainFrame* pMainFrame = new CMainFrame;
m_pMainWnd = pMainFrame;
if (!pMainFrame->Create(NULL,SOLITAIRE_NAME))
return FALSE;
// application settings
m_setMgr.Init();
m_setMgr.ReadSettings();
if (m_setMgr.GetFirstRun())
{
OnNotScore();
m_setMgr.SetFirstRun(FALSE);
m_setMgr.SetStartup(TRUE);
m_setMgr.SetStartSolitaire(TRUE);
}
if (m_setMgr.GetStartSolitaire())
{
StartSolitaire(TRUE);
// we can leave a place here to load best highscore...
}
m_pMainWnd->ShowWindow(SW_HIDE);
m_pMainWnd->UpdateWindow();
return TRUE;
}
////////////////////////////////////// App overrides /////////////////////////////////
BOOL CSolitaireHighscoreApp::PreTranslateMessage(MSG* pMsg)
{
if( pMsg->message == WM_KEYDOWN )
{
if (CTRL_W == pMsg->wParam) // CTRL + W down
{
WriteDefDeal();
}
}
return CWinAppEx::PreTranslateMessage(pMsg);
}
////////////////////////////////////// Menu handlers /////////////////////////////////
void CSolitaireHighscoreApp::OnAppAbout()
{
//Show the window
CAboutDlg aboutdlg;
((CMainFrame*)m_pMainWnd)->EnableMenu(FALSE);
aboutdlg.DoModal();
((CMainFrame*)m_pMainWnd)->EnableMenu(TRUE);
}
void CSolitaireHighscoreApp::OnCheckHighscore()
{
CheckHighscore();
}
void CSolitaireHighscoreApp::OnShowHighscores()
{
((CMainFrame*)m_pMainWnd)->EnableMenu(FALSE);
CHighscoreDlg dlg;
dlg.OnLoadHighScoreEvent += new LoadHighscoreEvent::T<CSolitaireHighscoreApp>(this, &CSolitaireHighscoreApp::OnLoadHighscore);
dlg.DoModal();
((CMainFrame*)m_pMainWnd)->EnableMenu(TRUE);
}
void CSolitaireHighscoreApp::OnHelp()
{
CString error;
CString strFileName = CString(m_pszHelpFilePath).TrimRight(_T(".HLP"))+".htm";
error.Format(_T("Error openning file : \r\n%s"),strFileName);
// open help file
if( (int)(ShellExecute(NULL,
CString("open"),
strFileName,
NULL,
NULL,
0)) <= 32 )
ShowMessageBox(error, MB_OK|MB_ICONEXCLAMATION);
}
void CSolitaireHighscoreApp::OnNotScore()
{
int icon = MB_OKCANCEL|MB_ICONINFORMATION;
if (m_setMgr.GetFirstRun())
icon = MB_OK|MB_ICONINFORMATION;
CString msg;
msg.Format(_T("%s will try and scan MS Solitaire.\r\nIf MS Solitaire is running, please close it.\r\nPlease wait until the scan is complete."), SOLITAIRE_NAME);
if (ShowMessageBox(msg, icon) == IDOK)
{
icon = MB_OK|MB_ICONEXCLAMATION;
((CMainFrame*)m_pMainWnd)->EnableMenu(FALSE);
int nRes = ScanForAddresses();
if (nRes == RES_SUCC_ALL)
{
icon = MB_OK|MB_ICONINFORMATION;
msg = _T("Scan succeeded.\r\nPlease try checking highscore again now.");
}
if (nRes == RES_SOL_NOT_RUN)
msg.Format(IDS_SOLNOTRUNNING);
if ((nRes & RES_FAIL_SCORE) != 0)
msg = _T("Scan failed.\r\nPlease contact support (click About...)");
/*if ((nRes & RES_FAIL_DEAL) != 0)
msg = _T("Scan failed.\r\nPlease contact support (click About...)");*/
ShowMessageBox(msg, icon);
((CMainFrame*)m_pMainWnd)->EnableMenu(TRUE);
}
}
void CSolitaireHighscoreApp::OnSettings()
{
// init setting dialog
CSettingsDlg setdlg;
setdlg.UserName = m_setMgr.GetUserName();
setdlg.Startup = m_setMgr.GetStartup();
setdlg.StartSolitaire = m_setMgr.GetStartSolitaire();
((CMainFrame*)m_pMainWnd)->EnableMenu(FALSE);
//Show the window
if (setdlg.DoModal() == IDOK)
{
m_setMgr.SetStartup(setdlg.Startup);
m_setMgr.SetStartSolitaire(setdlg.StartSolitaire);
m_setMgr.SetUserName(setdlg.UserName);
}
((CMainFrame*)m_pMainWnd)->EnableMenu(TRUE);
}
void CSolitaireHighscoreApp::OnStartSolitaire()
{
((CMainFrame*)m_pMainWnd)->EnableMenu(FALSE);
StartSolitaire(TRUE);
((CMainFrame*)m_pMainWnd)->EnableMenu(TRUE);
}
////////////////////////////////////// Score handlers /////////////////////////////////
#pragma warning(disable:4100)
void CSolitaireHighscoreApp::OnHighscoreCreated(long lScore)
{
// we could call update only once after show and then we don't
// need the on deleted call, but this is the correct way, since
// we are not certain that we didn't delete scores elsewhere.
m_setMgr.UpdateHighscoreSettings();
OnShowHighscores();
}
void CSolitaireHighscoreApp::OnNotHighscore(long lScore)
{
CString msg;
if (lScore > 0)
msg.Format(_T("Sorry.\r\n%d is not a highscore"), lScore);
else
msg.Format(_T("%d is not a highscore it's a low score.\r\nTry again when your score is above 0."), lScore);
ShowMessageBox(msg, MB_OK|MB_ICONINFORMATION);
}
void CSolitaireHighscoreApp::OnHighscoreDeleted(long lScore)
{
m_setMgr.UpdateHighscoreSettings();
}
#pragma warning(default:4100)
void CSolitaireHighscoreApp::OnLoadHighscore(long lScore)
{
HANDLE hProc = m_procMgr.GetProcessHandle(SOLITAIRE_EXE);
if (hProc != NULL)
{
m_procMgr.WriteProcessAddress(hProc, m_setMgr.GetScoreAddress(), lScore);
HWND hWnd = FindSolitaireWindow();
if (hWnd != NULL)
{ // will cause a redraw
SendMessage(hWnd, WM_SIZE, SIZE_MINIMIZED, 0);
}
m_procMgr.CloseProcess(hProc);
}
else
{
CString msg;
msg.Format(IDS_SOLNOTRUNNING);
ShowMessageBox(msg, MB_OK|MB_ICONEXCLAMATION);
}
}////////////////////////////////////// What's this??? /////////////////////////////////
void CSolitaireHighscoreApp::WriteDefDeal()
{
if (m_setMgr.GetDefaultDealValue() == -52)
m_setMgr.SetDefaultDealValue(100);
else
m_setMgr.SetDefaultDealValue(-52);
HANDLE hProc = m_procMgr.GetProcessHandle(SOLITAIRE_EXE);
if (hProc != NULL)
{
m_procMgr.WriteProcessAddress(hProc, DEALSUB_DEF_ADDR, m_setMgr.GetDefaultDealValue());
m_procMgr.CloseProcess(hProc);
}
}
////////////////////////////////////// Helper functions /////////////////////////////////
int CSolitaireHighscoreApp::ShowMessageBox(const CString& msg, UINT nType)
{
int iRes = 0;
((CMainFrame*)m_pMainWnd)->EnableMenu(FALSE);
iRes = m_pMainWnd->MessageBox(msg, SOLITAIRE_NAME, nType);
((CMainFrame*)m_pMainWnd)->EnableMenu(TRUE);
return iRes;
}
void CSolitaireHighscoreApp::CheckHighscore()
{
HANDLE hProc = m_procMgr.GetProcessHandle(SOLITAIRE_EXE);
if (hProc != NULL)
{
long lScore = m_procMgr.ReadProcessAddress(hProc, m_setMgr.GetScoreAddress());
m_hsMgr->CreateHighscore(m_setMgr.GetUserName(), lScore);
m_procMgr.CloseProcess(hProc);
}
else
{
CString msg;
msg.Format(IDS_SOLNOTRUNNING);
ShowMessageBox(msg, MB_OK|MB_ICONEXCLAMATION);
}
}
BOOL CSolitaireHighscoreApp::StartSolitaire(BOOL bShow)
{
HANDLE hProc = NULL;
TCHAR szPath[MAX_PATH] = {'\0'};
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, szPath)))
{
PathAppend(szPath, TEXT(SOLITAIRE_EXE));
CString fileName(szPath);
hProc = m_procMgr.CreateNewProcess(fileName, bShow);
}
return (hProc != NULL);
}
void CSolitaireHighscoreApp::PostSolitaireDealMsg()
{
HWND hWnd = FindSolitaireWindow();
if (hWnd != NULL)
PostMessage(hWnd, WM_KEYDOWN, VK_F2, 0);
}
BOOL CSolitaireHighscoreApp::ScanForAddresses()
{
long lOptions = m_setMgr.GetMsSolitaireOptions();
m_setMgr.SetMsSolitaireOptions(MSSOLITAIRE_OPTIONS_VEGAS); // vegas cumulative
#ifdef _DEBUG
StartSolitaire(TRUE);
#else
StartSolitaire(FALSE);
#endif
PostSolitaireDealMsg();
HANDLE hProc = m_procMgr.GetProcessHandle(SOLITAIRE_EXE);
int nRes = RES_SUCC_ALL;
if (hProc != NULL)
{
// looking for the score address in the data segment
long lValPtr = m_procMgr.FindValueInProcessMem(hProc, 0x000a000, 0x000bffff, -104);
if (-1 != lValPtr)
m_setMgr.SetScoreAddress(lValPtr);
else
nRes = RES_FAIL_SCORE;
// looking for the deal decrease
lValPtr = m_procMgr.FindValueInProcessMem(hProc, 0x01006000, 0x01010000, -52);
if (-1 != lValPtr)
m_setMgr.SetDefaultDealAddress(lValPtr);
else
nRes |= RES_FAIL_DEAL;
// close original
m_procMgr.KillProcess(hProc);
m_procMgr.CloseProcess(hProc);
// kill other running instances of solitaire
while ( (hProc = m_procMgr.GetProcessHandle(SOLITAIRE_EXE)) != NULL)
{
m_procMgr.KillProcess(hProc);
m_procMgr.CloseProcess(hProc);
}
// restore ms solitaire options
m_setMgr.SetMsSolitaireOptions(lOptions);
}
else
{
nRes = RES_SOL_NOT_RUN;
}
return nRes;
}
HWND CSolitaireHighscoreApp::FindSolitaireWindow()
{
int scanNum = 100;
CString strSol(SOLITAIRE);
HWND hWnd = NULL;
// we'll try and find the window for about 10 seconds
for (int i=0; i < scanNum; i++)
{
if ((hWnd = FindWindow(strSol, NULL)) != NULL)
{
break;
}
else
{
Sleep(100);
}
}
return hWnd;
}