private ApduResponse SendAPDU(Card card, byte[] bytesToSend, int expectedRequestLength)
{
Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU started");
Logger.TraceEvent(TraceEventType.Verbose, 0, "bytesToSend: {0}", BitConverter.ToString(bytesToSend));
Logger.TraceEvent(TraceEventType.Verbose, 0, "card connection handle: {0}", card.ConnectionHandle);
Logger.Flush();
IntPtr cardConnectionHandle = card.ConnectionHandle;
// establish a new temporary connection in case of context mismatch
if (card.ThreadId != Thread.CurrentThread.ManagedThreadId)
{
Logger.TraceEvent(TraceEventType.Verbose, 0,
string.Format("Card context mismatch. Original thread: {0}. Current thread: {1}",
card.ThreadId,
Thread.CurrentThread.ManagedThreadId));
Logger.Flush();
if (!_cardConnectionManager.IsConnectionExist(card.InternalUid, Thread.CurrentThread.ManagedThreadId))
{
// establish a new connection
var connectionResult = Connect(card.CardreaderName, card.InternalUid);
if (!connectionResult.IsSuccessful)
{
return new ApduResponse
{
ReturnCode = connectionResult.StatusCode,
RecvBuff = new byte[0],
ResponseLength = 0
};
}
// use a handle of a new connection
cardConnectionHandle = connectionResult.ConnectedCard.ConnectionHandle;
Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU: new connection established. Handle: "
+ cardConnectionHandle);
}
else
{
cardConnectionHandle = _cardConnectionManager
.GetConnection(card.InternalUid, Thread.CurrentThread.ManagedThreadId);
Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU: existed card context found. Handle: "
+ cardConnectionHandle);
}
}
var recvBuff = new byte[500];
WinscardWrapper.SCARD_IO_REQUEST pioSendRequest;
pioSendRequest.dwProtocol = card.Protocol;
pioSendRequest.cbPciLength = PciLength;
int returnCode = WinscardWrapper.SCardTransmit(
cardConnectionHandle, ref pioSendRequest,
ref bytesToSend[0], bytesToSend.Length,
ref pioSendRequest, ref recvBuff[0],
ref expectedRequestLength);
Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU ended. Return code: " + returnCode);
Logger.Flush();
//http://msdn.microsoft.com/en-us/library/windows/desktop/aa379804(v=vs.85).aspx
//The pcbRecvLength should be at least n+2 and will be set to n+2 upon return.
var result = new ApduResponse
{
RecvBuff = recvBuff,
ResponseLength = expectedRequestLength,
ReturnCode = returnCode
};
return result;
}