#include "..\..\..\..\pilot_nt.h"


extern "C"
{


  fcard_authorize  card_authorize;
  fcard_authorize2 card_authorize2;
  fcard_authorize3 card_authorize3;
  fcard_authorize4 card_authorize4;
  fcard_authorize5 card_authorize5;
  fcard_authorize6 card_authorize6;
  fcard_authorize6_ext card_authorize6_ext;
  fcard_authorize7 card_authorize7;
  fcard_authorize8 card_authorize8;
  fcard_complete_multi_auth8 card_complete_multi_auth8;
  fcard_authorize9 card_authorize9;
  fcard_authorize10 card_authorize10;
  fcard_authorize11 card_authorize11;
  fcard_authorize12 card_authorize12;
  fcard_authorize13 card_authorize13;
  fcard_authorize14 card_authorize14;
  fcard_authorize15 card_authorize15;
  fGetTerminalID GetTerminalID;
  fServiceMenu ServiceMenu;
  fclose_day close_day;
  fclose_day_info close_day_info;
  fget_statistics get_statistics;
  fGetVer GetVer;
  fSetConfigData SetConfigData;
  fDone Done;
  fEnableReader EnableReader;
  fDisableReader DisableReader;
  fTestPinpad TestPinpad;
  fSuspendTrx SuspendTrx;
  fCommitTrx CommitTrx;
  fRollbackTrx RollbackTrx;
  fAbortTransaction AbortTransaction;
  fAddMerchantCheque AddMerchantCheque;
  fReadCard ReadCard;
  fReadCardSB ReadCardSB;
  fReadCardWithType ReadCardWithType;
  fReadMaskedCardWithType ReadMaskedCardWithType;
  fReadTrack2 ReadTrack2;
  fReadCardTrack3 ReadCardTrack3;
  fReadSbercard ReadSbercard;
  fReadCardAndName ReadCardAndName;
  fReadCardFull ReadCardFull;
  fReadCardContext ReadCardContext;
  fAskCardHolderAbout AskCardHolderAbout;
  fSetGUIHandles SetGUIHandles;
  fEjectCard EjectCard;

#ifdef TEST_NO_VENDING_FUNCTIONS_IN_HEADER
//!!!this is for test whether the library can be loaded after removing same functions from the pilot_nt.h
  typedef int (*fCaptureCard)();
  fCaptureCard CaptureCard;
  typedef int (*fTestCard)();
  fTestCard TestCard;
  typedef int (*fOpenKeyboard)();
  fOpenKeyboard OpenKeyboard;
  typedef int (*fCloseKeyboard)();
  fCloseKeyboard CloseKeyboard;
  typedef int (*fReadKeyboard)();
  fReadKeyboard ReadKeyboard;
  typedef int (*fTestHardware)();
  fTestHardware TestHardware;
#endif
  
  fPilotGetHostStatus PilotGetHostStatus;
  fPilotCloseReader PilotCloseReader;
  fctxAlloc ctxAlloc;
  fctxFree ctxFree;
  fctxClear ctxClear;
  fctxSetString ctxSetString;
  fctxSetInt ctxSetInt;
  fctxSetBinary ctxSetBinary;
  fctxGetString ctxGetString;
  fctxGetInt ctxGetInt;
  fctxGetBinary ctxGetBinary;
  fGetOperationStatusByRequestId GetOperationStatusByRequestId;
}


