// EmvExample.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#define _LIB_API __declspec(dllimport)

#define CARD_AID_COUNT 256

#define NUM_FUNC_EMV_APP_SELECTED		 1//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_SELECT_LANG		 2//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_SELECT_APP			 3//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_ATT_GET_TR_DATA	 4//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_GET_TR_DATA		 5//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_GET_CRYPT_PIN		 6//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_GET_PIN			 7//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_HOST_SWOP			 8//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_FORCE_ACCEPT		 9//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_FORCE_ON_LINE		10//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_PIN_ENTRY_RESULT	11//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_ISSUER_REFERRAL	12//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_SHOW_FUNDS			13//!< sequence number function, for use into emv_kernel_registry()
#define NUM_FUNC_EMV_SELECT_ACCOUNT		14//!< sequence number function, for use into emv_kernel_registry()

BYTE               InbtLang[3];
BYTE               InbtLangSize;
HANDLE hInSelLangThread = NULL;
HANDLE hInTrDataThread = NULL;

/************************************************************************/
/*                  EMV kernel library functions:                       */
/************************************************************************/
typedef BYTE  (WINAPI *FUNC_EMV_KERNEL_REGISTRY			)(LPVOID lpHandle,BYTE btfNumber,LPVOID fPointer);
typedef LPVOID(WINAPI *FUNC_EMV_KERNEL_INIT				)(char *);
typedef VOID  (WINAPI *FUNC_EMV_KERNEL_UNINIT	        )(LPVOID lpHandle);
typedef BYTE  (WINAPI *FUNC_EMV_KER_RUN					)(LPVOID lpHandle,LPVOID lpCallbackHandle,BYTE btTrStatus,LPBYTE lpbtCr,LPDWORD lpdwCrSize, DWORD dwMaxSize);
typedef DWORD (WINAPI *FUNC_EMV_KERNEL_GET_DATA			)(WORD dwTag,LPBYTE lpbtData,LPDWORD lpdwSize,DWORD dwMaxSize);
typedef DWORD (WINAPI *FUNC_EMV_KERNEL_SET_DATA			)(WORD dwTag,LPBYTE lpbtData,DWORD dwSize);
typedef BYTE  (WINAPI *FUNC_EMV_KERNEL_SET_DATA_BY_TAG	)(LPVOID lpHandle,LPBYTE lpbtBuffer,DWORD dwBufferSize);
typedef BYTE  (WINAPI *FUNC_EMV_KERNEL_GET_CAM_DATA		)(LPVOID lpHandle,LPBYTE lpbtByte1,LPBYTE lpbtByte2);
typedef BYTE  (WINAPI *FUNC_EMV_KERNEL_GET_ERR_DATA		)(LPVOID lpHandle,LPBYTE lpbtByte1,LPBYTE lpbtByte2);
typedef BYTE  (WINAPI *FUNC_EMV_KERNEL_CLEAR_DATA		)(LPVOID lpHandle);
typedef BYTE  (WINAPI *FUNC_EMV_KERNEL_GET_DATA_BY_TAG	)(LPVOID lpHandle,LPBYTE lpbtTag,DWORD dwTagSize,LPBYTE lpbtData,LPDWORD lpdwSize,DWORD dwMaxSize);
typedef BYTE  (WINAPI *FUNC_EMV_KERNEL_GET_BUF_BY_DOL	)(LPVOID lpHandle,LPBYTE dol,DWORD dol_size, LPBYTE out,DWORD *out_len, DWORD out_max);
typedef BYTE  (WINAPI *FUNC_EMV_KERNEL_GET_BUF_BY_CDOL	)(LPVOID lpHandle,BYTE flag_cdol,LPBYTE lpbtBuffer,DWORD dwBufferSize, LPBYTE out, DWORD * out_len, DWORD out_max);

FUNC_EMV_KERNEL_REGISTRY		EmvRegistryProcAddr;
FUNC_EMV_KERNEL_INIT			EmvInitProcAddr;
FUNC_EMV_KERNEL_UNINIT			EmvUnInitProcAddr;
FUNC_EMV_KER_RUN				EmvRunProcAddr;
FUNC_EMV_KERNEL_GET_DATA		EmvGetTagProcAddr;
FUNC_EMV_KERNEL_SET_DATA		EmvSetTagProcAddr;
FUNC_EMV_KERNEL_SET_DATA_BY_TAG	EmvSetByTagProcAddr;
FUNC_EMV_KERNEL_GET_CAM_DATA	EmvGetCamDataProcAddr;
FUNC_EMV_KERNEL_GET_ERR_DATA	EmvGetErrDataProcAddr;
FUNC_EMV_KERNEL_CLEAR_DATA		EmvClearDataProcAddr;
FUNC_EMV_KERNEL_GET_DATA_BY_TAG	EmvGetByTagProcAddr;
FUNC_EMV_KERNEL_GET_BUF_BY_DOL 	EmvSetBufByDolProcAddr;
FUNC_EMV_KERNEL_GET_BUF_BY_CDOL EmvSetBufByCDolProcAddr;


/************************************************************************/
/*                  Smart Card library functions:                       */
/************************************************************************/
typedef BYTE (WINAPI *PROC_SELECT_READER  )( char *,DWORD);
typedef BYTE (WINAPI *PROC_OPEN_READER    )( char * rname, char * comPortName);
typedef BYTE (WINAPI *PROC_CHECK_CONNECT  )( void);
typedef BYTE (WINAPI *PROC_WAIT_CONNECT   )( DWORD);
typedef BYTE (WINAPI *PROC_ANSWER_TO_RESET)( BYTE *atr, DWORD * max_len, BYTE * protocol);
typedef WORD (WINAPI *PROC_SEND_APDU_IN   )( BYTE *cmd,BYTE * data,WORD *data_len,BYTE *answer,WORD answer_max_len);
typedef WORD (WINAPI *PROC_SEND_APDU_OUT  )( BYTE *Cmd,WORD *stat,BYTE *answer,WORD answer_max_len);
typedef BYTE (WINAPI *PROC_CLOSE_READER   )( void);
typedef BYTE (WINAPI *PROC_TAKE_CARD	  )( DWORD);
typedef VOID (WINAPI *PROC_STOP_TAKE_CARD )( void);
typedef BYTE (WINAPI *PROC_GET_CARD_OUT	  )( void);	
typedef BYTE (WINAPI *PROC_GET_MAG_DATA   )( BYTE * buffMagData, DWORD * buffMagDataSize);
typedef DWORD (WINAPI *PROC_GET_TRACK1	  )( BYTE * buffMagData, DWORD buffMagDataSize);
typedef DWORD (WINAPI *PROC_GET_TRACK2	  )( BYTE * buffMagData, DWORD buffMagDataSize);
typedef BYTE (WINAPI *PROC_EJECT_CARD     )( void);

