I contacted ReinerSCT support, and they provided a .dll
file with an example.
Here’s the example:
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//
// Das folgende Beispiel zeigt das dynaische laden/entladen einer CTAPI Dll
//
// In einer Anwendung ist der logische Ablauf wie folgt:
//
// {
// CCtapiDllSample cCtApiDll;
// cCtApiDll.Open (1,1) // Öffne Port 1 mit CTN 1
//
// ..Befehle zm Leser und zur Chipkarte
// ..Beispiel siehe Funktion GetCardMonStatus ()
//
// cCtApiDll.Close ();
// }
// Will man die Lib statisch binden so kann folgender header verwendet werden:
// #define CTAPI_RETURN STDAPI_(char)
//
// CTAPI_RETURN CT_init (unsigned short ctn,
// unsigned short pn);
//
// CTAPI_RETURN CT_data (unsigned short ctn,
// unsigned char *dad,
// unsigned char *sad,
// unsigned short lenc,
// const unsigned char *command,
// unsigned short *lenr,
// unsigned char *response);
//
// CTAPI_RETURN CT_close(unsigned short ctn);
//
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// Spezifikation der Funtionspointer gemäß MKT
typedef char (_stdcall *FUNC_CT_INIT)( unsigned short ctn,
unsigned short pn);
typedef char (_stdcall *FUNC_CT_DATA)(unsigned short ctn,
unsigned char *dad,
unsigned char *sad,
unsigned short lenc,
const unsigned char *command,
unsigned short *lenr,
unsigned char *response);
typedef char (_stdcall *FUNC_CT_CLOSE)(unsigned short ctn);
// Name der Funktionen der CTAPI gemäß MKT
#define FUNCNAME_CT_INIT "CT_init"
#define FUNCNAME_CT_DATA "CT_data"
#define FUNCNAME_CT_CLOSE "CT_close"
// Werte für SAD/DAD gemäß MKT
#define CT_DEST_CARD 0
#define CT_DEST_CT 1
#define CT_DEST_APPLICATION 2
#define CTAPI_FILENAME "ctrsct32.dll"
class CCtapiDllSample
{
public:
// Kartenstatus
enum ECardMonStatus
{
eCardReleased,
eCardInserted,
eCardError,
eCardUnknown
};
CCtapiDllSample();
virtual ~CCtapiDllSample();
// Laden/Entladen der CTAPI DLL
BOOL LoadDll ();
void FreeDll();
BOOL IsLoaded ();
// Beispielimplementierung CT_OPEN / CT_CLOSE
char Open (USHORT p_nCtn, USHORT p_nPort);
char Close ();
ECardMonStatus GetCardMonStatus ();
// Funktionspointer der CTAPI
// Können direkt von ausßen verwendet werden,
// oder über gekapselte Funktionen wie z.B. in ECardMonStatus GetCardMonStatus ();
FUNC_CT_INIT m_pFuncCtInit;
FUNC_CT_DATA m_pFuncCtData;
FUNC_CT_CLOSE m_pFuncCtClose;
protected:
// DLL Handel der CTAPI-DLL
HINSTANCE m_hDLL;
USHORT m_nCtn;
USHORT m_nPort;
};
CCtapiDllSample::CCtapiDllSample()
{
m_pFuncCtInit=0;
m_pFuncCtData=0;
m_pFuncCtClose=0;
m_hDLL=0;
m_nCtn=1;
m_nPort=0;
}
CCtapiDllSample::~CCtapiDllSample()
{
FreeDll ();
}
void CCtapiDllSample::FreeDll()
{
try
{
if (m_hDLL )
{
FreeLibrary (m_hDLL);
}
}
catch (...)
{
ASSERT (0);
};
m_pFuncCtInit=0;
m_pFuncCtData=0;
m_pFuncCtClose=0;
m_hDLL=0;
};
BOOL CCtapiDllSample::LoadDll ()
{
INT nRet=0;
m_hDLL = LoadLibraryA (CTAPI_FILENAME);
if (!m_hDLL) return false;
m_pFuncCtInit= (FUNC_CT_INIT)::GetProcAddress(m_hDLL,FUNCNAME_CT_INIT);
m_pFuncCtData= (FUNC_CT_DATA)::GetProcAddress(m_hDLL,FUNCNAME_CT_DATA);;
m_pFuncCtClose=(FUNC_CT_CLOSE)::GetProcAddress(m_hDLL,FUNCNAME_CT_CLOSE);
if (!m_pFuncCtInit || !m_pFuncCtData || !m_pFuncCtClose)
{
FreeDll();
return false;
}
return true;
}
BOOL CCtapiDllSample::IsLoaded ()
{
return m_hDLL!=0;
}
char CCtapiDllSample::Open (USHORT p_nCtn, USHORT p_nPort)
{
LoadDll ();
ASSERT (m_pFuncCtInit);
m_nPort=p_nPort;
return m_pFuncCtInit (p_nCtn,p_nPort);
};
char CCtapiDllSample::Close ()
{
ASSERT (m_pFuncCtClose);
return m_pFuncCtClose (m_nCtn);
};
CCtapiDllSample::ECardMonStatus CCtapiDllSample::GetCardMonStatus ()
{
ASSERT (m_pFuncCtData);
BYTE Dad=CT_DEST_CT;
BYTE Sad=CT_DEST_APPLICATION;
ULONG nRelevantByte=0;
BYTE Cmd[]={0x20, 0x13, 0x00, 0x80, 0x00};
USHORT Lc=5;
BYTE Rsp[100];
USHORT Lr=sizeof (Rsp);
INT nRet=-1;
nRet=m_pFuncCtData (m_nCtn,&Dad,&Sad,Lc,Cmd,&Lr,Rsp);
if (nRet<0)
return eCardError;
if (Lr < 3)
return eCardError;
// Ermittle SW1SW2
if (((USHORT) ((Rsp[Lr-2]*0x0100)+(Rsp[Lr-1]))) != 0x9000)
return eCardError;
// Ermittle nun Card Status
switch (Lr)
{
case 3:
// Nötig zur Abwärtskompatiblität V0.9
// Eigentlich nur cyberjack KB
nRelevantByte=0;
break;
case 4:
nRelevantByte=0;
break;
case 5:
if (Rsp[0] != 0x80 || Rsp[1]!=0x01)
return eCardError;
// Tag 80 gefunden
nRelevantByte=2;
break;
default:
return eCardError;
break;
};
return (Rsp[nRelevantByte] & 0x01) ? eCardInserted : eCardReleased;;
};
I think it is possible to use a .dll
file in Xojo with a Declare
statement as far as I know.
Three different functions I can use: CT_init
, CT_data
and CT_close
.
But I am not sure how to use them. I assume that CT_init
and CT_close
are to start and stop the connection and CT_data
to get data from the smart card.
This is what I tried so far:
Declare Function init Lib "Ctrsct32" Alias "CT_init" (ctn As Integer, pn As Integer) as CString
Declare Function data Lib "Ctrsct32" Alias "CT_data" (ctn As Integer, dad As CString, sad As CString, lenc As Integer, command As CString, lenr As Integer, response As CString) as CString
Declare Function close Lib "Ctrsct32" Alias "CT_close" (ctn As Integer) as CString
Var value As CString
Try
value = init(1,1)
Catch e As FunctionNotFoundException
MessageBox(e.Message)
End Try
After I execute this code by pressing a button, I get this error: