How can I call API SCardTransmit(........) from C#?

A

Aaron

SCardTransmit(.....) is an API from "Winscard.dll" that used to send
commands, in bytes, to smart card and get response, also in bytes, from
that smart card, and the following is the way I used to call that API
from C#.

protected byte[] Execute()
{
//Handle the smart card that I have already got.
UIntPtr cardHandle = got card handle ;

//Buffer used to contain the command sent to smart card
//this command is used to change pin1 of sim card.
byte[] sendBuffer = build buffer needed ;

//Length of the buffer above.
int sendBufLen = sendBuffer.Length ;

//Buffer used to store the response info from the
//smart card. In my example, it is always the same,
//and I don't know the reason why.
byte[] recvBuffer = new byte[2] ;

//Length of the response buffer.
int recvBufLen = 2 ;

//The PCI info sent to the smart card,
//I get the address of this PCI from "Winscard.dll",
//and method "GetPciT0()" is defined bellow.
IntPtr sendPci = this.GetPciT0() ;

//The PCI info return back from smart card.
//and the type "Pci" is a struct I defined as bellow,
//and it is the same as its counterpart defined in C
//from MSDN.
//[StructLayout(LayoutKind.Sequential)]
//public struct Pci
//{
// public Pci(int protocol, int length)
// {
// this.protocol = protocol ;
// this.pciLength = length ;
// }
// public int protocol ;
// public int pciLength ;
//}
Pci recvPci = new Pci(0, 0) ;

//Send the command to smart card.
int ret = SCardTransmit(cardHandle, sendPci, sendBufLen,
sendBufLen, recvPci, recvBuffer,
recvBufLen
)
return recvBuffer ;
}

//Get the address of Pci from "Winscard.dll".
private IntPtr GetPciT0()
{
IntPtr handle = LoadLibrary("Winscard.dll") ;
IntPtr pci = GetProcAddress(handle, "g_rgSCardT0Pci") ;
FreeLibrary(handle) ;
return pci ;
}

[DllImport("Winscard.dll")]
private extern static int SCardTransmit
(UIntPtr cardHandle, IntPtr sendPci,
byte[] sendBuffer, int sbLength,
[In, Out] Pci recvPci,
[Out] IntPtr recvBuffer,
[In, Out] int rbLength
) ;

[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(string fileName) ;

[DllImport("kernel32.dll")]
private extern static void FreeLibrary(IntPtr handle) ;

[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr handle, string
procName) ;

The API SCardTransmit(....) can be called successfully, because the
return value from that API is "0", and also the pin1 value in smart card
is changed, but the problem is that the value of "recvBuffer" is always
the same, "0200" in hexstyle, and the hope value is "9000" if the pin1
is changed and "9804" if do not have enough rights to change that pin1.
I don't know where the problem is and how I can handle it.
there may be some problem with the transition of "recvBuffer" from
managed code to unmanaged code, I guess.

The card reader I used is "SCM SCR331 0", for other infomation about
SCardTransmit(.....), please refer to MSDN.

Hope your response, best regards.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top