PROC_SELECT_READER		AddrSelectReader;
PROC_OPEN_READER		AddrOpenReader;      	
PROC_CHECK_CONNECT		AddrCheckConnect;    
PROC_WAIT_CONNECT		AddrWaitConnect;     	
PROC_ANSWER_TO_RESET	AddrAnswerToReset;  	
PROC_SEND_APDU_IN		AddrSendApduIn;      	
PROC_SEND_APDU_OUT		AddrSendApduOut;    
PROC_CLOSE_READER		AddrCloseReader;
PROC_TAKE_CARD			AddrTakeCard;
PROC_STOP_TAKE_CARD		AddrStopTakingCard;
PROC_GET_CARD_OUT		AddrGetCardOut;
PROC_GET_MAG_DATA		AddrGetMagData;

PROC_GET_TRACK1			AddrGetTrack1;
PROC_GET_TRACK2			AddrGetTrack2;

PROC_EJECT_CARD			AddrEjectCard;

typedef struct tag_emv_TRANS_DATA
{
	BYTE _9C[1];     // ISO 8583:1993(E), A.9 Processing codes:	
	BYTE _5F36[1];   // Transaction Currency Exponent
	BYTE _5F2A[2];   // Transaction Currency Code    Example USD => _5F2A[2]={0x08, 0x40};  
	BYTE _9F02[6];   // Amount, Authorized (Numeric) Example:12.99(USD) => _9F12[6]={0x00, 0x00, 0x00, 0x00, 0x12, 0x99};
	BYTE _9F03[6];   // Amount, Other (Binary)
	BYTE status_pan; // 0 => "OK", 1 => "PAN in the exception file"
} 
emv_TRANS_DATA; //!< current transaction data
 
typedef struct tag_emv_APP_INFO
{
	BYTE btIssuerCodeTable;//!< Shall be 1-10, if zero => common 	
	BYTE btAppLabelLength;	
	BYTE btIsoAppLabel[16];	
	BYTE btAppAidLength;
	BYTE btAppAid[16];	
	BYTE btTerParamEntryID;
} 
emv_APP_INFO; //!< The list of applications (candidate list)

emv_APP_INFO InSelApp;
emv_TRANS_DATA InTrData;

DWORD InGetTrData(LPVOID lpParam);



WORD hex2code(WORD h) 
{
	if (h<='9') return h-'0';
	else return h-'A'+10;
}

BYTE code2hex(BYTE c) 
{
	if (c<=9) return c+'0';
	else return c-10+'A';
}

void hex2bin( BYTE * hex, BYTE * bin, DWORD BYTE_amn) 
{
	WORD x,y;
	while (BYTE_amn>0) {
		x=hex2code((WORD)*hex++)<<4;
		y=hex2code((WORD)*hex++);
		*bin++ =(BYTE)(x+y);
		BYTE_amn--;
	}
}

void bin2hex( BYTE * bin, BYTE * hex, DWORD BYTE_amn) 
{
	while (BYTE_amn>0) {
		*hex++ = code2hex((BYTE)(*bin>>4));
		*hex++ = code2hex((BYTE)(*bin&0xf));
		bin++;
		BYTE_amn--;
	}
}
typedef struct{
	BYTE ReaderNameLen;
	char ReaderName[256];
	char portName[100];
} AReader;
AReader Reader;

void SetReaderParam(CHAR *bu_f)
{
	BYTE *pStr;

	memset(&Reader,0,sizeof(Reader));


	pStr    =(BYTE*)strstr(bu_f,"Smart Card Reader Name Len          :");
	if(pStr)hex2bin(pStr+strlen("Smart Card Reader Name Len          :"),&Reader.ReaderNameLen ,1);

	pStr    =(BYTE*)strstr(bu_f,"Smart Card Reader Name              :");
	if(pStr)memcpy (Reader.ReaderName ,
		pStr+strlen("Smart Card Reader Name              :"),Reader.ReaderNameLen);


	{
		BYTE comPortNameLen = 0;

		pStr    =(BYTE*)strstr(bu_f,"COM Port Name Len                   :");
		if(pStr)hex2bin(pStr+strlen("COM Port Name Len                   :"),&comPortNameLen,1);

		pStr    =(BYTE*)strstr(bu_f,"COM Port Name                       :");
		if(pStr)memcpy (Reader.portName ,
			pStr+strlen("COM Port Name                       :"),comPortNameLen);

	}

}
void ReadReaderParamFile(char * fname) 
{ 
	FILE *f;

	f = fopen(fname,"rb");
	if( f )
	{
		char *bu_f;
		long fsize;

		fseek(f,0L,SEEK_END);
		fsize=ftell(f);		
		fseek(f,0L,SEEK_SET);

		if ((bu_f = (char *) malloc(fsize+1)))
		{
			fread(bu_f,fsize,1,f);
			SetReaderParam(bu_f);
			free(bu_f);
		} else {
			printf("\r\nFSize MORE:%s",fname);
		}
		fclose(f);		
	} else {
		printf("\r\nFile not found:%s",fname);
	}		
}



/************************************************************************/
/*                      EMV kernel library.                             */
/*          The CallBack(external) interface for EMV kernel function:   */
/************************************************************************/
/**
 ******************************************************************************************************************
 *	@fn VOID WINAPI emv_fAppSelected(LPVOID lpHandle, LPBYTE lpbtLang, BYTE btLangSize, emv_APP_INFO *lpSelApp);
 *  @b Assignment:\n
 *	@brief 	Вызывается из "EMV kernel", сразу после чтения ПАНа карты(таг 5A).\n
 *	@brief 	Интерфейсное приложение может запустить ввод пар-ров транзакции в фоновом режиме \n
 *  @author:  YALCO LLC (C)
 ******************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Получает из EMV kernel ПАН(таг 5A) и трэк(таг 57) исп. функ."emv_kernelGetCardData" или "emv_kernelGetDataByTag".
 *  2.) Строит список доступных сервисов и операций.
 *  3.) Запускает процедуру ввода пар-ров транзакции(операция, валюта, сумма), в фоновом режиме.
 *	@endcode
 *  @b Use in:
 *	@code
 *      - emv_kernel_run();"EMV kernel"
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle   - handle from emv_RunTransaction \n
 *  @b LPBYTE lpbtLang   - pointer to input language buffer	  \n
 *  @b BYTE   btLangSize - language buffer size               \n
 *  @b emv_APP_INFO *lpSelApp	- pointer to selected app data
 ******************************************************************************************************************
 *  @return void
 ******************************************************************************************************************
*/
void WINAPI emv_fAppSelected(LPVOID lpHandle,
							 LPBYTE lpbtLang, BYTE btLangSize,
							 emv_APP_INFO *lpSelApp)
{
	printf("\r\nemv_fAppSelected()...");
	

	if(btLangSize <= sizeof(InbtLang)){
		memcpy(InbtLang,lpbtLang, btLangSize);
		InbtLangSize=btLangSize;
	}//Получаем язык.

	memcpy(&InSelApp,lpSelApp,sizeof(InSelApp));//Получаем указатель на выбранное приложение.
	
	{					
		DWORD Tid;
		SECURITY_ATTRIBUTES sa;
		sa.nLength = sizeof(sa);
		sa.bInheritHandle = FALSE;
		sa.lpSecurityDescriptor = NULL;
		//Запускаем в отдельном потоке интерфейс ввода параметров транзакции.
		//При этом карта продолжает "читаться" в EMV Kernel lib
		hInTrDataThread = CreateThread(&sa,0,(LPTHREAD_START_ROUTINE)InGetTrData,NULL,0,&Tid);	
		if(!hInTrDataThread){
			//"CreateThread InGetTrData ERROR"
		}
	}
}

