www.pudn.com > SmartCardSrc.zip > SmartCardDlg.cpp


//------------------------------------------------------------------------------ 
// 
// Copyright (c) 1999-2005  Matt Brunk   
// 
// This program is free software; you can redistribute it and/or modify 
// it under the terms of the GNU General Public License VERSION 2 as 
// published by the Free Software Foundation.  You are not allowed to 
// use any other version of the license; unless you got the explicit 
// permission from the author to do so. 
// 
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
// 
// You should have received a copy of the GNU General Public License 
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
// 
//------------------------------------------------------------------------------ 
// SmartCardDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "SmartCard.h" 
#include "SmartCardDlg.h" 
#include "DlgSetup.h" 
#include "EnumPorts.h" 
#include "sdes.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
typedef struct 
{ 
	unsigned long first; 
	unsigned long last; 
} serialNumStruct; 
 
static const CString s_szSectionSettings	= "Settings"; 
static const CString s_szPort					=	"Port"; 
static const CString s_szBaud					=	"Baud"; 
static const CString s_szClearOutput			=	"ClearOutput"; 
static const CString s_szEncrypt				=	"Encrypt"; 
static const CString s_szVerbose				=	"Verbose"; 
 
///////////////////////////////////////////////////////////////////////////// 
// CAboutDlg dialog used for App About 
 
class CAboutDlg : public CDialog 
{ 
public: 
	CAboutDlg(); 
 
// Dialog Data 
	//{{AFX_DATA(CAboutDlg) 
	enum { IDD = IDD_ABOUTBOX }; 
	//}}AFX_DATA 
 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CAboutDlg) 
	protected: 
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support 
	//}}AFX_VIRTUAL 
 
// Implementation 
protected: 
	//{{AFX_MSG(CAboutDlg) 
	//}}AFX_MSG 
	DECLARE_MESSAGE_MAP() 
}; 
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
	//{{AFX_DATA_INIT(CAboutDlg) 
	//}}AFX_DATA_INIT 
} 
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CAboutDlg) 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
	//{{AFX_MSG_MAP(CAboutDlg) 
		// No message handlers 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CSmartCardDlg dialog 
 
CSmartCardDlg::CSmartCardDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CSmartCardDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CSmartCardDlg) 
		// NOTE: the ClassWizard will add member initialization here 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
	m_hSmallIcon = (HICON)::LoadImage 
	( 
		AfxGetResourceHandle(), 
        MAKEINTRESOURCE(IDR_MAINFRAME), 
		IMAGE_ICON, 
        16, 
		16, 
		0 
	); 
 
	m_iPort	= 1; 
	m_iBaud = 9600; 
	m_first = 0; 
	m_last	= 0; 
} 
 
void CSmartCardDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CSmartCardDlg) 
	DDX_Control(pDX, IDC_CHECK_VERBOSE, m_checkVerbose); 
	DDX_Control(pDX, IDC_CHECK_ENCRYPT, m_checkEncrypt); 
	DDX_Control(pDX, IDC_CHECK_CLEAR, m_checkClear); 
	DDX_Control(pDX, IDC_COMBO_COM_PORT, m_comboPort); 
	DDX_Control(pDX, IDC_COMBO_BAUD, m_comboBaud); 
	DDX_Control(pDX, IDC_BUTTON_PROGRAM, m_BtnProgram); 
	DDX_Control(pDX, IDC_COMBO_STOP_BITS, m_comboStopBits); 
	DDX_Control(pDX, IDC_EDIT_REMAINING, m_EditRemaining); 
	DDX_Control(pDX, IDC_EDIT_CURRENT, m_EditCurrent); 
	DDX_Control(pDX, IDC_EDIT_OUT, m_EditOut); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CSmartCardDlg, CDialog) 
	//{{AFX_MSG_MAP(CSmartCardDlg) 
	ON_WM_SYSCOMMAND() 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_BN_CLICKED(IDC_BUTTON_ATR, OnButtonAtr) 
	ON_BN_CLICKED(IDC_BUTTON_START_SESSION, OnButtonStartSession) 
	ON_BN_CLICKED(IDC_BUTTON_SUBMIT_CODE, OnButtonSubmitCode) 
	ON_BN_CLICKED(IDC_BUTTON_SELECT_FILE, OnButtonSelectFile) 
	ON_BN_CLICKED(IDC_BUTTON_READ_FILE, OnButtonReadFile) 
	ON_BN_CLICKED(IDC_BUTTON_SETUP, OnButtonSetup) 
	ON_BN_CLICKED(IDC_BUTTON_PROGRAM, OnButtonProgram) 
	ON_CBN_SELCHANGE(IDC_COMBO_STOP_BITS, OnSelchangeComboStopBits) 
	ON_BN_CLICKED(IDC_BUTTON_DUMP_DCB, OnButtonDumpDcb) 
	ON_CBN_SELCHANGE(IDC_COMBO_BAUD, OnSelchangeComboBaud) 
	ON_CBN_SELCHANGE(IDC_COMBO_COM_PORT, OnSelchangeComboComPort) 
	ON_WM_DESTROY() 
	ON_BN_CLICKED(IDC_CHECK_ENCRYPT, OnCheckEncrypt) 
	ON_BN_CLICKED(IDC_CHECK_VERBOSE, OnCheckVerbose) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CSmartCardDlg message handlers 
 
