// AutoResumeDlg.cpp : implementation file
//

#include "stdafx.h"
#include "AutoResume.h"
#include "AutoResumeDlg.h"
#include <Notify.h>
#include <Pm.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
ULONGLONG g_resumetime;
// the interal between twice suspend must >12sec
#define  E_ERROR_WAIT   _HRESULT_TYPEDEF_(0x81000002L) 
int g_nStep =0;
TCHAR g_AppName[MAX_PATH];
CString AutoRunAppName;
HANDLE g_hCancelRepeatEvent;
// CAutoResumeDlg dialog

CAutoResumeDlg::CAutoResumeDlg(CWnd* pParent /*=NULL*/)
: CDialog(CAutoResumeDlg::IDD, pParent)
, m_str_resumetime(_T("20"))
, m_str_valTimes(_T("3"))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CAutoResumeDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, m_str_resumetime);
	DDX_Text(pDX, IDC_TIME, m_str_valTimes);
	DDX_Control(pDX, IDC_EDIT2, m_Edit3);
	DDX_Control(pDX, IDC_BUTTON2, m_RepeatButton);
}

BEGIN_MESSAGE_MAP(CAutoResumeDlg, CDialog)
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
	ON_WM_SIZE()
#endif
	//}}AFX_MSG_MAP
	ON_EN_CHANGE(IDC_TIME, &CAutoResumeDlg::OnEnChangeEdit1)
	ON_BN_CLICKED(IDC_BUTTON1, &CAutoResumeDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &CAutoResumeDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &CAutoResumeDlg::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON4, &CAutoResumeDlg::OnBnClickedButton4)
END_MESSAGE_MAP()


// CAutoResumeDlg message handlers

BOOL CAutoResumeDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	m_str_resumetime = _T("20");
	m_str_valTimes = _T("3");
	//g_resumetime = _wtoi(m_str_resumetime);
	UpdateData(FALSE);
	//g_resumetime = _wtoi(m_str_resumetime);
	//SetDlgItemInt(IDC_TIME, 1);
	// TODO: Add extra initialization here
	g_hCancelRepeatEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
void CAutoResumeDlg::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
{
	if (AfxIsDRAEnabled())
	{
		DRA::RelayoutDialog(
			AfxGetResourceHandle(), 
			this->m_hWnd, 
			DRA::GetDisplayMode() != DRA::Portrait ? 
			MAKEINTRESOURCE(IDD_AUTORESUME_DIALOG_WIDE) : 
		MAKEINTRESOURCE(IDD_AUTORESUME_DIALOG));
	}
}
#endif