DWORD InGetTrData(LPVOID lpParam)
{
	printf("\r\nInGetTrData...");
	//MessageBox(NULL,"InGetTrData frome emv_fAppSelected","EmvWin OK!",MB_OK);
	DWORD tag_len = 0;
	BYTE pan[10] = {0};
	if(EmvGetTagProcAddr)
	{
		if(!EmvGetTagProcAddr(0x5A,pan,&tag_len,sizeof(pan)))	//получение ПАНа
		{
			char span[100];
			memset(span,0,sizeof(span));
			bin2hex(pan,(BYTE*)span,tag_len);
			printf("\r\nPAN = %s",span);
			//Поиск пана в стоп листе...		
			;
			//Формирование интерфейса ввода параметров транзакции на основе ПАНа
			
			InTrData._9C[0] = 0;//00 Goods and service ISO 8583:1993(E), A.9 Processing codes:
			
			InTrData._5F2A[0] = 0x08;// USD
			InTrData._5F2A[1] = 0x40;// USD

			InTrData._9F02[0] = 0x00;
			InTrData._9F02[1] = 0x00;
			InTrData._9F02[2] = 0x00;
			InTrData._9F02[3] = 0x01;// => 100,00 USD
			InTrData._9F02[4] = 0x00;// => 100,00 USD
			InTrData._9F02[5] = 0x00;// => 100,00 USD
			//MessageBox(NULL,"Inputing of amount, currency and type of transaction","Inputing transacThread",MB_OK);
		}
	}

	return 0;
}

/**
 ******************************************************************************************************************
 *	@fn BYTE WINAPI emv_fSelLang(LPVOID lpHandle, LPBYTE lpbtLang, BYTE btMaxSize);
 *  @b Assignment:\n
 *	@brief 	Вызывается из "EMV kernel", в случае необходимости в выборе языка.\n
 *	@brief 	Предлагает клиенту выбрать язык интерфейса\n
 *  @author:  YALCO LLC (C)
 ******************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Формирует экран выбора языка.
 *  2.) Возвращает в "EMV kernel" язык, выбранный клиентом.
 *	@endcode
 *  @b Use in:
 *	@code
 *      - emv_kernel_run();"EMV kernel"
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle - handle from emv_RunTransaction \n
 *  @b LPBYTE lpbtLang - pointer to output language buffer		\n
 *  @b BYTE btMaxSize - max output buffer size
 ******************************************************************************************************************
 *  @param Exit: \n
 *  @b LPBYTE lpbtLang - pointer to output language buffer
 ******************************************************************************************************************
 *  @return BYTE:\n
 *  @b 0		- canceled				\n
 *  @b other	- language buffer size
 ******************************************************************************************************************
*/
BYTE WINAPI emv_fSelLang(LPVOID lpHandle,LPBYTE lpbtLang,BYTE btMaxSize)
{
	printf("\r\nemv_fSelLang...");
	lpbtLang[0] = 0x45;//'E'
	lpbtLang[1] = 0x4E;//'N'

	return 2;//language buffer size
}
/**
 ******************************************************************************************************************
 *	@fn BYTE WINAPI emv_fSelApp(LPVOID lpHandle, BYTE   btRetry,  LPBYTE lpbtLang, BYTE btLangSize, emv_APP_INFO *lpAppList, BYTE btAppListSize);
 *  @b Assignment:\n
 *	@brief 	Вызывается из "EMV kernel", в случае необходимости в выборе приложения клиентом.
 *	@brief 	Предлагает клиенту выбрать приложение из списка, в соответствии с кандидат-листом\n
 *  @author:  YALCO LLC (C)
 ******************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Формирует экран выбора приложения.
 *  2.) Возвращает в "EMV kernel" порядковый номер, выбранного приложения.
 *	@endcode
 *  @b Use in:
 *	@code
 *      - emv_kernel_run();"EMV kernel"
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle	- handle from emv_RunTransaction				\n
 *  @b BYTE btRetry		- retry pin entry flag (0 - 1st, other - retry)
 *  @b LPBYTE lpbtLang	- pointer to buffer with selected language
 *  @b BYTE btLangSize	- buffer with selected language
 *  @b emv_APP_INFO - *lpAppList - array with app to select info	\n
 *  @b WORD wAppListSize- array size
 ******************************************************************************************************************
 *  @return WORD:\n
 *  @b 0xFFFF - cancel			\n
 *  @b other - selected index
 ******************************************************************************************************************
*/
BYTE WINAPI emv_fSelApp(LPVOID lpHandle,
						BYTE btRetry,
						LPBYTE lpbtLang, 
						BYTE btLangSize,
						emv_APP_INFO *lpAppList,
						BYTE btAppListSize)
{
	printf("\r\nemv_fSelApp...");

	BYTE i;

	for (i = 0; i<CARD_AID_COUNT && i < btAppListSize; i++)
	{
		//Данные в pAppList[i].btIsoAppLabel представлены в соответствии с кодовой таблицей ISO 8859.
		//Нужно перевести в понятный для Windows формат. Номер кодовой таблицы в структуре укаазан.
	}

	//Выводим список приложений на экран для выбора клиентом на языке в Language.

	//Возвращаем индеск выбранного приложения.
	return 0;
}

/**
 ******************************************************************************************************************
 *	@fn BYTE WINAPI emv_fAttGetTrData(LPVOID lpHandle, LPBYTE lpbtLang, BYTE btLangSize, emv_APP_INFO *lpSelApp,emv_TRANS_DATA *lpTrData);
 *  @b Assignment:\n
 *	@brief 	Вызывается из "EMV kernel", для получения пара-ров транзакции(Операция, Валюта, Сумма).
 *	@brief 	Using if Attended terminal: 
 *	@brief 	(TermParam._9F35[0]>>4) == 2 ( Merchant )
 *	@brief 	||
 *	@brief 	(
 *	@brief 	TermParam.Flag_5F57 && // Select Account(Specification Update Bulletin No. 39)
 *	@brief 	CheckTags._9F38.TagPresent && 
 *	@brief 	FindTag2Dol(0x5F57, CheckTags._9F38.TagLen, CardData._9F38)
 *	@brief 	 )
 *	@brief 	 && emv_fAttGetTRData
 *	@brief 	
 *  @author:  YALCO LLC (C)
 ******************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Формирует экран ввода счёта для перевода средств.(If transaction is transfer)
 *  2.) Формирует экран выбора типа операции.
 *  3.) Формирует экран выбора валюты.
 *  4.) Формирует экран выбора суммы.
 *  5.) Проверяет наличие карты в стоп-листе.
 *  6.) Возвращает в "EMV kernel" выбранные параметры транзакции.
 *	@endcode
 *  @b Use in:
 *	@code
 *      - emv_kernel_run();"EMV kernel"
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle		- handle from emv_RunTransaction		\n
 *  @b LPBYTE lpbtLang		- pointer to buffer with selected lang		\n
 *  @b BYTE btLangSize		- buffer with selected lang size			\n			
 *  @b emv_APP_INFO *lpSelApp	- pointer to selected app data
 ******************************************************************************************************************
 *  @param Exit: \n
 *  @b emv_TRANS_DATA *lpTrData - pointer to buffer to fill with tr data
 ******************************************************************************************************************
 *  @return BYTE:\n
 *  @b 0 - ok			\n
 *  @b other - cancel
 ******************************************************************************************************************
*/
BYTE WINAPI emv_fAttGetTrData(LPVOID lpHandle,
							  LPBYTE lpbtLang, BYTE btLangSize,
							  emv_APP_INFO *lpSelApp,
							  emv_TRANS_DATA *lpTrData)
{		
	printf("\r\nemv_fAttGetTrData...");
	return 0;
}

/**
 ******************************************************************************************************************
 *	@fn BYTE WINAPI emv_fGetTrData(LPVOID lpHandle, emv_TRANS_DATA *lpTrData);
 *  @b Assignment:\n
 *	@brief 	Вызывается из "EMV kernel", для получения пара-ров транзакции(Операция, Валюта, Сумма).
 *  @author:  YALCO LLC (C)
 ******************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Формирует экран ввода счёта для перевода средств.(If transaction is transfer)
 *  2.) Формирует экран выбора типа операции.
 *  3.) Формирует экран выбора валюты.
 *  4.) Формирует экран выбора суммы.
 *  5.) Проверяет наличие карты в стоп-листе.
 *  6.) Возвращает в "EMV kernel" выбранные параметры транзакции.
 *	@endcode
 *  @b Use in:
 *	@code
 *      - emv_kernel_run();"EMV kernel"
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle		- handle from emv_RunTransaction		\n
 *  @b emv_APP_INFO *lpSelApp	- pointer to selected app data
 ******************************************************************************************************************
 *  @param Exit: \n
 *  @b emv_TRANS_DATA *lpTrData - pointer to buffer to fill with tr data
 ******************************************************************************************************************
 *  @return BYTE:\n
 *  @b 0 - ok			\n
 *  @b other - cancel
 ******************************************************************************************************************
*/
BYTE WINAPI emv_fGetTrData(LPVOID lpHandle,emv_TRANS_DATA *lpTrData)
{
	printf("\r\nemv_fGetTrData...");
	//MessageBox(NULL,"emv_fGetTrData","EmvWin OK!",MB_OK);


	if(hInTrDataThread)
	{
		DWORD exit_code;
		while (1)
		{
			if(GetExitCodeThread(hInTrDataThread,&exit_code) == TRUE)
			{
				if(exit_code != STILL_ACTIVE)
				{
					CloseHandle(hInTrDataThread);
					break;
				} else {
					printf("\r\nWaiting of input the amount, currency and transaction type...");
					Sleep(1000);
				}
			}	
		}
	}

	memcpy(lpTrData,&InTrData,sizeof(InTrData));
	return 0;
}

/**
 ******************************************************************************************************************
 *	@fn BYTE WINAPI emv_fGetCryptPin(LPVOID lpHandle, LPBYTE lpbtPinblock, LPBYTE lpbtSize,     BYTE btMaxSize);
 *  @b Assignment:\n
 *	@brief 	Вызывается из "EMV kernel", в случае необходимости online проверки ПИНа в ЦА.
 *	@brief 	Предлагает клиенту ввести ПИН карты\n
 *  @author:  YALCO LLC (C)
 ******************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Формирует экран ввода ПИНа.
 *  2.) Возвращает в "EMV kernel" шиврованный ПИН блок.
 *	@endcode
 *  @b Use in:
 *	@code
 *      - emv_kernel_run();"EMV kernel"
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle		- handle from emv_RunTransaction
 ******************************************************************************************************************
 *  @param Exit: \n
 *  @b LPBYTE lpbtPinblock	- pointer to buffer to store entered pin block			\n
 *  @b LPBYTE lpbtSize		- pointer to buffer to store entered pin block size		\n
 *  @b BYTE btMaxSize		- buffer to store entered pin block size
 ******************************************************************************************************************
 *  @return BYTE:\n
 *  @b 0		- ok				\n
 *  @b 1		- timeout (cancel)	\n
 *  @b other	- abort
 ******************************************************************************************************************
*/
BYTE WINAPI emv_fGetCryptPin(LPVOID lpHandle, LPBYTE lpbtPinblock, LPBYTE lpbtSize, BYTE btMaxSize)
{
	BYTE PinBlock[40];
	memset(PinBlock,0,sizeof(PinBlock));
	// ...
	lpbtPinblock[0] = PinBlock[0];
	lpbtPinblock[1] = PinBlock[1];
	lpbtPinblock[2] = PinBlock[2];
	lpbtPinblock[3] = PinBlock[3];
	lpbtPinblock[4] = PinBlock[4];
	lpbtPinblock[5] = PinBlock[5];
	lpbtPinblock[6] = PinBlock[6];
	lpbtPinblock[7] = PinBlock[7];
	*lpbtSize =8;

	printf("\r\nemv_fGetCryptPin...");
	return 0;
}