BOOL CSmartCardDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Add "About..." menu item to system menu. 
 
	// IDM_ABOUTBOX must be in the system command range. 
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 
	ASSERT(IDM_ABOUTBOX < 0xF000); 
 
	CMenu* pSysMenu = GetSystemMenu(FALSE); 
	if (pSysMenu != NULL) 
	{ 
		CString strAboutMenu; 
		strAboutMenu.LoadString(IDS_ABOUTBOX); 
		if (!strAboutMenu.IsEmpty()) 
		{ 
			pSysMenu->AppendMenu(MF_SEPARATOR); 
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 
		} 
	} 
 
	// 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_hSmallIcon, FALSE);	// Set small icon 
	 
 
	CClientDC dc(this); 
	int	nHeight = -((dc.GetDeviceCaps(LOGPIXELSY) * 10) / 72); 
 
	m_font.CreateFont 
	( 
		nHeight, 
		0, 
		0, 
		0, 
		FW_NORMAL, 
		0, 
		0, 
		0, 
		DEFAULT_CHARSET, 
		OUT_CHARACTER_PRECIS, 
		CLIP_CHARACTER_PRECIS, 
		DEFAULT_QUALITY, 
		DEFAULT_PITCH | FF_DONTCARE, 
		_T("Courier New") 
	); 
	 
	m_EditOut.SetLimitText(200000); 
	m_EditOut.SetFont(&m_font); 
	 
	m_iPort	= AfxGetApp()->GetProfileInt(s_szSectionSettings, s_szPort, 1); 
 
	if ( !CEnumPorts::IsPortAvailable(m_iPort) ) 
	{ 
		m_iPort = 1; 
	} 
 
	std::vector ports; 
	CEnumPorts::GetAvailablePorts(ports); 
 
	m_comboPort.ResetContent(); 
 
	CString sss; 
	int nSel = -1; 
	CString szPort; 
	szPort.Format("COM%d", m_iPort); 
 
	for ( size_t nn = 0; nn < ports.size(); nn++ ) 
	{ 
		sss.Format(_T("COM%d"), ports[nn]); 
		m_comboPort.AddString(sss); 
		if ( szPort.Compare(sss) == 0 ) 
		{ 
			nSel = (int)nn; 
		} 
	} 
 
	//m_comboPort.AddString(_T("COM254")); 
 
	if ( nSel >= 0 ) 
	{ 
		m_comboPort.SetCurSel(nSel); 
	} 
 
	m_iBaud	= AfxGetApp()->GetProfileInt(s_szSectionSettings, s_szBaud, 9600); 
	m_checkClear.SetCheck(AfxGetApp()->GetProfileInt(s_szSectionSettings, s_szClearOutput, 0)); 
	m_checkEncrypt.SetCheck(AfxGetApp()->GetProfileInt(s_szSectionSettings, s_szEncrypt, 0)); 
	m_checkVerbose.SetCheck(AfxGetApp()->GetProfileInt(s_szSectionSettings, s_szVerbose, 1)); 
 
	m_acos1.EnableEncryption(m_checkEncrypt.GetCheck() != 0); 
	m_acos1.SetVerbose(m_checkVerbose.GetCheck() != 0); 
	m_comboPort.SetCurSel(m_iPort - 1); 
 
	int idx = 0; 
	CString ttt; 
	sss.Format(_T("%d"), m_iBaud); 
	bool found = false; 
	for ( int bb = 0; bb < m_comboBaud.GetCount(); bb++ ) 
	{ 
		m_comboBaud.GetLBText(bb, ttt); 
		if ( sss.Compare(ttt) == 0 ) 
		{ 
			idx = bb; 
			found = true; 
			break; 
		} 
	} 
 
	if ( !found ) 
	{ 
		idx = 0; 
		m_iBaud = 9600; 
	} 
 
	m_comboBaud.SetCurSel(idx); 
	m_comboStopBits.SetCurSel(1); 
 
	m_acos1.SetPort(m_iPort); 
	m_acos1.SetBaud(m_iBaud); 
	m_acos1.SetEditControl(&m_EditOut); 
 
	m_EditOut.SetLimitText(0x8000); 
 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CSmartCardDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
	if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
	{ 
		CAboutDlg dlgAbout; 
		dlgAbout.DoModal(); 
	} 
	else 
	{ 
		CDialog::OnSysCommand(nID, lParam); 
	} 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CSmartCardDlg::OnPaint()  
{ 
	if (IsIconic()) 
	{ 
		CPaintDC dc(this); // device context for painting 
 
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
		// Center icon in client rectangle 
		int cxIcon = GetSystemMetrics(SM_CXICON); 
		int cyIcon = GetSystemMetrics(SM_CYICON); 
		CRect rect; 
		GetClientRect(&rect); 
		int x = (rect.Width() - cxIcon + 1) / 2; 
		int y = (rect.Height() - cyIcon + 1) / 2; 
 
		// Draw the icon 
		dc.DrawIcon(x, y, m_hIcon); 
	} 
	else 
	{ 
		CDialog::OnPaint(); 
	} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CSmartCardDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
void CSmartCardDlg::OnButtonAtr()  
{ 
	DispatchCommand(COMMAND_ATR); 
} 
 
void CSmartCardDlg::OnButtonStartSession()  
{ 
	DispatchCommand(COMMAND_START_SESSION); 
} 
 
void CSmartCardDlg::OnButtonSubmitCode()  
{ 
	DispatchCommand(COMMAND_SUBMIT_CODE); 
} 
 
void CSmartCardDlg::OnButtonSelectFile()  
{ 
	DispatchCommand(COMMAND_SELECT_FILE); 
} 
 
void CSmartCardDlg::OnButtonReadFile()  
{ 
	DispatchCommand(COMMAND_READ_FILE); 
} 
 
void CSmartCardDlg::OnButtonSetup()  
{ 
	DispatchCommand(COMMAND_SETUP); 
} 
 
void CSmartCardDlg::OnButtonProgram()  
{ 
	DispatchCommand(COMMAND_PROGRAM); 
} 
 
bool CSmartCardDlg::DoATR() 
{ 
	unsigned char	buf[64]; 
	DWORD			dwLength; 
 
	dwLength = sizeof buf; 
	return m_acos1.GetATR(buf, dwLength); 
} 
 
void CSmartCardDlg::DoStartSession()  
{ 
	unsigned char buf[128]; 
	DWORD dwLength; 
	if ( m_acos1.StartSession(buf, dwLength) ) 
	{ 
		CString ccc; 
		CString sss = _T("key = ");; 
		for ( DWORD ii = 0; ii < dwLength; ii++ ) 
		{ 
			ccc.Format(_T("%02X "), buf[ii]); 
			sss += ccc; 
		} 
		sss += _T("\r\n"); 
		AppendText(sss); 
	} 
} 
 
bool CSmartCardDlg::DoSubmitCode()  
{ 
	unsigned char CODE[] = {'A', 'C', 'O', 'S', 'T', 'E', 'S', 'T'}; 
	return m_acos1.SubmitIC(CODE); 
} 
 
bool CSmartCardDlg::DoSelectFile()  
{ 
	unsigned char FILE_DATA[] = {0xFF, 0x03}; 
	return m_acos1.SelectFile(FILE_DATA); 
} 
 
void CSmartCardDlg::DoReadFile()  
{ 
	BOOL bEnableEncryption = m_checkEncrypt.GetCheck(); 
	//if ( !DoATR() ) 
	//{ 
	//	return; 
	//} 
 
	if ( !DoSubmitCode() ) 
	{ 
		return; 
	} 
 
	if ( !DoSelectFile() ) 
	{ 
		return; 
	} 
 
	unsigned char buf[128]; 
	DWORD dwLength; 
	if ( m_acos1.ReadRecord(6, 8, buf, dwLength) ) 
	{ 
		if ( bEnableEncryption ) 
		{ 
			for ( int ii = 0; ii < 8; ii++ ) 
			{ 
				buf[ii] = SDES::Decrypt(buf[ii]); 
			} 
		} 
 
		CString response; 
		CString ccc; 
 
		serialNumStruct serialNum; 
		::CopyMemory(&serialNum, buf, 8); 
 
		m_first = serialNum.first; 
		m_last = serialNum.last; 
 
		m_BtnProgram.EnableWindow(m_first <= m_last); 
 
		CString sss; 
		sss.Format(_T("%lu"), serialNum.first); 
		m_EditCurrent.SetWindowText(sss); 
		sss.Format(_T("%lu"), serialNum.last - serialNum.first + 1); 
		m_EditRemaining.SetWindowText(sss);				 
 
		if ( m_checkVerbose.GetCheck() ) 
		{ 
			response.Format(_T("RECORD %2d: "), 6); 
			for ( DWORD ii = 0; ii < dwLength; ii++ ) 
			{ 
				ccc.Format(_T("%02X "), buf[ii]); 
				response += ccc; 
			}			 
			AppendText(response); 
		} 
	} 
} 
 
void CSmartCardDlg::DoSetup()  
{ 
	CDlgSetup dlg; 
 
	int nResponse = dlg.DoModal(); 
	if ( nResponse == IDOK ) 
	{ 
		ClearOutput(); 
 
		serialNumStruct serialNum; 
		serialNum.first = dlg.m_uStartNum; 
		serialNum.last	= dlg.m_uStartNum + dlg.m_uCount - 1; 
 
		m_BtnProgram.EnableWindow(serialNum.first <= serialNum.last); 
 
		CString			sss; 
 
		if ( !m_acos1.OpenPort() ) 
		{ 
			CString errMsg = m_acos1.GetLastErrorMsg(); 
			sss.Format(_T("Error opening serial port.\n\n%s"), (LPCTSTR)errMsg); 
			AfxMessageBox(sss, MB_OK | MB_ICONERROR ); 
			return; 
		} 
		Sleep(200); 
 
		unsigned char CODE[] = {'A', 'C', 'O', 'S', 'T', 'E', 'S', 'T'}; 
		if ( m_acos1.SubmitIC(CODE) ) 
		{ 
			unsigned char FILE_DATA[] = {0xFF, 0x03}; 
			if ( m_acos1.SelectFile(FILE_DATA) ) 
			{ 
				if ( m_acos1.WriteRecord(6, (unsigned char *)&serialNum, sizeof serialNum) ) 
				{ 
					AppendText(_T("Success "));	 
					DoReadFile(); 
				} 
			} 
		}			 
	} 
 
} 
 
void CSmartCardDlg::DoProgram()  
{ 
	DoReadFile(); 
	 
	if ( m_first <= m_last ) 
	{ 
 
		m_first++; 
 
		serialNumStruct serialNum; 
		serialNum.first = m_first; 
 
		unsigned char CODE[] = {'A', 'C', 'O', 'S', 'T', 'E', 'S', 'T'}; 
		if ( m_acos1.SubmitIC(CODE) ) 
		{ 
			unsigned char FILE_DATA[] = {0xFF, 0x03}; 
			if ( m_acos1.SelectFile(FILE_DATA) ) 
			{ 
				if ( m_acos1.WriteRecord(6, (unsigned char *)&serialNum, 4) ) 
				{ 
					AppendText(_T("Success ")); 
					DoReadFile(); 
				} 
			} 
		}			 
	} 
	else 
	{ 
		AfxMessageBox(_T("Serial numbers exhausted!"), MB_OK | MB_ICONWARNING ); 
	} 
	 
} 
 
void CSmartCardDlg::OnSelchangeComboStopBits()  
{ 
	m_acos1.SetStopBits(m_comboStopBits.GetCurSel() + 1); 
} 
 
void CSmartCardDlg::OnButtonDumpDcb()  
{	 
	if ( !m_acos1.OpenPort() ) 
	{ 
		CString	sss; 
		CString errMsg = m_acos1.GetLastErrorMsg(); 
		sss.Format(_T("Error opening serial port.\n\n%s"), (LPCTSTR)errMsg); 
		AfxMessageBox(sss, MB_OK | MB_ICONERROR ); 
		return; 
	} 
 
	ClearOutput(); 
	m_acos1.DumpDCB(); 
	m_acos1.ClosePort(); 
} 
 
void CSmartCardDlg::OnSelchangeComboBaud()  
{ 
	CString sss; 
	m_comboBaud.GetLBText(m_comboBaud.GetCurSel(), sss); 
	_stscanf(sss, "%d", &m_iBaud);	 
	m_acos1.SetBaud(m_iBaud); 
} 
 
void CSmartCardDlg::OnSelchangeComboComPort()  
{ 
	CString sss; 
 
	if ( m_comboPort.GetCount() > 0 ) 
	{ 
		m_comboPort.GetLBText(m_comboPort.GetCurSel(), sss); 
		_stscanf(sss, "COM%d", &m_iPort); 
		m_acos1.SetPort(m_iPort); 
	} 
} 
 
void CSmartCardDlg::OnDestroy()  
{ 
	AfxGetApp()->WriteProfileInt(s_szSectionSettings, s_szPort, m_iPort); 
	AfxGetApp()->WriteProfileInt(s_szSectionSettings, s_szBaud, m_iBaud); 
	AfxGetApp()->WriteProfileInt(s_szSectionSettings, s_szClearOutput, m_checkClear.GetCheck()); 
	AfxGetApp()->WriteProfileInt(s_szSectionSettings, s_szEncrypt, m_checkEncrypt.GetCheck()); 
	AfxGetApp()->WriteProfileInt(s_szSectionSettings, s_szVerbose, m_checkVerbose.GetCheck()); 
 
	CDialog::OnDestroy();	 
} 
 
void CSmartCardDlg::AppendText(LPCTSTR Text) 
{ 
	CString msg = Text; 
 
	msg += _T("\r\n"); 
 
	int Length = m_EditOut.GetWindowTextLength(); 
 
	m_EditOut.SetSel(Length, Length); 
	m_EditOut.ReplaceSel(msg); 
	m_EditOut.LineScroll( m_EditOut.GetLineCount() ); 
} 
 
void CSmartCardDlg::ClearOutput() 
{ 
	if ( m_checkClear.GetCheck() ) 
	{ 
		m_EditOut.SetWindowText(_T("")); 
	} 
} 
 
void CSmartCardDlg::DispatchCommand(CommandEnum command) 
{ 
	CString	sss; 
 
	if ( command != COMMAND_SETUP ) 
	{ 
		ClearOutput(); 
 
		if ( !m_acos1.OpenPort() ) 
		{ 
			CString errMsg = m_acos1.GetLastErrorMsg(); 
			sss.Format(_T("Error opening serial port.\n\n%s"), (LPCTSTR)errMsg); 
			AfxMessageBox(sss, MB_OK | MB_ICONERROR ); 
			return; 
		} 
	} 
 
	switch ( command ) 
	{ 
		case COMMAND_ATR: 
		{ 
			DoATR(); 
		} 
		break; 
 
		case COMMAND_START_SESSION: 
		{ 
			DoStartSession(); 
		} 
		break; 
 
		case COMMAND_SUBMIT_CODE: 
		{ 
			DoSubmitCode(); 
		} 
		break; 
 
		case COMMAND_SELECT_FILE: 
		{ 
			DoSelectFile(); 
		} 
		break; 
 
		case COMMAND_READ_FILE: 
		{ 
			DoReadFile(); 
		} 
		break; 
 
		case COMMAND_SETUP: 
		{ 
			DoSetup(); 
		} 
		break; 
 
		case COMMAND_PROGRAM: 
		{ 
			DoProgram(); 
		} 
		break; 
 
		default: 
			break; 
	} 
 
	m_acos1.ClosePort(); 
 
} 
 
void CSmartCardDlg::OnCheckEncrypt()  
{ 
	m_acos1.EnableEncryption(m_checkEncrypt.GetCheck() != 0); 
} 
 
void CSmartCardDlg::OnCheckVerbose()  
{ 
	m_acos1.SetVerbose(m_checkVerbose.GetCheck() != 0);	 
}