static const char ccard_authorize[]="_card_authorize";
static const char ccard_authorize2[]="_card_authorize2";
static const char ccard_authorize3[]="_card_authorize3";
static const char ccard_authorize4[]="_card_authorize4";
static const char ccard_authorize5[]="_card_authorize5";
static const char ccard_authorize6[]="_card_authorize6";
static const char ccard_authorize6_ext[]="_card_authorize6_ext";
static const char ccard_authorize7[]="_card_authorize7";
static const char ccard_authorize8[]="_card_authorize8";
static const char ccard_complete_multi_auth8[]="_card_complete_multi_auth8";
static const char ccard_authorize9[]="_card_authorize9";
static const char ccard_authorize10[]="_card_authorize10";
static const char ccard_authorize11[]="_card_authorize11";
static const char ccard_authorize12[]="_card_authorize12";
static const char ccard_authorize13[]="_card_authorize13";
static const char ccard_authorize14[]="_card_authorize14";
static const char ccard_authorize15[]="_card_authorize15";
static const char cGetTerminalID[]="_GetTerminalID";
static const char cServiceMenu[]="_ServiceMenu";
static const char cclose_day[]="_close_day";
static const char cclose_day_info[]="_close_day_info";
static const char cget_statistics[]="_get_statistics";
static const char cGetVer[]="_GetVer";
static const char cSetConfigData[]="_SetConfigData";
static const char cDone[]="_Done";
static const char cEnableReader[]="_EnableReader";
static const char cDisableReader[]="_DisableReader";
static const char cTestPinpad[]="_TestPinpad";
static const char cSuspendTrx[]="_SuspendTrx";
static const char cCommitTrx[]="_CommitTrx";
static const char cRollbackTrx[]="_RollbackTrx";
static const char cAbortTransaction[]="_AbortTransaction";
static const char cAddMerchantCheque[]="_AddMerchantCheque";
static const char cReadCard[]="_ReadCard";
static const char cReadCardSB[]="_ReadCardSB";
static const char cReadCardWithType[]="_ReadCardWithType";
static const char cReadMaskedCardWithType[]="_ReadMaskedCardWithType";
static const char cReadTrack2[]="_ReadTrack2";
static const char cReadCardTrack3[]="_ReadCardTrack3";
static const char cReadSbercard[]="_ReadSbercard";
static const char cReadCardAndName[]="_ReadCardAndName";
static const char cReadCardFull[]="_ReadCardFull";
static const char cReadCardContext[]="_ReadCardContext";
static const char cAskCardHolderAbout[]="_AskCardHolderAbout";
static const char cSetGUIHandles[]="_SetGUIHandles";
static const char cEjectCard[]="_EjectCard";
static const char cCaptureCard[]="_CaptureCard";
static const char cTestCard[]="_TestCard";
static const char cOpenKeyboard[]="_OpenKeyboard";
static const char cCloseKeyboard[]="_CloseKeyboard";
static const char cReadKeyboard[]="_ReadKeyboard";
static const char cTestHardware[]="_TestHardware";
static const char cPilotGetHostStatus[]="_PilotGetHostStatus";
static const char cPilotCloseReader[]="_PilotCloseReader";
static const char cctxAlloc[]="_ctxAlloc";
static const char cctxFree[]="_ctxFree";
static const char cctxClear[]="_ctxClear";
static const char cctxSetString[]="_ctxSetString";
static const char cctxSetInt[]="_ctxSetInt";
static const char cctxSetBinary[]="_ctxSetBinary";
static const char cctxGetString[]="_ctxGetString";
static const char cctxGetInt[]="_ctxGetInt";
static const char cctxGetBinary[]="_ctxGetBinary";
static const char cGetOperationStatusByRequestId[]="_GetOperationStatusByRequestId";

void FreePilotNt(HMODULE dll);

#define cat(a, b) a ## b
template<typename t> 
t load_function(HMODULE h, const char* name)
{
#ifdef WINCE
  return (t)::GetProcAddress(h, name+1);
#else
  return (t)::GetProcAddress(h, name);
#endif  /*WINCE*/
}

#ifdef WINCE
#define LOAD_FUNCTION(f, t, h, n, e)\
  if ((f=(t)::GetProcAddress(h, n+1))==NULL)\
  {\
    FreePilotNt(h);\
    *e=n;\
    h=NULL;\
    goto err_exit;\
  }\

#else
#define LOAD_FUNCTION(v)\
  if ((v=load_function<cat(f, v)>(dll, cat(c, v)))==NULL)\
  {\
    FreePilotNt(dll);\
    dll=NULL;\
    *nameOfTheUncknownFunction=cat(c, v);\
    goto err_exit;\
  }\

#endif /*WINCE*/


HMODULE LoadPilotNt(const char* name, const char** nameOfTheUncknownFunction)
{
  if (nameOfTheUncknownFunction)
    *nameOfTheUncknownFunction=NULL;

  HMODULE dll=LoadLibrary(name);
  if (!dll)
  {
    goto err_exit;
  }

  LOAD_FUNCTION(card_authorize)
  LOAD_FUNCTION(card_authorize2)
  LOAD_FUNCTION(card_authorize3)
  LOAD_FUNCTION(card_authorize4)
  LOAD_FUNCTION(card_authorize5)
  LOAD_FUNCTION(card_authorize6)
  LOAD_FUNCTION(card_authorize6_ext)
  LOAD_FUNCTION(card_authorize7)
  LOAD_FUNCTION(card_authorize8)
  LOAD_FUNCTION(card_complete_multi_auth8)
  LOAD_FUNCTION(card_authorize9)
  LOAD_FUNCTION(card_authorize10)
  LOAD_FUNCTION(card_authorize11)
  LOAD_FUNCTION(card_authorize12)
  LOAD_FUNCTION(card_authorize13)
  LOAD_FUNCTION(card_authorize14)
  LOAD_FUNCTION(card_authorize15)
  LOAD_FUNCTION(GetTerminalID)
  LOAD_FUNCTION(ServiceMenu)
  LOAD_FUNCTION(close_day)
  LOAD_FUNCTION(close_day_info)
  LOAD_FUNCTION(get_statistics)
  LOAD_FUNCTION(GetVer)
  LOAD_FUNCTION(SetConfigData)
  LOAD_FUNCTION(Done)
  LOAD_FUNCTION(EnableReader)
  LOAD_FUNCTION(DisableReader)
  LOAD_FUNCTION(TestPinpad)
  LOAD_FUNCTION(SuspendTrx)
  LOAD_FUNCTION(CommitTrx)
  LOAD_FUNCTION(RollbackTrx)
  LOAD_FUNCTION(AbortTransaction)
  LOAD_FUNCTION(AddMerchantCheque)
  LOAD_FUNCTION(ReadCard)
  LOAD_FUNCTION(ReadCardSB)
  LOAD_FUNCTION(ReadCardWithType)
  LOAD_FUNCTION(ReadMaskedCardWithType)
  LOAD_FUNCTION(ReadTrack2)
  LOAD_FUNCTION(ReadCardTrack3)
  LOAD_FUNCTION(ReadSbercard)
  LOAD_FUNCTION(ReadCardAndName)
  LOAD_FUNCTION(ReadCardFull)
  LOAD_FUNCTION(ReadCardContext)
  LOAD_FUNCTION(AskCardHolderAbout)
  LOAD_FUNCTION(SetGUIHandles)
  LOAD_FUNCTION(EjectCard)  
#ifdef TEST_NO_VENDING_FUNCTIONS_IN_HEADER
  LOAD_FUNCTION(CaptureCard)
  LOAD_FUNCTION(TestCard)
  LOAD_FUNCTION(OpenKeyboard)
  LOAD_FUNCTION(CloseKeyboard)
  LOAD_FUNCTION(ReadKeyboard)
  LOAD_FUNCTION(TestHardware)
#endif /*TEST_NO_VENDING_FUNCTIONS_IN_HEADER*/
  LOAD_FUNCTION(PilotGetHostStatus)
  LOAD_FUNCTION(PilotCloseReader)
  LOAD_FUNCTION(ctxAlloc)
  LOAD_FUNCTION(ctxFree)
  LOAD_FUNCTION(ctxClear)
  LOAD_FUNCTION(ctxSetString)
  LOAD_FUNCTION(ctxSetInt)
  LOAD_FUNCTION(ctxSetBinary)
  LOAD_FUNCTION(ctxGetString)
  LOAD_FUNCTION(ctxGetInt)
  LOAD_FUNCTION(ctxGetBinary)
  LOAD_FUNCTION(GetOperationStatusByRequestId)


err_exit:
  return dll;
}


void FreePilotNt(HMODULE dll)
{
  if (dll)
    FreeLibrary(dll);
  card_authorize=NULL;
  card_authorize2=NULL;
  card_authorize3=NULL;
  card_authorize4=NULL;
  card_authorize5=NULL;
  card_authorize6=NULL;
  card_authorize6_ext=NULL;
  card_authorize7=NULL;
  card_authorize8=NULL;
  card_complete_multi_auth8=NULL;
  card_authorize9=NULL;
  card_authorize10=NULL;
  card_authorize11=NULL;
  card_authorize12=NULL;
  card_authorize13=NULL;
  card_authorize14=NULL;
  card_authorize15=NULL;
  GetTerminalID=NULL;
  ServiceMenu=NULL;
  close_day=NULL;
  close_day_info=NULL;
  get_statistics=NULL;
  GetVer=NULL;
  SetConfigData=NULL;
  Done=NULL;
  EnableReader=NULL;
  DisableReader=NULL;
  TestPinpad=NULL;
  SuspendTrx=NULL;
  CommitTrx=NULL;
  RollbackTrx=NULL;
  AbortTransaction=NULL;
  AddMerchantCheque=NULL;
  ReadCard=NULL;
  ReadCardSB=NULL;
  ReadCardWithType=NULL;
  ReadMaskedCardWithType=NULL;
  ReadTrack2=NULL;
  ReadCardTrack3=NULL;
  ReadSbercard=NULL;
  ReadCardAndName=NULL;
  ReadCardFull=NULL;
  ReadCardContext=NULL;
  AskCardHolderAbout=NULL;
  SetGUIHandles=NULL;
  EjectCard=NULL;
/*
  CaptureCard=NULL;
  TestCard=NULL;
  OpenKeyboard=NULL;
  CloseKeyboard=NULL;
  ReadKeyboard=NULL;
  TestHardware=NULL;
*/
  PilotGetHostStatus=NULL;
  PilotCloseReader=NULL;
  ctxAlloc=NULL;
  ctxFree=NULL;
  ctxClear=NULL;
  ctxSetString=NULL;
  ctxSetInt=NULL;
  ctxSetBinary=NULL;
  ctxGetString=NULL;
  ctxGetInt=NULL;
  ctxGetBinary=NULL;
  GetOperationStatusByRequestId = NULL;
}