/**
 ******************************************************************************************************************
 *	@fn BYTE WINAPI emv_fGetPin(LPVOID lpHandle, BYTE   btTryCounter, BYTE btRetry, LPBYTE lpbtPinblock, LPBYTE lpbtSize,  BYTE btMaxSize);
 *  @b Assignment:\n
 *	@brief 	Вызывается из "EMV kernel", в случае необходимости проверки ПИНа картой.
 *	@brief 	Предлагает клиенту ввести ПИН карты\n
 *  @author:  YALCO LLC (C)
 ******************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Формирует экран ввода ПИНа.
 *  2.) Возвращает в "EMV kernel" введённый ПИН.
 *	@endcode
 *  @b Use in:
 *	@code
 *      - emv_kernel_run();"EMV kernel"
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle		- handle from emv_RunTransaction				\n
 *  @b BYTE   btTryCounter  - PAN Try Counter                                   \n
 *  @b BYTE   btRetry		- retry pin entry flag (0 - 1st, other - retry)
 ******************************************************************************************************************
 *  @param Exit: \n
 *  @b LPBYTE lpbtPinblock	- pointer to buffer to store entered PIN (4-12 ASCII characters)     \n
 *  @b LPBYTE lpbtSize		- Length of PIN entered (4-12 ASCII characters)                      \n
 *  @b BYTE btMaxSize		- buffer to store entered pin block size
 ******************************************************************************************************************
 *  @return BYTE:\n
 *  @b 0		- ok				\n
 *  @b 1		- timeout (cancel)	\n
 *  @b other	- abort
 ******************************************************************************************************************
*/
BYTE WINAPI emv_fGetPin(LPVOID lpHandle, BYTE   btTryCounter, BYTE btRetry, LPBYTE lpbtPinblock, LPBYTE lpbtSize, BYTE btMaxSize)
{
	printf("\r\nemv_fGetPin...");
	return 0;
}

/**
 ******************************************************************************************************************
 *	@fn BYTE WINAPI emv_fHostSwop(LPVOID lpHandle, LPBYTE btAC1, DWORD dwAC1Size, LPBYTE lpbtHostCr,LPDWORD lpdwHostCrSize, DWORD dwMaxSize, LPBYTE lpbtTag71,LPDWORD lpdwTag71Size, LPBYTE lpbtTag72,LPDWORD lpdwTag72Size);
 *  @b Assignment:\n
 *	@brief 	Вызывается из "EMV kernel", для связи с ЦА.
 *  @author:  YALCO LLC (C)
 ******************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Формирует запрос в соответствии с требованиями эмитента.
 *  1.) Execute связь с ЦА(центром авторизации).
 *	@endcode
 *  @b Use in:
 *	@code
 *      - emv_kernel_run();"EMV kernel"
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle		- handle from emv_RunTransaction			\n
 *  @b LPBYTE btAC1			- pointer to the buffer with EMV data to send (Created over "DolHostRequest" if present).\n
 *  @b                        Terminal Param file Exsample:
 *  @b                        Authoris. DolHostRequest_Len     LEN:04                                   //  
 *  @b                        Authoris. DolHostRequest       [116]:9F339F35                             //  
 *  @b DWORD dwAC1Size		- buffer with EMV data to send size
 ******************************************************************************************************************
 *  @param Exit: \n
 *  @b LPBYTE   lpbtHostCr		- pointer to the buffer to store host EMV data	\n
 *  @b LPDWORD  lpdwHostCrSize	- buffer to store host EMV data size			\n
 *  @b DWORD    dwMaxSize		- buffer to store host EMV data max length
 *  @b LPBYTE   lpbtTag71       - buffer to store Script 71 data        (can be NULL if present into lpbtHostCr)
 *  @b LPDWORD  dwTag71Size     - buffer to store Script 71 data Length (can be zero if present into lpbtHostCr)
 *  @b LPBYTE   lpbtTag72       - buffer to store Script 72 data        (can be NULL if present into lpbtHostCr)
 *  @b LPDWORD  dwTag72Size     - buffer to store Script 72 data Length (can be zero if present into lpbtHostCr)
 ******************************************************************************************************************
 *  @return BYTE:\n
 *  @b 0 - ok						\n
 *  @b other - unable to go on line
 ******************************************************************************************************************
*/
BYTE WINAPI emv_fHostSwop(LPVOID lpHandle,LPBYTE btAC1,  DWORD dwAC1Size,
						  LPBYTE lpbtHostCr,  LPDWORD lpdwHostCrSize,  DWORD dwMaxSize, 
						  LPBYTE lpbtTag71,   LPDWORD lpdwTag71Size,   DWORD dwTag71Size, 
						  LPBYTE lpbtTag72,   LPDWORD lpdwTag72Size,   DWORD dwTag72Size)
{
	char data[100];
	DWORD data_len;

	BYTE tag9F26[24];
	DWORD tag9F26Size = 0;
	//...
	BYTE tagCB[6];
	DWORD tagCBSize = 0;


	*lpdwTag71Size = 0;
	*lpdwTag72Size=0;
	
	if(EmvSetBufByDolProcAddr)
	{
		//		char str[]="9F029F0395575A";
		char str[]="9F269F279F109F379F36959A9C9F025F2A829F1A9F09F334F9F089F349F359F1E9F53849F099F41CB";
		BYTE dol[256];
		DWORD dol_size;
		BYTE out[256];
		DWORD out_len;
		DWORD out_max=sizeof(out);
		
		dol_size=strlen(str)/2;
		hex2bin((BYTE*)str,dol,dol_size);
		
		if(0 == EmvSetBufByDolProcAddr(NULL,(BYTE*)dol,dol_size,out,&out_len,out_max))
		{

		}
	}
	
	//for receive data for host from EMV kernel use EmvGetTagProcAddr();
	EmvGetTagProcAddr(0x9F26,tag9F26,&tag9F26Size,sizeof(tag9F26));
	//...
	EmvGetTagProcAddr(0xCB,tagCB,&tagCBSize,sizeof(tagCB));
	
	memset(data,0,sizeof(data));
	strcpy(data,"910A993680ED37FC095330308A023030");
	data_len = strlen(data)/2;
	if(dwMaxSize>data_len){
		hex2bin((BYTE *)data,lpbtHostCr,data_len);
		*lpdwHostCrSize = data_len;	
	}

	printf("\r\nemv_fHostSwop...");
	return 0;
}