void CAutoResumeDlg::OnEnChangeEdit1()
{
	// TODO:  If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.

	// TODO:  Add your control notification handler code here
}
int   PosiInt(TCHAR*   Tstr) 
{ 
	char *str = new char[100];
	char *p=str;
	DWORD dwNum = WideCharToMultiByte(CP_OEMCP,NULL,Tstr,-1,NULL,0,NULL,FALSE);
	WideCharToMultiByte(CP_OEMCP,NULL,Tstr,-1,(LPSTR)str,dwNum,NULL,FALSE);
	int   i=0; 
	str=p;
	while(i<(dwNum-1))
	{ 
		if((*p <=57)&&(*p>=48))
		{
		}
		else 
		{
			delete []str;
			str = NULL;
			return 0; 
		}
		p++;
		i++; 
	} 
	if (str)
	{
		delete []str;
		str = NULL;
	}
	return 1; 
}
void CAutoResumeDlg::OnBnClickedButton1()
{
	// TODO: Add your control notification handler code here
	BOOL flag = false;
	HMODULE hDLL = LoadLibrary(_T("\\Windows\\DTRControlSuspend.dll"));

	union {
		LONGLONG time64;
		FILETIME FT;
	}SleepTime;
	SYSTEMTIME st;
	LONGLONG time_temp;

	GetLocalTime(&st);

	SystemTimeToFileTime(&st, &SleepTime.FT);
	UpdateData(TRUE);

	if(PosiInt(m_str_resumetime.GetBuffer(m_str_resumetime.GetLength())) == 0)
	{
		MessageBox(L"Please enter a positive integer.", L"Error", MB_OKCANCEL);
		return;
	}

	m_resumetime = _wtoi(m_str_resumetime);
	if(m_resumetime < 20)
	{
		MessageBox(L"The resume time after suspend must be more than 19 seconds.", L"Error", MB_OK);
		return;
	}
	time_temp = m_resumetime * 10000000;
	// 215*10000000 Value beyonds the scope of  DWORD, we define LONGLONG variable can solve this bug.
	// We are passed in seconds, but we need to set the
	// wake time in multiples of 100 nanoseconds   
	SleepTime.time64 += (time_temp);

	FileTimeToSystemTime(&SleepTime.FT, &st);

	RETAILMSG(1, (
		L"+CeRunAppAtTime(%d/%d/%d %d:%d:%d.%03d)\r\n", 
		st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute,
		st.wSecond, st.wMilliseconds
		));

	TCHAR lpFileName[MAX_PATH+1];

	GetModuleFileName(NULL, lpFileName, MAX_PATH);


	if (FALSE == CeRunAppAtTime(L" ", &st))
	{
		//MessageBox(L"Error", L"Failed", MB_OK);
		RETAILMSG(1,(TEXT("!!!!CeRunAppAtTime failed error code=%x!!!!!!\r\n"), GetLastError()));
	}
	//SetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);

	DTRControlSuspend pSuspend = 
		(DTRControlSuspend)GetProcAddress(hDLL, _T("DTRControlSuspend"));
	//Sleep(20000);

	if (pSuspend)
	{
		// RETAILMSG(1,(TEXT("!!!!Call DTR suspend!!!!!!\r\n")));
		if(g_nStep == 0)
		{
			HRESULT hr = pSuspend(TRUE);
			//E_ERROR_WAIT
			if(hr == E_ERROR_WAIT)
			{
				MessageBox(L"The system can't be suspended this time. Wait a moment please.", L"Error", MB_OK);
			}
			else
			{
				SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);
				//please add the auto ran app at here.
				CString sAppName;
				GetLocalTime(&st);
				//SystemTimeToFileTime(&st, &SleepTime.FT);
				//SleepTime.time64 += 2 * 10000000;
				//FileTimeToSystemTime(&SleepTime.FT, &st);
				m_Edit3.GetWindowText(sAppName);
				RETAILMSG(1,(TEXT("!!!!2!!!!!!\r\n")));
				if (FALSE == CeRunAppAtTime(sAppName.GetBuffer(), &st))
				{
					//MessageBox(L"Error", L"Failed", MB_OK);
					RETAILMSG(1,(TEXT("!!!!CeRunAppAtTime failed error code=%x!!!!!!\r\n"), GetLastError()));
				}
				SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
				RETAILMSG(1,(TEXT("!!!!2*2!!!!!!\r\n")));
			}
		}
		else
		{
			MessageBox(L"The Repeat operation is running, please do it until it was completed.", L"Error", MB_OK);
		}
	}


	//m_Cedit.EnableWindow(true);
	if (hDLL)
	{
		FreeLibrary(hDLL);
	}
}

void CAutoResumeDlg::OnBnClickedButton2()
{
	// TODO: Add your control notification handler code here
	CString csText;
	GetDlgItemText(IDC_TIME, csText);
	int nMax = _ttoi(csText);
	m_valTimes = 0;
//	_wtoi(m_str_valTimes) = 0;
	UpdateData(TRUE);
	if(PosiInt(m_str_resumetime.GetBuffer(m_str_resumetime.GetLength())) == 0)
	{
		MessageBox(L"Please enter a positive integer.", L"Error", MB_OKCANCEL);
		return;
	}

	m_resumetime = _wtoi(m_str_resumetime);
	if(m_resumetime < 20)
	{
		MessageBox(L"The resume time after suspend must be more than 19 seconds.", L"Error", MB_OK);
		return;
	}
	g_resumetime = m_resumetime;

	if(PosiInt(m_str_valTimes.GetBuffer(m_str_valTimes.GetLength())) == 0)
	{
		MessageBox(L"Please enter a positive integer.", L"Error", MB_OKCANCEL);
		return;
	}

	if(_wtoi(m_str_valTimes) <= 0)
	{
		MessageBox(L"The suspend-resume operation value must be more than 0.", L"Error", MB_OK);
		return;
	}
	if(g_nStep == 0)
	{
		CString sAppName;
		m_Edit3.GetWindowText(sAppName);
		wcscpy_s(g_AppName,MAX_PATH,sAppName.GetBuffer());
		m_valTimes = _wtoi(m_str_valTimes);
		ResetEvent(g_hCancelRepeatEvent);
		pThread = AfxBeginThread(AutoRunTimeThread, this);		
		if (pThread)
		{
			m_RepeatButton.EnableWindow(FALSE);
		}
	}
	else
	{
		MessageBox(L"The Repeat operation is running, please do it until it was completed.", L"Error", MB_OK);
	}
}

