#include "config.h"
#include <time.h>
#include <stdio.h>
#include <string.h>
#include "wintypes.h"
#include "pcsclite.h"
#include "winscard.h"
#include "debuglog.h"
#include "winscard_msg.h"
#include "winscard_svc.h"
#include "sys_generic.h"
#include "thread_generic.h"
#include "readerfactory.h"
#include "hotplug.h"
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <stdlib.h>
static struct _psContext
{
SCARDCONTEXT hContext;
SCARDHANDLE hCard[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
DWORD dwClientID;
PCSCLITE_THREAD_T pthThread;
sharedSegmentMsg msgStruct;
int protocol_major, protocol_minor;
} psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
LONG MSGCheckHandleAssociation(SCARDHANDLE, DWORD);
LONG MSGFunctionDemarshall(psharedSegmentMsg, DWORD, uint32_t *replySize);
LONG MSGAddContext(SCARDCONTEXT, DWORD);
LONG MSGRemoveContext(SCARDCONTEXT, DWORD);
LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, DWORD);
LONG MSGRemoveHandle(SCARDHANDLE, DWORD);
LONG MSGCleanupClient(DWORD);
static void ContextThread(LPVOID pdwIndex);
LONG ContextsInitialize(void)
{
memset(psContext, 0, sizeof(struct _psContext)*PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
return 1;
}
LONG CreateContextThread(PDWORD pdwClientID)
{
int i;
for (i = 0; i < PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
{
if (psContext[i].dwClientID == 0)
{
psContext[i].dwClientID = *pdwClientID;
*pdwClientID = 0;
break;
}
}
if (i == PCSCLITE_MAX_APPLICATIONS_CONTEXTS)
{
SYS_CloseFile(psContext[i].dwClientID);
psContext[i].dwClientID = 0;
Log2(PCSC_LOG_CRITICAL, "No more context available (max: %d)",
PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
return SCARD_F_INTERNAL_ERROR;
}
if (SYS_ThreadCreate(&psContext[i].pthThread, THREAD_ATTR_DETACHED,
(PCSCLITE_THREAD_FUNCTION( )) ContextThread,
(LPVOID) i) != 1)
{
SYS_CloseFile(psContext[i].dwClientID);
psContext[i].dwClientID = 0;
Log1(PCSC_LOG_CRITICAL, "SYS_ThreadCreate failed");
return SCARD_E_NO_MEMORY;
}
return SCARD_S_SUCCESS;
}
static void ContextThread(LPVOID dwIndex)
{
LONG rv;
DWORD dwContextIndex = (DWORD)dwIndex;
Log2(PCSC_LOG_DEBUG, "Thread is started: %d",
psContext[dwContextIndex].dwClientID);
while (1)
{
sharedSegmentMsg msgStruct = {0,};
systemAwakeAndReadyCheck();
switch (rv = SHMProcessEventsContext(psContext[dwContextIndex].dwClientID, &msgStruct, 0))
{
case 0:
if (msgStruct.mtype == CMD_CLIENT_DIED)
{
Log2(PCSC_LOG_DEBUG, "Client die: %d",
psContext[dwContextIndex].dwClientID);
MSGCleanupClient(dwContextIndex);
SYS_ThreadExit((LPVOID) NULL);
}
break;
case 1:
if (msgStruct.mtype == CMD_FUNCTION)
{
uint32_t replySize = 0;
MSGFunctionDemarshall(&msgStruct, dwContextIndex, &replySize);
if ((msgStruct.command != SCARD_TRANSMIT_EXTENDED)
&& (msgStruct.command != SCARD_CONTROL_EXTENDED))
{
sharedSegmentMsg tmpMsgStruct;
replySize += (sizeof(sharedSegmentMsg) - sizeof(msgStruct.data));
memcpy(&tmpMsgStruct, &msgStruct, replySize);
SHSharedSegmentMsgToNetworkOrder(&tmpMsgStruct);
rv = SHMMessageSend(&tmpMsgStruct, replySize,
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
}
}
else
if (msgStruct.mtype == CMD_VERSION)
{
version_struct *veStr;
veStr = (version_struct *) msgStruct.data;
ntohlVersionStruct(veStr);
psContext[dwContextIndex].protocol_major = veStr->major;
psContext[dwContextIndex].protocol_minor = veStr->minor;
Log3(PCSC_LOG_DEBUG,
"Client is protocol version %d:%d",
veStr->major, veStr->minor);
veStr->rv = SCARD_S_SUCCESS;
if ((veStr->major > PROTOCOL_VERSION_MAJOR)
|| (veStr->major == PROTOCOL_VERSION_MAJOR
&& veStr->minor > PROTOCOL_VERSION_MINOR))
{
Log3(PCSC_LOG_CRITICAL,
"Client protocol is too new %d:%d",
veStr->major, veStr->minor);
Log3(PCSC_LOG_CRITICAL,
"Server protocol is %d:%d",
PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR);
veStr->rv = SCARD_E_NO_SERVICE;
}
veStr->major = PROTOCOL_VERSION_MAJOR;
veStr->minor = PROTOCOL_VERSION_MINOR;
htonlVersionStruct(veStr);
sharedSegmentMsg tmpMsgStruct = msgStruct;
SHSharedSegmentMsgToNetworkOrder(&tmpMsgStruct);
rv = SHMMessageSend(&tmpMsgStruct, SHMCalculateMessageSize(sizeof(version_struct)),
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
}
else
continue;
break;
case 2:
break;
case -1:
Log1(PCSC_LOG_ERROR, "Error in SHMProcessEventsContext");
break;
default:
Log2(PCSC_LOG_ERROR,
"SHMProcessEventsContext unknown retval: %d", rv);
break;
}
}
}
LONG MSGFunctionDemarshall(psharedSegmentMsg msgStruct, DWORD dwContextIndex, uint32_t *replySize)
{
LONG rv;
establish_struct *esStr;
release_struct *reStr;
connect_struct *coStr;
reconnect_struct *rcStr;
disconnect_struct *diStr;
begin_struct *beStr;
cancel_struct *caStr;
end_struct *enStr;
status_struct *stStr;
transmit_struct *trStr;
control_struct *ctStr;
getset_struct *gsStr;
rv = 0;
*replySize = 0;
switch (msgStruct->command)
{
case SCARD_ESTABLISH_CONTEXT:
esStr = ((establish_struct *) msgStruct->data);
ntohlEstablishStruct(esStr);
esStr->rv = SCardEstablishContext(esStr->dwScope, 0, 0,
(int32_t *)&esStr->phContext);
if (esStr->rv == SCARD_S_SUCCESS)
esStr->rv =
MSGAddContext(esStr->phContext, dwContextIndex);
htonlEstablishStruct(esStr);
*replySize = sizeof(establish_struct);
break;
case SCARD_RELEASE_CONTEXT:
reStr = ((release_struct *) msgStruct->data);
ntohlReleaseStruct(reStr);
reStr->rv = SCardReleaseContext(reStr->hContext);
if (reStr->rv == SCARD_S_SUCCESS)
reStr->rv =
MSGRemoveContext(reStr->hContext, dwContextIndex);
htonlReleaseStruct(reStr);
*replySize = sizeof(release_struct);
break;
case SCARD_CONNECT:
coStr = ((connect_struct *) msgStruct->data);
ntohlConnectStruct(coStr);
Log3(PCSC_LOG_DEBUG, "SCardConnect hContext: 0x%08X, phCard: 0x%08X", coStr->hContext, coStr->phCard);
coStr->rv = SCardConnect(coStr->hContext, coStr->szReader,
coStr->dwShareMode, coStr->dwPreferredProtocols,
&coStr->phCard, &coStr->pdwActiveProtocol);
Log3(PCSC_LOG_DEBUG, "SCardConnect result: %d [0x%08X]", coStr->rv, coStr->rv);
if (coStr->rv == SCARD_S_SUCCESS)
{
coStr->rv =
MSGAddHandle(coStr->hContext, coStr->phCard, dwContextIndex);
Log3(PCSC_LOG_DEBUG, "MSGAddHandle result: %d [0x%08X]", coStr->rv, coStr->rv);
}
htonlConnectStruct(coStr);
*replySize = sizeof(connect_struct);
break;
case SCARD_RECONNECT:
rcStr = ((reconnect_struct *) msgStruct->data);
ntohlReconnectStruct(rcStr);
rv = MSGCheckHandleAssociation(rcStr->hCard, dwContextIndex);
if (rv != 0) return rv;
rcStr->rv = SCardReconnect(rcStr->hCard, rcStr->dwShareMode,
rcStr->dwPreferredProtocols,
rcStr->dwInitialization, &rcStr->pdwActiveProtocol);
htonlReconnectStruct(rcStr);
*replySize = sizeof(reconnect_struct);
break;
case SCARD_DISCONNECT:
diStr = ((disconnect_struct *) msgStruct->data);
ntohlDisconnectStruct(diStr);
rv = MSGCheckHandleAssociation(diStr->hCard, dwContextIndex);
if (rv != 0) return rv;
diStr->rv = SCardDisconnect(diStr->hCard, diStr->dwDisposition);
if (diStr->rv == SCARD_S_SUCCESS)
diStr->rv =
MSGRemoveHandle(diStr->hCard, dwContextIndex);
htonlDisconnectStruct(diStr);
*replySize = sizeof(disconnect_struct);
break;
case SCARD_BEGIN_TRANSACTION:
{
beStr = ((begin_struct *) msgStruct->data);
int ix;
unsigned char *px = &msgStruct->data[sizeof(begin_struct)];
for (ix = 0; ix < 32; ++ix)
*px++ = 0xEE;
beStr->rv = -99; ntohlBeginStruct(beStr);
rv = MSGCheckHandleAssociation(beStr->hCard, dwContextIndex);
if (rv != 0) return rv;
beStr->rv = SCardBeginTransaction(beStr->hCard);
htonlBeginStruct(beStr);
}
*replySize = sizeof(begin_struct);
break;
case SCARD_END_TRANSACTION:
enStr = ((end_struct *) msgStruct->data);
ntohlEndStruct(enStr);
rv = MSGCheckHandleAssociation(enStr->hCard, dwContextIndex);
if (rv != 0) return rv;
enStr->rv =
SCardEndTransaction(enStr->hCard, enStr->dwDisposition);
htonlEndStruct(enStr);
*replySize = sizeof(end_struct);
break;
case SCARD_CANCEL_TRANSACTION:
caStr = ((cancel_struct *) msgStruct->data);
ntohlCancelStruct(caStr);
rv = MSGCheckHandleAssociation(caStr->hCard, dwContextIndex);
if (rv != 0) return rv;
caStr->rv = SCardCancelTransaction(caStr->hCard);
htonlCancelStruct(caStr);
*replySize = sizeof(cancel_struct);
break;
case SCARD_STATUS:
stStr = ((status_struct *) msgStruct->data);
ntohlStatusStruct(stStr);
rv = MSGCheckHandleAssociation(stStr->hCard, dwContextIndex);
if (rv != 0) return rv;
stStr->rv = SCardStatus(stStr->hCard, stStr->mszReaderNames,
&stStr->pcchReaderLen, &stStr->pdwState,
&stStr->pdwProtocol, stStr->pbAtr, &stStr->pcbAtrLen);
htonlStatusStruct(stStr);
*replySize = sizeof(status_struct);
break;
case SCARD_TRANSMIT:
trStr = ((transmit_struct *) msgStruct->data);
ntohlTransmitStruct(trStr);
Log2(PCSC_LOG_DEBUG, "SCardTransmit cbSendLength: %d", trStr->cbSendLength);
rv = MSGCheckHandleAssociation(trStr->hCard, dwContextIndex);
if (rv != 0) return rv;
{
SCARD_IO_REQUEST ioSendPci;
SCARD_IO_REQUEST ioRecvPci;
ioSendPci.dwProtocol = trStr->pioSendPciProtocol;
ioSendPci.cbPciLength = trStr->pioSendPciLength;
trStr->rv = SCardTransmit(trStr->hCard, &ioSendPci,
trStr->pbSendBuffer, trStr->cbSendLength,
&ioRecvPci, trStr->pbRecvBuffer,
&trStr->pcbRecvLength);
trStr->pioRecvPciProtocol = ioRecvPci.dwProtocol;
trStr->pioRecvPciLength = ioRecvPci.cbPciLength;
}
Log2(PCSC_LOG_DEBUG, "SCardTransmit pcbRecvLength: %d", trStr->pcbRecvLength);
htonlTransmitStruct(trStr);
*replySize = sizeof(transmit_struct);
break;
case SCARD_CONTROL:
ctStr = ((control_struct *) msgStruct->data);
ntohlControlStruct(ctStr);
rv = MSGCheckHandleAssociation(ctStr->hCard, dwContextIndex);
if (rv != 0) return rv;
ctStr->rv = SCardControl(ctStr->hCard, ctStr->dwControlCode,
ctStr->pbSendBuffer, ctStr->cbSendLength,
ctStr->pbRecvBuffer, ctStr->cbRecvLength,
&ctStr->dwBytesReturned);
htonlControlStruct(ctStr);
*replySize = sizeof(control_struct);
break;
case SCARD_GET_ATTRIB:
gsStr = ((getset_struct *) msgStruct->data);
ntohlGetSetStruct(gsStr);
rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
if (rv != 0) return rv;
gsStr->rv = SCardGetAttrib(gsStr->hCard, gsStr->dwAttrId,
gsStr->pbAttr, &gsStr->cbAttrLen);
htonlGetSetStruct(gsStr);
*replySize = sizeof(getset_struct);
break;
case SCARD_SET_ATTRIB:
gsStr = ((getset_struct *) msgStruct->data);
ntohlGetSetStruct(gsStr);
rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
if (rv != 0) return rv;
gsStr->rv = SCardSetAttrib(gsStr->hCard, gsStr->dwAttrId,
gsStr->pbAttr, gsStr->cbAttrLen);
htonlGetSetStruct(gsStr);
*replySize = sizeof(getset_struct);
break;
case SCARD_TRANSMIT_EXTENDED:
{
transmit_struct_extended *treStr;
unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
treStr = ((transmit_struct_extended *) msgStruct->data);
ntohlTransmitStructExtended(treStr);
Log2(PCSC_LOG_DEBUG, "SCardTransmitExt cbSendLength: %d", treStr->cbSendLength);
rv = MSGCheckHandleAssociation(treStr->hCard, dwContextIndex);
if (rv != 0) return rv;
if (treStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
{
memcpy(pbSendBuffer, treStr->data,
PCSCLITE_MAX_MESSAGE_SIZE-sizeof(*treStr));
rv = SHMMessageReceive(
pbSendBuffer+PCSCLITE_MAX_MESSAGE_SIZE-sizeof(*treStr),
treStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
if (rv)
Log1(PCSC_LOG_CRITICAL, "reception failed");
}
else
memcpy(pbSendBuffer, treStr->data, treStr->cbSendLength);
{
SCARD_IO_REQUEST ioSendPci;
SCARD_IO_REQUEST ioRecvPci;
ioSendPci.dwProtocol = treStr->pioSendPciProtocol;
ioSendPci.cbPciLength = treStr->pioSendPciLength;
treStr->rv = SCardTransmit(treStr->hCard, &ioSendPci,
pbSendBuffer, treStr->cbSendLength,
&ioRecvPci, pbRecvBuffer,
&treStr->pcbRecvLength);
treStr->pioRecvPciProtocol = ioRecvPci.dwProtocol;
treStr->pioRecvPciLength = ioRecvPci.cbPciLength;
}
treStr->size = sizeof(*treStr) + treStr->pcbRecvLength;
Log3(PCSC_LOG_DEBUG, "SCardTransmitExt pcbRecvLength: %d, size: %d",
treStr->pcbRecvLength, treStr->size);
Log3(PCSC_LOG_DEBUG, "SCardTransmitExt SCardTransmit result: %d [0x%08X]",
treStr->rv, treStr->rv);
if (treStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
{
memcpy(treStr->data, pbRecvBuffer, PCSCLITE_MAX_MESSAGE_SIZE
- sizeof(*treStr));
SHSharedSegmentMsgToNetworkOrder(msgStruct);
htonlTransmitStructExtended(treStr);
rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
if (rv)
Log1(PCSC_LOG_CRITICAL, "transmission failed");
rv = SHMMessageSend(pbRecvBuffer + PCSCLITE_MAX_MESSAGE_SIZE
- sizeof(*treStr),
treStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
if (rv)
Log1(PCSC_LOG_CRITICAL, "transmission failed");
}
else
{
size_t dataSize = treStr->pcbRecvLength;
memcpy(treStr->data, pbRecvBuffer, dataSize);
size_t replySize = dataSize + sizeof(transmit_struct_extended) - 4;
Log3(PCSC_LOG_DEBUG, "SCardTransmitExt/SHMMessageSend one block: data: %d, total: %d",
dataSize, replySize);
htonlTransmitStructExtended(treStr);
rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED, psContext[dwContextIndex].dwClientID,
replySize, SHMCommunicationTimeout(), treStr);
#if 0
size_t replySize = sizeof(sharedSegmentMsg) - sizeof(msgStruct->data) + dataSize + sizeof(transmit_struct_extended) - 4;
Log3(PCSC_LOG_DEBUG, "SCardTransmitExt/SHMMessageSend one block: data: %d, total: %d",
dataSize, replySize);
SHSharedSegmentMsgToNetworkOrder(msgStruct);
htonlTransmitStructExtended(treStr);
rv = SHMMessageSend(msgStruct, replySize,
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
#endif
if (rv)
Log1(PCSC_LOG_CRITICAL, "transmission failed");
#if 0
SHSharedSegmentMsgToHostOrder(msgStruct);
#endif
}
}
break;
case SCARD_CONTROL_EXTENDED:
{
control_struct_extended *cteStr;
unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
cteStr = ((control_struct_extended *) msgStruct->data);
ntohlControlStructExtended(cteStr);
Log2(PCSC_LOG_DEBUG, "SCardControlExt cbSendLength: %d", cteStr->cbSendLength);
rv = MSGCheckHandleAssociation(cteStr->hCard, dwContextIndex);
if (rv != 0) return rv;
if (cteStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
{
memcpy(pbSendBuffer, cteStr->data,
PCSCLITE_MAX_MESSAGE_SIZE-sizeof(*cteStr));
rv = SHMMessageReceive(
pbSendBuffer+PCSCLITE_MAX_MESSAGE_SIZE-sizeof(*cteStr),
cteStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
if (rv)
Log1(PCSC_LOG_CRITICAL, "reception failed");
}
else
memcpy(pbSendBuffer, cteStr->data, cteStr->cbSendLength);
cteStr->rv = SCardControl(cteStr->hCard, cteStr->dwControlCode,
pbSendBuffer, cteStr->cbSendLength,
pbRecvBuffer, cteStr->cbRecvLength,
&cteStr->pdwBytesReturned);
cteStr->size = sizeof(*cteStr) + cteStr->pdwBytesReturned;
Log3(PCSC_LOG_DEBUG, "SCardControlExt pdwBytesReturned: %d, size: %d",
cteStr->pdwBytesReturned, cteStr->size);
if (cteStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
{
memcpy(cteStr->data, pbRecvBuffer, PCSCLITE_MAX_MESSAGE_SIZE
- sizeof(*cteStr));
sharedSegmentMsg tmpMsgStruct = *msgStruct;
SHSharedSegmentMsgToNetworkOrder(&tmpMsgStruct);
htonlControlStructExtended(cteStr);
rv = SHMMessageSend(&tmpMsgStruct, sizeof(tmpMsgStruct),
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
if (rv)
Log1(PCSC_LOG_CRITICAL, "transmission failed");
rv = SHMMessageSend(pbRecvBuffer + PCSCLITE_MAX_MESSAGE_SIZE
- sizeof(*cteStr),
cteStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
if (rv)
Log1(PCSC_LOG_CRITICAL, "transmission failed");
}
else
{
size_t dataSize = cteStr->pdwBytesReturned;
memcpy(cteStr->data, pbRecvBuffer, dataSize);
dataSize = dataSize + sizeof(*cteStr) - sizeof(cteStr->data);
sharedSegmentMsg tmpMsgStruct = *msgStruct;
dataSize = SHMCalculateMessageSize(dataSize);
tmpMsgStruct.msgSize = dataSize;
SHSharedSegmentMsgToNetworkOrder(&tmpMsgStruct);
cteStr = ((control_struct_extended *) tmpMsgStruct.data);
htonlControlStructExtended(cteStr);
rv = SHMMessageSend(&tmpMsgStruct, dataSize,
psContext[dwContextIndex].dwClientID,
SHMCommunicationTimeout());
if (rv)
Log1(PCSC_LOG_CRITICAL, "transmission failed");
}
}
break;
default:
Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", msgStruct->command);
return -1;
}
return 0;
}
LONG MSGAddContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
{
psContext[dwContextIndex].hContext = hContext;
return SCARD_S_SUCCESS;
}
LONG MSGRemoveContext(SCARDCONTEXT hContext, DWORD dwContextIndex)
{
int i;
LONG rv;
if (psContext[dwContextIndex].hContext == hContext)
{
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
{
if (psContext[dwContextIndex].hCard[i] != 0)
{
PREADER_CONTEXT rContext = NULL;
DWORD dwLockId;
rv = RFReaderInfoById(psContext[dwContextIndex].hCard[i],
&rContext);
if (rv != SCARD_S_SUCCESS)
return rv;
dwLockId = rContext->dwLockId;
rContext->dwLockId = 0;
if (psContext[dwContextIndex].hCard[i] != dwLockId)
{
rv = SCARD_W_REMOVED_CARD;
}
else
{
rv = SCardStatus(psContext[dwContextIndex].hCard[i], NULL,
NULL, NULL, NULL, NULL, NULL);
}
if (rv == SCARD_W_RESET_CARD || rv == SCARD_W_REMOVED_CARD)
SCardDisconnect(psContext[dwContextIndex].hCard[i],
SCARD_LEAVE_CARD);
else
SCardDisconnect(psContext[dwContextIndex].hCard[i],
SCARD_RESET_CARD);
psContext[dwContextIndex].hCard[i] = 0;
}
}
psContext[dwContextIndex].hContext = 0;
return SCARD_S_SUCCESS;
}
return SCARD_E_INVALID_VALUE;
}
LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard, DWORD dwContextIndex)
{
int i;
if (psContext[dwContextIndex].hContext == hContext)
{
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
{
if (psContext[dwContextIndex].hCard[i] == 0)
{
psContext[dwContextIndex].hCard[i] = hCard;
break;
}
}
if (i == PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS)
{
return SCARD_F_INTERNAL_ERROR;
} else
{
return SCARD_S_SUCCESS;
}
}
return SCARD_E_INVALID_VALUE;
}
LONG MSGRemoveHandle(SCARDHANDLE hCard, DWORD dwContextIndex)
{
int i;
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
{
if (psContext[dwContextIndex].hCard[i] == hCard)
{
psContext[dwContextIndex].hCard[i] = 0;
return SCARD_S_SUCCESS;
}
}
return SCARD_E_INVALID_VALUE;
}
LONG MSGCheckHandleAssociation(SCARDHANDLE hCard, DWORD dwContextIndex)
{
int i;
for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
{
if (psContext[dwContextIndex].hCard[i] == hCard)
{
return 0;
}
}
Log2(PCSC_LOG_ERROR, "Client failed to authenticate (hCard: 0x%08X)", hCard);
SYS_Sleep(2);
return SCARD_E_INVALID_HANDLE;
}
LONG MSGCleanupClient(DWORD dwContextIndex)
{
if (psContext[dwContextIndex].hContext != 0)
{
SCardReleaseContext(psContext[dwContextIndex].hContext);
MSGRemoveContext(psContext[dwContextIndex].hContext, dwContextIndex);
}
psContext[dwContextIndex].dwClientID = 0;
psContext[dwContextIndex].protocol_major = 0;
psContext[dwContextIndex].protocol_minor = 0;
return 0;
}