/**
 **************************************************************************************************************************
 *	@fn BYTE WINAPI emv_fSelectAccount(LPVOID lpHandle, LPBYTE lpbtLang, BYTE btLangSize, emv_APP_INFO *lpSelApp);
 *  @b Assignment:\n
 *	@brief 	Осуществляет диалог с клиентом, если требуется выбор счёта.
 *  @author    YALCO LLC (C)
 **************************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Выводит на экран сообщения:
 *                   - Select Account:
 *                   - Savings     
 *                   - Cheque/debit
 *                   - Credit      
 *  2.) Предоставляет меню для выбора.
 *
 *	@endcode
 *  @b Use in:
 *	@code
 *      - EmvStart();
 *	@endcode
 *  @b Call functions:
 *	@code
 *      - SelectMess();
 *        Тело функции находится во внешнем приложении, которое использует библиотеку EMV.
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n:
 *  @b LPVOID lpHandle   - handle from emv_RunTransaction \n
 *  @b LPBYTE lpbtLang   - pointer to input language buffer	  \n
 *  @b BYTE   btLangSize - language buffer size               \n
 *  @b emv_APP_INFO *lpSelApp	- pointer to selected app data
 *
 *  @param Exit: \n
 *  @b None 
 ******************************************************************************************************************
 *  @return 
 *  @b BYTE - Выбор из предложенного меню:
 *  @b   0x00 => Default – no account specified.
 *  @b 	 0x10 => Savings     
 *  @b 	 0x20 => Cheque/debit
 *  @b 	 0x30 => Credit      
 *  @b   0xFF => Terminate Transaction
 ******************************************************************************************************************
*/
BYTE WINAPI emv_fSelectAccount(LPVOID lpHandle,
							   LPBYTE lpbtLang, BYTE btLangSize,
							   emv_APP_INFO *lpSelApp
							   )
{
	printf("\r\nemv_fSelectAccount...");
	return 0;
}

BOOL SelectOpenReader(void)
{
	if(AddrSelectReader)
	{
		// If 3K5 or NEURON
		if(Reader.ReaderNameLen && strlen(Reader.portName))
		{

			printf ("\r\nOpen reader:%s, port:%s",Reader.ReaderName,Reader.portName);

			if((BYTE)AddrOpenReader(Reader.ReaderName,Reader.portName) != 0)
			{
				return FALSE;
			} else {
				printf("\r\nReader  Open OK:");

				if(AddrTakeCard)
				{
					BYTE rc = AddrTakeCard(0);
					if (rc == 0)
					{
						printf("\r\nPlease insert card\r\n");
					} else 
					{
						printf("\r\nAddrTakeCard(0)err = 0x%X",rc);
					}
				}
			}
		} else {//USB reader
			//char reader_name[256];
			TCHAR reader_name[256];
			memset(reader_name,0,sizeof(reader_name));

			if(AddrSelectReader(reader_name,sizeof(reader_name))==1)
			{
				if(AddrOpenReader)
				{		
					printf("\r\nOpening of reader:%s", reader_name);
					if((BYTE)AddrOpenReader(reader_name, "") != 0)
					{
						printf("\r\nreader opened ERROR!");
					}else {
						printf("\r\nreader opened OK");
					}			
				}
			} else {
				printf("\r\nCard reader not found! Please establish smart-card reader and repeat again");
				return FALSE;
			}
		}
	}
	return TRUE;
}
int WaitInsertCard(void)
{
	if(AddrCheckConnect)
	{
		while ((BYTE)AddrCheckConnect() == 0)
		{
			printf(".");
			Sleep(1000);
		}

		// If 3K5 or NEURON
		if(Reader.ReaderNameLen && strlen(Reader.portName))
		{	
			BYTE buff[1024];
			DWORD buffSize = sizeof(buff);

			memset(buff,0,sizeof(buff));

			if(AddrGetMagData)
			{
				BYTE res;
				res = AddrGetMagData(buff, &buffSize);
				if(res == 0 || res == 0x0A)
				{
					printf("\r\nMagnit Data = ");//%s",(char*)buff);
					int i = 0;
					while ( i < buffSize )
					{
						if(buff[i] > 0x1F)
							printf("%c",buff[i]);
						else
							printf(" %02X ",buff[i]);
						i++;
					}
				}
				else
				{
					printf("\r\nGetMagData() err...");
				}
			}

			printf("\r\n");

			memset(buff,0,sizeof(buff));
			if(AddrGetTrack1)
			{
				buffSize = AddrGetTrack1(buff, sizeof(buff));
				if(buffSize > 0)
				{
					printf("\r\nGet Trak1 = %s",(char*)buff);
				}
				else
				{
					printf("\r\nTrack1 err...");
				}
			}

			memset(buff,0,sizeof(buff));
			if(AddrGetTrack2)
			{
				buffSize = AddrGetTrack2(buff, sizeof(buff));
				if(buffSize > 0)
				{
					printf("\r\nGet Trak2 = %s",(char*)buff);
				}
				else
				{
					printf("\r\nTrack2 err...");
				}
			}
		}
		return 0;
	} else {
		return -1;
	}
}

/**
 **************************************************************************************************************************
 *	@fn VOID WINAPI emv_fViewPinRes(LPVOID lpHandle, BYTE btPinResult);
 *  @b Assignment:\n
 *	@brief 	Выводит на экран результат проверки Plaintext(off_line) PIN, \n
 *  @author    YALCO LLC (C)
 **************************************************************************************************************************
 *  @b Execute:
 *	@code
 *  1.) Выводит на экран сообщение "INCORRECT PIN" or "PIN OK":
 *	@endcode
 ******************************************************************************************************************
 *  @param Entry: \n
 *  @b BYTE btPinResult;
 *  @b      1     => PIN_OK
 *  @b      other => INCORRECT_PIN
 *  @param Exit: \n
 *  @b None 
 ******************************************************************************************************************
 *  @return void
 ******************************************************************************************************************
*/
VOID WINAPI emv_fViewPinRes(LPVOID lpHandle, BYTE btPinResult)
{
	printf("emv_fViewPinRes");
}