UINT CAutoResumeDlg::AutoRunTimeThread(LPVOID lpParam)
{
	HMODULE hDLL = LoadLibrary(_T("\\Windows\\DTRControlSuspend.dll"));
	ULONGLONG time_temp;
	int nMax = 1;
	CAutoResumeDlg *pDlg;
	if (NULL == lpParam)
	{
		return 0;
	}
	pDlg = (CAutoResumeDlg *)lpParam;
	nMax = pDlg->m_valTimes;

	while (g_nStep < nMax)
	{
		RETAILMSG(1,(TEXT("---for step %d nMax %d!!!!!!\r\n"), g_nStep, nMax));
		if(g_nStep > 0)
		{
			//Sleep(30000);
			if(WAIT_OBJECT_0 == WaitForSingleObject(g_hCancelRepeatEvent,30000))
			{
				g_nStep = nMax;
				break;
			}
		}
		g_nStep++;
		union {
			ULONGLONG time64;
			FILETIME FT;
		}SleepTime;
		SYSTEMTIME st;

		GetLocalTime(&st);

		SystemTimeToFileTime(&st, &SleepTime.FT);

		// We are passed in seconds, but we need to set the
		// wake time in multiples of 100 nanoseconds   
		//  SleepTime.time64 += (15 * 10000000);
		time_temp = g_resumetime * 10000000;
		SleepTime.time64 += time_temp;

		FileTimeToSystemTime(&SleepTime.FT, &st);

		RETAILMSG(1, (
			L"+CeRunAppAtTime(%d/%d/%d %d:%d:%d.%03d)\r\n", 
			st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute,
			st.wSecond, st.wMilliseconds
			));


		if (FALSE == CeRunAppAtTime(L" ", &st))
		{
			//MessageBox(L"Error", L"Failed", MB_OK);
			RETAILMSG(1,(TEXT("!!!!CeRunAppAtTime failed error code=%x!!!!!!\r\n"), GetLastError()));
		}
		//SetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE);

		DTRControlSuspend pSuspend = 
			(DTRControlSuspend)GetProcAddress(hDLL, _T("DTRControlSuspend"));

		if (pSuspend)
		{
			HRESULT hr = pSuspend(TRUE);
			//E_ERROR_WAIT
			if(hr == E_ERROR_WAIT)
			{
				g_nStep = 0;
				::MessageBox(NULL,L"The system can't be suspended this time. Wait a moment please.", L"Error", MB_OK);
				break;
			}
			else
			{
				SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);
				//please add the auto ran app at here.
				GetLocalTime(&st);
				//SystemTimeToFileTime(&st, &SleepTime.FT);
				//SleepTime.time64 += 2 * 10000000;
				//FileTimeToSystemTime(&SleepTime.FT, &st);
				if (FALSE == CeRunAppAtTime(g_AppName, &st))
				{
					//MessageBox(L"Error", L"Failed", MB_OK);
					RETAILMSG(1,(TEXT("!!!!CeRunAppAtTime failed error code=%x!!!!!!\r\n"), GetLastError()));
				}
			} 
		}
	}
	if(g_nStep == nMax)
	{
		g_nStep = 0;
	}
	if (hDLL)
	{
		FreeLibrary(hDLL);
	}
	pDlg->m_RepeatButton.EnableWindow(TRUE);
	return 0;
}
void CAutoResumeDlg::OnBnClickedButton3()
{
	// TODO: Add your control notification handler code here
	CString FileName;
	CFileDialog dlg(TRUE,NULL,NULL,NULL,TEXT("All files(*.*)|*.*||"),NULL); 

	dlg.DoModal(); 
	FileName = dlg.GetPathName();
#if 1
	CFileStatus   status; 
	if(!CFile::GetStatus(FileName,status)) 
	{ 
		AfxMessageBox(L"App does not exist");
		return;
	} 
#endif
	
	AutoRunAppName = FileName;
	m_Edit3.SetWindowText(FileName);
}

void CAutoResumeDlg::OnBnClickedButton4()
{
	// TODO: Add your control notification handler code here
	CancelAutoRun();
}

void CAutoResumeDlg::CancelAutoRun()
{
	SetEvent(g_hCancelRepeatEvent);
	CeRunAppAtTime(AutoRunAppName.GetBuffer(), NULL);
	AutoRunAppName = L" ";
	m_Edit3.SetWindowText(AutoRunAppName);
}