/**
 *********************************************************************************************************************
 *	@file		EmvKernelWinApi.cpp
 *  @brief		EMV Library for ATM.
 *  @brief	    Emv Library, External Interface sample.
 *  @author		Ilya Yalin
 *  @author		Email: ilya@yalko.ru 
 *	@author		Website: http://www.yalko.ru 
 *  @version	1.0
 *  @date		2016
 *********************************************************************************************************************
*/
/**
***************** Modification Section: *****************************************************************************
$Archive: /ProjectsYalko/EmvKernelWinApi/EmvKernelWinApi.cpp $
$Author: Yalin $
$Date: 26.02.16 13:08 $
$Revision: 08 $
$Header: /ProjectsYalko/EmvKernelWinApi/EmvKernelWinApi.cpp 08 26.02.16 13:08 Yalin $
$Log: /ProjectsYalko/EmvKernelWinApi/EmvKernelWinApi.cpp $
*********************************************************************************************************************
*/
#include "stdafx.h"
#include "EmvKernelWinApi.h"

#define MAX_LOADSTRING 100

// Глобальные переменные:
HANDLE hThread_EmvStart = NULL;
HANDLE hEvent_GetAmount = NULL;
HANDLE hEvent_GetCryptPin = NULL;

HINSTANCE hInst;								// текущий экземпляр
INT_PTR CALLBACK DlgMain(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	hInst = hInstance;
    DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, DlgMain);
	return 0;
}
HWND hMainDlg = NULL;
char trace[10000];
void AddTrace(char *str)
{
    if(hMainDlg != NULL && strlen(trace) < sizeof(trace) - strlen(str))
    {
        strcat(trace,str);
	    SetDlgItemText(hMainDlg,IDC_EDIT_TRACE,trace);
    }
}
BYTE _9F02[6];//Amount
BYTE PinBlock[8];//Crypted PIN block
INT_PTR CALLBACK DlgGetCryptPin(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_SHOWWINDOW:
		SetDlgItemText(hDlg,IDC_EDIT1,"1234567890ABCDEF");
		break;
	case WM_COMMAND:
	    switch(LOWORD(wParam))
	    {
	        case IDOK:
				char data[256];
	            GetDlgItemText (hDlg,IDC_EDIT1,data,sizeof(data));
	            AddTrace("\r\nCrypt Pin = ");
	            AddTrace(data);
	            
                PinBlock[0] = 0x11;
                PinBlock[1] = 0x22;
                PinBlock[2] = 0x33;
                PinBlock[3] = 0x44;
                PinBlock[4] = 0x55;
                PinBlock[5] = 0x66;
                PinBlock[6] = 0x77;
                PinBlock[7] = 0x88;

				SetEvent(hEvent_GetCryptPin);
			    EndDialog(hDlg, LOWORD(wParam));
			    return (INT_PTR)TRUE;
	        case IDCANCEL:
			    EndDialog(hDlg, LOWORD(wParam));
			    return (INT_PTR)TRUE;
	    }
		break;
	}
	return (INT_PTR)FALSE;
}
INT_PTR CALLBACK DlgGetAmount(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_SHOWWINDOW:
		SetDlgItemText(hDlg,IDC_EDIT1,"1234500");
		break;
	case WM_COMMAND:
	    switch(LOWORD(wParam))
	    {
	        case IDOK:	       
				char data[256];
	            GetDlgItemText (hDlg,IDC_EDIT1,data,sizeof(data));
	            if(strlen(data) > 2)
	            {
	                AddTrace("\r\nAmount = ");
	                AddTrace(data);
	                
	                _9F02[0] = 0x00;
	                _9F02[1] = 0x00;
	                _9F02[2] = 0x00;
	                _9F02[3] = 0x10;
	                _9F02[4] = 0x00;
	                _9F02[5] = 0x00;
	                
					SetEvent(hEvent_GetAmount);
			        EndDialog(hDlg, LOWORD(wParam));
			        return (INT_PTR)TRUE;
	            } else {
	                AddTrace("\r\nAmount should be more 99 (more 3 numbers)");
	                break;
	            }
	        case IDCANCEL:
			    EndDialog(hDlg, LOWORD(wParam));
			    return (INT_PTR)TRUE;
	    }
		break;
	}
	return (INT_PTR)FALSE;
}
DWORD fThread_EmvStart(LPVOID lpParam)					   
{
    if(hEvent_GetAmount == NULL && hEvent_GetCryptPin == NULL)
    {
	    hEvent_GetCryptPin = MyCreateEvent(NULL,TRUE,TRUE,_T("hEvent_GetCryptPin"));
	    ResetEvent(hEvent_GetCryptPin); //change the state to unselected (no events)        
	    hEvent_GetAmount = MyCreateEvent(NULL,TRUE,TRUE,_T("hEvent_GetAmount"));
	    ResetEvent(hEvent_GetAmount); //change the state to unselected (no events)

        BOOL rc = Start_EmvExamle();
        
        CloseHandle(hEvent_GetCryptPin);
        CloseHandle(hEvent_GetAmount);        
        hEvent_GetAmount = NULL;
        hEvent_GetCryptPin = NULL;
        
        if(rc)
        {
            AddTrace("\r\nStart_EmvExamle() result is ok.");
            return 0;//ok
        } else {
            AddTrace("\r\nStart_EmvExamle() result is err.");
            return 1;//err 1
        }
	} else {
        AddTrace("\r\n!(hEvent_GetAmount == NULL && hEvent_GetCryptPin == NULL)");
        return 2;//err 2
	}   	
}
BOOL flag_init_emv_kernel = FALSE;
INT_PTR CALLBACK DlgMain(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	hMainDlg = hDlg;
	switch (message)
	{
	case WM_COMMAND:
	    switch(LOWORD(wParam))
	    {
			case IDC_BUTTON_EMVINIT:
				AddTrace("\r\nIDC_BUTTON_EMVINIT");
				if(Init_EMVKernel())
                {
	                AddTrace("\r\nInit_EMVKernel() ok.");
					flag_init_emv_kernel = TRUE;
                } else {
	                AddTrace("\r\nInit_EMVKernel() error.");
					flag_init_emv_kernel = FALSE;
                }
				break;
			case IDC_BUTTON_EMVSTART:
				if(flag_init_emv_kernel)
	            {
		            AddTrace("\r\nStart Emv Kernel...");
		            {
			            DWORD Tid;
			            hThread_EmvStart = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fThread_EmvStart, NULL, 0, &Tid);
		            }
				} else {
	                AddTrace("\r\n!(flag_init_emv_kernel)...");
	            }
				break;
			case IDC_BUTTON_GET_CRYPT_PIN: 
				AddTrace("\r\nIDC_BUTTON_GET_CRYPT_PIN");
				DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG_GETCRYPT_PIN), hDlg, DlgGetCryptPin);
				break;
			case IDC_BUTTON_GET_AMOUNT: 
				AddTrace("\r\nIDC_BUTTON_GET_AMOUNT");
				DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG_GET_AMOUNT), hDlg, DlgGetAmount);
				break;
			case IDC_BUTTON_EMVUNINIT:
				AddTrace("\r\nIDC_BUTTON_EMVUNINIT");
				if(flag_init_emv_kernel)
	            {
	                UnInit_EMVKernel();
					flag_init_emv_kernel = FALSE;
	            }
				break;
	        case IDOK:
	        case IDCANCEL:
				if(flag_init_emv_kernel)
				{
					UnInit_EMVKernel();
				}
			    EndDialog(hDlg, LOWORD(wParam));
			    DestroyWindow(hDlg);
			    return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}
HANDLE MyCreateEvent(LPSECURITY_ATTRIBUTES atr, BOOL manual_reset, BOOL init_state, TCHAR * name)
{
	TCHAR win_name[256];
	TCHAR str_date[100];
	SYSTEMTIME d;
	//GetSystemTime(&d);
	GetLocalTime(&d);


//	_stprintf(str_date,"%d%d%d%d%d%d%d"
	_stprintf_s( str_date, sizeof( str_date ) / sizeof(TCHAR), _T("%d%d%d%d%d%d%d")
		,d.wYear
		,d.wMonth
		,d.wDay
		,d.wHour
		,d.wMinute 
		,d.wSecond 
		,d.wMilliseconds
		);

	memset(win_name,0,sizeof(win_name));
	_tcscat(win_name,name);
	_tcscat(win_name,str_date);
	return CreateEvent(atr, manual_reset, init_state, win_name);
}