int main(int argc, char* argv[])
{
	TCHAR reader_name[256] = _T("Athena ASEDrive IIIe USB 0\0");
	TCHAR emv_setup_file[256] = _T("test_ttype14.cfg");
	HINSTANCE hEmvDll;
	HINSTANCE hSmarCardDll;
	LONG hEmvInit;
	DWORD rc_dword;
	BYTE btTrStatus=0;
	DWORD emv_data_len=0;
	TCHAR emv_data[512];

	_tcscpy(emv_data,emv_setup_file);
	emv_data_len = _tcslen (emv_data);


	hEmvDll = LoadLibrary ("emv_ker.dll");
	
	if(hEmvDll != NULL)
	{
		if(!(EmvRegistryProcAddr	= (FUNC_EMV_KERNEL_REGISTRY)		GetProcAddress (hEmvDll,"emv_kernel_registry")))	{MessageBox(NULL,"emv_kernel_registry","ERROR",MB_OK);}
		if(!(EmvInitProcAddr		= (FUNC_EMV_KERNEL_INIT)			GetProcAddress (hEmvDll,"emv_kernelInit")))			{MessageBox(NULL,"emv_kernelInit","ERROR",MB_OK);}
		if(!(EmvUnInitProcAddr		= (FUNC_EMV_KERNEL_UNINIT	)		GetProcAddress (hEmvDll,"emv_kernelUnInit")))		{MessageBox(NULL,"emv_kernelUnInit","ERROR",MB_OK);}
		if(!(EmvRunProcAddr			= (FUNC_EMV_KER_RUN			)		GetProcAddress (hEmvDll,"emv_kernel_run")))			{MessageBox(NULL,"emv_kernel_run","ERROR",MB_OK);}
		if(!(EmvGetTagProcAddr		= (FUNC_EMV_KERNEL_GET_DATA	)		GetProcAddress (hEmvDll,"emv_kernelGetCardData")))	{MessageBox(NULL,"emv_kernelGetCardData","ERROR",MB_OK);}
		if(!(EmvSetTagProcAddr		= (FUNC_EMV_KERNEL_SET_DATA	)		GetProcAddress (hEmvDll,"emv_kernelSetCardData")))	{MessageBox(NULL,"emv_kernelSetCardData","ERROR",MB_OK);}	
		if(!(EmvSetByTagProcAddr	= (FUNC_EMV_KERNEL_SET_DATA_BY_TAG)	GetProcAddress (hEmvDll,"emv_kernelSetBerTlvData"))){MessageBox(NULL,"emv_kernelSetBerTlvData","ERROR",MB_OK);}
		if(!(EmvGetCamDataProcAddr	= (FUNC_EMV_KERNEL_GET_CAM_DATA)	GetProcAddress (hEmvDll,"emv_kernelGetCamData")))	{MessageBox(NULL,"emv_kernelGetCamData","ERROR",MB_OK);}
		if(!(EmvGetErrDataProcAddr	= (FUNC_EMV_KERNEL_GET_ERR_DATA)	GetProcAddress (hEmvDll,"emv_kernelGetErrData")))	{MessageBox(NULL,"emv_kernelGetErrData","ERROR",MB_OK);}
		if(!(EmvClearDataProcAddr	= (FUNC_EMV_KERNEL_CLEAR_DATA)		GetProcAddress (hEmvDll,"emv_kernelClearData")))	{MessageBox(NULL,"emv_kernelClearData","ERROR",MB_OK);}
		if(!(EmvGetByTagProcAddr	= (FUNC_EMV_KERNEL_GET_DATA_BY_TAG)	GetProcAddress (hEmvDll,"emv_kernelGetDataByTag")))	{MessageBox(NULL,"emv_kernelGetDataByTag","ERROR",MB_OK);}
		if(!(EmvSetBufByDolProcAddr	= (FUNC_EMV_KERNEL_GET_BUF_BY_DOL)	GetProcAddress (hEmvDll,"emv_GetTLVBufByDOL")))		{MessageBox(NULL,"emv_GetTLVBufByDOL","ERROR",MB_OK);}
		if(!(EmvSetBufByCDolProcAddr= (FUNC_EMV_KERNEL_GET_BUF_BY_CDOL)	GetProcAddress (hEmvDll,"emv_GetTLVBufByCDOL")))	{MessageBox(NULL,"emv_GetTLVBufByCDOL","ERROR",MB_OK);}
	} else {
		
		printf("\r\n%s ERROR!","LoadLibrary (emv_ker.dll)");
		return FALSE;
	}
	hSmarCardDll = LoadLibrary ("SmartCard.dll");

	if(hSmarCardDll != NULL)
	{
		if(!(AddrSelectReader    =  (PROC_SELECT_READER		)GetProcAddress (hSmarCardDll,"SelectReader"))   ){MessageBox(NULL,"SelectReader","ERROR",MB_OK);	}		
		if(!(AddrOpenReader      =  (PROC_OPEN_READER		)GetProcAddress (hSmarCardDll,"OpenReader"))     ){MessageBox(NULL,"OpenSmartReader","ERROR",MB_OK);	}
		if(!(AddrCheckConnect    =  (PROC_CHECK_CONNECT		)GetProcAddress (hSmarCardDll,"CheckConnect"))   ){MessageBox(NULL,"CheckConnect","ERROR",MB_OK);	}
		if(!(AddrWaitConnect     =  (PROC_WAIT_CONNECT		)GetProcAddress (hSmarCardDll,"WaitConnect"))    ){MessageBox(NULL,"WaitConnect","ERROR",MB_OK);		}
		if(!(AddrAnswerToReset   =  (PROC_ANSWER_TO_RESET	)GetProcAddress (hSmarCardDll,"Atr"))			){MessageBox(NULL,"Atr","ERROR",MB_OK);	}
		if(!(AddrSendApduIn      =  (PROC_SEND_APDU_IN		)GetProcAddress (hSmarCardDll,"SendApduIn"))		){MessageBox(NULL,"SendApduIn","ERROR",MB_OK);		}
		if(!(AddrSendApduOut     =  (PROC_SEND_APDU_OUT		)GetProcAddress (hSmarCardDll,"SendApduOut"))	){MessageBox(NULL,"SendApduOut","ERROR",MB_OK);		}
		if(!(AddrCloseReader     =  (PROC_CLOSE_READER		)GetProcAddress (hSmarCardDll,"CloseReader"))    ){MessageBox(NULL,"CloseReader","ERROR",MB_OK);}
		if(!(AddrTakeCard		 =  (PROC_TAKE_CARD			)GetProcAddress (hSmarCardDll,"TakeCard"))    ){MessageBox(NULL,"TakeCard","ERROR",MB_OK);}
		if(!(AddrStopTakingCard	 =  (PROC_STOP_TAKE_CARD	)GetProcAddress (hSmarCardDll,"StopTakingCard"))    ){MessageBox(NULL,"StopTakingCard","ERROR",MB_OK);}
		if(!(AddrGetCardOut		 =  (PROC_GET_CARD_OUT		)GetProcAddress (hSmarCardDll,"GetCardOut"))    ){MessageBox(NULL,"GetCardOut","ERROR",MB_OK);}
		if(!(AddrGetMagData		 =  (PROC_GET_MAG_DATA		)GetProcAddress (hSmarCardDll,"GetMagData"))    ){MessageBox(NULL,"GetMagData","ERROR",MB_OK);}

		if(!(AddrGetTrack1		 =  (PROC_GET_TRACK1		)GetProcAddress (hSmarCardDll,"GetTrack1"))    ){MessageBox(NULL,"GetTrack1","ERROR",MB_OK);}
		if(!(AddrGetTrack2		 =  (PROC_GET_TRACK2		)GetProcAddress (hSmarCardDll,"GetTrack2"))    ){MessageBox(NULL,"GetTrack2","ERROR",MB_OK);}

		if(!(AddrEjectCard		 =  (PROC_EJECT_CARD		)GetProcAddress (hSmarCardDll,"EjectCard"))    ){MessageBox(NULL,"EjectCard","ERROR",MB_OK);}
	} else {
		
		printf("\r\n%s ERROR!","LoadLibrary (SmartCard.dll)");
		FreeLibrary (hEmvDll);
		printf("\r\nEnd of program\r\nPlease press any key...");
		getchar();
		return FALSE;
	}

	if(EmvInitProcAddr)
	{			
		hEmvInit = (LONG)EmvInitProcAddr(NULL);
		if(!hEmvInit){
			printf("\r\n%s ERROR! Please check license! +7 495 973 8776 managers@yalko.ru","emv_kernelInit");
		} else 
		{
			/************************************************************************/
			/*          The CallBack(external) interface for EMV kernel function:   */
			/************************************************************************/
			if(EmvRegistryProcAddr)
			{
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_APP_SELECTED,		emv_fAppSelected	))MessageBox(NULL,_T("emv_fAppSelected"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_SELECT_LANG,		emv_fSelLang		))MessageBox(NULL,_T("emv_fSelLang"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_SELECT_APP,		emv_fSelApp			))MessageBox(NULL,_T("emv_fSelApp"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_ATT_GET_TR_DATA,	emv_fAttGetTrData	))MessageBox(NULL,_T("emv_fAttGetTrData"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_GET_TR_DATA,		emv_fGetTrData		))MessageBox(NULL,_T("emv_fGetTrData"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_GET_CRYPT_PIN,		emv_fGetCryptPin	))MessageBox(NULL,_T("emv_fGetCryptPin"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_GET_PIN,			emv_fGetPin			))MessageBox(NULL,_T("emv_fGetPin"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_HOST_SWOP,			emv_fHostSwop		))MessageBox(NULL,_T("emv_fHostSwop"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_PIN_ENTRY_RESULT,	emv_fViewPinRes		))MessageBox(NULL,_T("emv_fViewPinRes"),_T("err"),MB_OK);
				if(EmvRegistryProcAddr((LPVOID)hEmvInit,NUM_FUNC_EMV_SELECT_ACCOUNT,	emv_fSelectAccount	))MessageBox(NULL,_T("emv_fSelectAccount"),_T("err"),MB_OK);
			}
			
			memset(&Reader,0,sizeof(Reader));
			ReadReaderParamFile("reader.txt");

			if(SelectOpenReader() == FALSE)
			{
				printf ("\r\nAtm Reader  Open ERROR:");
				FreeLibrary (hEmvDll);
				FreeLibrary (hSmarCardDll);
				getchar();
				return FALSE;
			} 

			printf("\r\nPlease insert card\r\n");
			if(WaitInsertCard() == 0)
			{

				printf("\r\nStart EMV Transaction...\r\n");

				rc_dword=(BYTE)EmvRunProcAddr(	//emv_kernelRun
					(LPVOID)hEmvInit,	//LPVOID	lpHandle
					NULL,				//LPVOID	lpCallbackHandle
					btTrStatus ,		//0 => New card.  1 => The same card, the same Application .  2 => The same card, new select Application 
					(BYTE*)emv_data,			//LPBYTE	lpbtCr
					&emv_data_len,				//LPDWORD	lpdwCrSize
					sizeof(emv_data)			//DWORD		dwMaxSize
				);

				printf("\r\nEMV result = %d", rc_dword);

				printf("\r\nEMV result can be:");
				printf("\r\n	AC1:                       ");
				printf("\r\n	  0x00 - approved          ");
				printf("\r\n	  0x01 - force accept      ");
				printf("\r\n	  0x02 - decline           ");
				printf("\r\n	  0x03 - abort             ");
				printf("\r\n	  0x04 - capture           ");
				printf("\r\n	  0x05 - decline & advice  ");
				printf("\r\n	AC2:                       ");
				printf("\r\n	  0x10 - approved          ");
				printf("\r\n	  0x11 - force accept      ");
				printf("\r\n	  0x12 - decline           ");
				printf("\r\n	  0x13 - reversal          ");
				printf("\r\n	  0x14 - abort + reversal  ");
				printf("\r\n	  0x15 - capture           ");
				printf("\r\n	  0x16 - capture & reversal");
				printf("\r\n	  0x17 - approved     + advice");
				printf("\r\n	  0x18 - force accept + advice");
				printf("\r\n	  0x19 - decline      + advice");
				printf("\r\n	Other:                     ");
				printf("\r\n	  0x55 - NotAccepted       ");
				printf("\r\n	  0x66 - Card Error.       ");

				printf("\r\nEMV result = %d", rc_dword);



				{
					BYTE _9C[1];
					BYTE _9F02[6];
					BYTE _5F2A[2];
					char sdata[100];
					DWORD tag_len;

					if(!EmvGetTagProcAddr(0x9C,_9C,&tag_len,sizeof(_9C)))	//получение ПАНа
					{
						memset(sdata,0,sizeof(sdata));
						bin2hex(_9C,(BYTE*)sdata,tag_len);
						printf("\r\nTransaction Type = %s",sdata);
					}
					if(!EmvGetTagProcAddr(0x9F02,_9F02,&tag_len,sizeof(_9F02)))	//получение ПАНа
					{
						memset(sdata,0,sizeof(sdata));
						bin2hex(_9F02,(BYTE*)sdata,tag_len);
						printf("\r\nAmount = %s",sdata);
					}
					if(!EmvGetTagProcAddr(0x5F2A,_5F2A,&tag_len,sizeof(_5F2A)))	//получение ПАНа
					{
						memset(sdata,0,sizeof(sdata));
						bin2hex(_5F2A,(BYTE*)sdata,tag_len);
						printf("\r\nCurrency = %s",sdata);
					}
				}


				if ( Reader.ReaderNameLen && strlen(Reader.portName ) )
				{
					if(AddrEjectCard)
					{
						printf("\r\nEjectCard()...");
						AddrEjectCard();
					}
				} 
				else
				{
					printf("\r\nPlease remove card\r\n");
					while ((BYTE)AddrCheckConnect() == 1)
					{
						printf(".");
						Sleep(1000);
					}
				}

				//printf("\r\nPlease remove card\r\n");
				//while ((BYTE)AddrCheckConnect() == 1)
				//{
				//	printf(".");
				//	Sleep(1000);
				//}
			}	

			if(AddrCloseReader)
			{
				AddrCloseReader();
			}
		}
	}



	printf("\r\nEmv uninit...");
	EmvUnInitProcAddr(&hEmvInit);
	printf("\r\nEnd of program\r\nPlease press any key...");

	FreeLibrary (hEmvDll);
	FreeLibrary (hSmarCardDll);
	getchar();
	
	return 0;
}