You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
596 lines
21 KiB
596 lines
21 KiB
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include "MarshalPC.h"
|
|
#include <tchar.h>
|
|
#include "carddbg.h"
|
|
|
|
#if (!defined(UNICODE) && !defined(_UNICODE))
|
|
#define SCARDSTATUS "SCardStatusA"
|
|
#define GETOPENCARDNAME "GetOpenCardNameA"
|
|
#else
|
|
#define SCARDSTATUS "SCardStatusW"
|
|
#define GETOPENCARDNAME "GetOpenCardNameW"
|
|
#endif
|
|
|
|
typedef LONG (WINAPI *LPFNSCARDESTABLISHCONTEXT)(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
|
|
typedef LONG (WINAPI *LPFNSCARDSTATUS)(SCARDHANDLE, LPTSTR, LPDWORD, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
|
|
typedef LONG (WINAPI *LPFNGETOPENCARDNAME)(LPOPENCARDNAME);
|
|
typedef LONG (WINAPI *LPFNSCARDTRANSMIT)(SCARDHANDLE, LPCSCARD_IO_REQUEST, LPCBYTE, DWORD, LPSCARD_IO_REQUEST, LPBYTE, LPDWORD);
|
|
typedef LONG (WINAPI *LPFNDISCONNECT)(SCARDHANDLE, DWORD);
|
|
typedef LONG (WINAPI *LPFNSCARDRELEASECONTEXT)(SCARDCONTEXT);
|
|
typedef LONG (WINAPI *LPFNSCARDBEGINTRANSACTION)(SCARDHANDLE);
|
|
typedef LONG (WINAPI *LPFNSCARDENDTRANSACTION)(SCARDHANDLE, DWORD);
|
|
|
|
typedef struct {
|
|
HINSTANCE hPCSCInst; // winscard
|
|
HINSTANCE hPCSCInst2; // scarddlg
|
|
LPFNSCARDESTABLISHCONTEXT lpfnEstablish;
|
|
LPFNGETOPENCARDNAME lpfnOpenCard;
|
|
LPFNSCARDSTATUS lpfnStatus;
|
|
LPFNSCARDTRANSMIT lpfnSCardTransmit;
|
|
LPFNDISCONNECT lpfnDisconnect;
|
|
LPFNSCARDRELEASECONTEXT lpfnRelease;
|
|
LPFNSCARDBEGINTRANSACTION lpfnSCardBeginTransaction;
|
|
LPFNSCARDENDTRANSACTION lpfnSCardEndTransaction;
|
|
} PCSC_CTX;
|
|
|
|
#define REAL_PCSC 0
|
|
#define FAKE_PCSC 1
|
|
|
|
static PCSC_CTX axCtx[2] = // Array of contexts for each PC/SC
|
|
{
|
|
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
|
|
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
static LONG _GetCardHandle(LPCWSTR mszCardNames, LPMYSCARDHANDLE phCard);
|
|
static LONG WINAPI _MySCWTransmit(SCARDHANDLE hCard, LPCBYTE lpbIn, DWORD dwIn, LPBYTE lpBOut, LPDWORD pdwOut);
|
|
// bEnd = 0 -> LITTLE_ENDIAN ; otherwise -> BIG_ENDIAN
|
|
static LONG WINAPI hScwSetEndianness(SCARDHANDLE hCard, BOOL bEnd);
|
|
|
|
#define MAX_NAME 256
|
|
|
|
|
|
SCODE WINAPI hScwAttachToCard(SCARDHANDLE hCard, LPCWSTR mszCardNames, LPSCARDHANDLE phCard)
|
|
{
|
|
return hScwAttachToCardEx(hCard, mszCardNames, 0x00, phCard);
|
|
}
|
|
|
|
SCODE WINAPI hScwAttachToCardEx(SCARDHANDLE hCard, LPCWSTR mszCardNames, BYTE byINS, LPSCARDHANDLE phCard)
|
|
{
|
|
LPMYSCARDHANDLE phTmp = NULL;
|
|
SCODE ret = SCARD_S_SUCCESS;
|
|
|
|
LOG_BEGIN_PROXY(hScwAttachToCardEx);
|
|
|
|
__try {
|
|
|
|
if (phCard == NULL)
|
|
RaiseException(STATUS_INVALID_PARAM, 0, 0, 0);
|
|
|
|
phTmp = (LPMYSCARDHANDLE)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, sizeof(MYSCARDHANDLE));
|
|
|
|
if ((hCard == (SCARDHANDLE)NULL) && (mszCardNames == NULL)) // No PC/SC
|
|
{
|
|
phTmp->dwFlags = FLAG_NOT_PCSC;
|
|
*phCard = (SCARDHANDLE)phTmp;
|
|
return ret;
|
|
}
|
|
|
|
if ((hCard == (SCARDHANDLE)NULL) || (mszCardNames == NULL)) // real PC/SC
|
|
{
|
|
// In this case we will be using PC/SC so we init the structure
|
|
if (axCtx[REAL_PCSC].hPCSCInst == NULL)
|
|
{
|
|
axCtx[REAL_PCSC].hPCSCInst = LoadLibrary(_T("winscard.dll"));
|
|
axCtx[REAL_PCSC].hPCSCInst2 = LoadLibrary(_T("scarddlg.dll"));
|
|
}
|
|
|
|
if ((axCtx[REAL_PCSC].hPCSCInst == NULL) || (axCtx[REAL_PCSC].hPCSCInst2 == NULL))
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
|
|
if (axCtx[REAL_PCSC].lpfnEstablish == NULL)
|
|
{
|
|
// Set all calls to DLL once and for all
|
|
axCtx[REAL_PCSC].lpfnEstablish = (LPFNSCARDESTABLISHCONTEXT)GetProcAddress(axCtx[REAL_PCSC].hPCSCInst, "SCardEstablishContext");
|
|
if (axCtx[REAL_PCSC].lpfnEstablish == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[REAL_PCSC].lpfnOpenCard = (LPFNGETOPENCARDNAME)GetProcAddress(axCtx[REAL_PCSC].hPCSCInst2, GETOPENCARDNAME);
|
|
if (axCtx[REAL_PCSC].lpfnOpenCard == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[REAL_PCSC].lpfnStatus = (LPFNSCARDSTATUS)GetProcAddress(axCtx[REAL_PCSC].hPCSCInst, SCARDSTATUS);
|
|
if (axCtx[REAL_PCSC].lpfnStatus == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[REAL_PCSC].lpfnSCardTransmit = (LPFNSCARDTRANSMIT)GetProcAddress(axCtx[REAL_PCSC].hPCSCInst, "SCardTransmit");
|
|
if (axCtx[REAL_PCSC].lpfnSCardTransmit == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[REAL_PCSC].lpfnDisconnect = (LPFNDISCONNECT)GetProcAddress(axCtx[REAL_PCSC].hPCSCInst, "SCardDisconnect");
|
|
if (axCtx[REAL_PCSC].lpfnDisconnect == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[REAL_PCSC].lpfnRelease = (LPFNSCARDRELEASECONTEXT)GetProcAddress(axCtx[REAL_PCSC].hPCSCInst, "SCardReleaseContext");
|
|
if (axCtx[REAL_PCSC].lpfnRelease == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[REAL_PCSC].lpfnSCardBeginTransaction = (LPFNSCARDBEGINTRANSACTION)GetProcAddress(axCtx[REAL_PCSC].hPCSCInst, "SCardBeginTransaction");
|
|
if (axCtx[REAL_PCSC].lpfnSCardBeginTransaction == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[REAL_PCSC].lpfnSCardEndTransaction = (LPFNSCARDENDTRANSACTION)GetProcAddress(axCtx[REAL_PCSC].hPCSCInst, "SCardEndTransaction");
|
|
if (axCtx[REAL_PCSC].lpfnSCardEndTransaction == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
}
|
|
|
|
phTmp->dwFlags = FLAG_REALPCSC;
|
|
|
|
}
|
|
else if ((hCard == NULL_TX) || (mszCardNames == NULL_TX_NAME)) // PC/SC for simulator
|
|
{
|
|
// In this case we will be using PC/SC so we init the structure
|
|
if (axCtx[FAKE_PCSC].hPCSCInst == NULL)
|
|
{
|
|
axCtx[FAKE_PCSC].hPCSCInst = LoadLibrary(_T("scwwinscard.dll"));
|
|
axCtx[FAKE_PCSC].hPCSCInst2 = axCtx[FAKE_PCSC].hPCSCInst;
|
|
}
|
|
|
|
if (axCtx[FAKE_PCSC].hPCSCInst == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
|
|
if (axCtx[FAKE_PCSC].lpfnEstablish == NULL)
|
|
{
|
|
// Set all calls to DLL once and for all
|
|
axCtx[FAKE_PCSC].lpfnEstablish = (LPFNSCARDESTABLISHCONTEXT)GetProcAddress(axCtx[FAKE_PCSC].hPCSCInst, "SCardEstablishContext");
|
|
if (axCtx[FAKE_PCSC].lpfnEstablish == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[FAKE_PCSC].lpfnOpenCard = (LPFNGETOPENCARDNAME)GetProcAddress(axCtx[FAKE_PCSC].hPCSCInst2, GETOPENCARDNAME);
|
|
if (axCtx[FAKE_PCSC].lpfnOpenCard == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[FAKE_PCSC].lpfnStatus = (LPFNSCARDSTATUS)GetProcAddress(axCtx[FAKE_PCSC].hPCSCInst, SCARDSTATUS);
|
|
if (axCtx[FAKE_PCSC].lpfnStatus == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[FAKE_PCSC].lpfnSCardTransmit = (LPFNSCARDTRANSMIT)GetProcAddress(axCtx[FAKE_PCSC].hPCSCInst, "SCardTransmit");
|
|
if (axCtx[FAKE_PCSC].lpfnSCardTransmit == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[FAKE_PCSC].lpfnDisconnect = (LPFNDISCONNECT)GetProcAddress(axCtx[FAKE_PCSC].hPCSCInst, "SCardDisconnect");
|
|
if (axCtx[FAKE_PCSC].lpfnDisconnect == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[FAKE_PCSC].lpfnRelease = (LPFNSCARDRELEASECONTEXT)GetProcAddress(axCtx[FAKE_PCSC].hPCSCInst, "SCardReleaseContext");
|
|
if (axCtx[FAKE_PCSC].lpfnRelease == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[FAKE_PCSC].lpfnSCardBeginTransaction = (LPFNSCARDBEGINTRANSACTION)GetProcAddress(axCtx[FAKE_PCSC].hPCSCInst, "SCardBeginTransaction");
|
|
if (axCtx[FAKE_PCSC].lpfnSCardBeginTransaction == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
axCtx[FAKE_PCSC].lpfnSCardEndTransaction = (LPFNSCARDENDTRANSACTION)GetProcAddress(axCtx[FAKE_PCSC].hPCSCInst, "SCardEndTransaction");
|
|
if (axCtx[FAKE_PCSC].lpfnSCardEndTransaction == NULL)
|
|
RaiseException(STATUS_NO_SERVICE, 0, 0, 0);
|
|
}
|
|
|
|
phTmp->dwFlags = FLAG_FAKEPCSC;
|
|
}
|
|
else
|
|
RaiseException(STATUS_INVALID_PARAM, 0, 0, 0);
|
|
|
|
if ((hCard == (SCARDHANDLE)NULL) || (hCard == NULL_TX)) // Dialog wanted
|
|
{
|
|
phTmp->dwFlags |= FLAG_MY_ATTACH;
|
|
ret = (SCODE)_GetCardHandle(mszCardNames, phTmp);
|
|
}
|
|
else
|
|
phTmp->hCard = hCard;
|
|
|
|
// Get the protocol
|
|
if (ret == SCARD_S_SUCCESS)
|
|
{
|
|
DWORD dwLenReader, dwState, dwATRLength;
|
|
BYTE abyATR[32];
|
|
TCHAR wszReader[MAX_NAME];
|
|
|
|
dwLenReader = MAX_NAME;
|
|
dwATRLength = 32;
|
|
ret = (*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnStatus)(
|
|
phTmp->hCard,
|
|
wszReader,
|
|
&dwLenReader,
|
|
&dwState,
|
|
&phTmp->dwProtocol,
|
|
abyATR,
|
|
&dwATRLength);
|
|
|
|
// Set the default callback because we are in PC/SC config here
|
|
if (ret == SCARD_S_SUCCESS)
|
|
{
|
|
phTmp->byINS = byINS;
|
|
ret = hScwSetTransmitCallback((SCARDHANDLE)phTmp, _MySCWTransmit);
|
|
if (ret == SCARD_S_SUCCESS)
|
|
*phCard = (SCARDHANDLE)phTmp;
|
|
}
|
|
else
|
|
RaiseException(STATUS_INTERNAL_ERROR, 0, 0, 0);
|
|
}
|
|
else
|
|
RaiseException(STATUS_INTERNAL_ERROR, 0, 0, 0);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
if (phTmp)
|
|
HeapFree(GetProcessHeap(), 0, phTmp);
|
|
|
|
if (ret == SCARD_S_SUCCESS)
|
|
{
|
|
switch(GetExceptionCode())
|
|
{
|
|
case STATUS_INVALID_PARAM:
|
|
ret = MAKESCODE(SCW_E_INVALIDPARAM);
|
|
break;
|
|
|
|
case STATUS_NO_MEMORY:
|
|
case STATUS_ACCESS_VIOLATION:
|
|
ret = MAKESCODE(SCW_E_BUFFERTOOSMALL);
|
|
break;
|
|
|
|
case STATUS_NO_SERVICE:
|
|
ret = SCARD_E_NO_SERVICE;
|
|
break;
|
|
|
|
default:
|
|
ret = SCARD_F_UNKNOWN_ERROR;
|
|
}
|
|
} // Otherwise ret was set already
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
SCODE WINAPI hScwDetachFromCard(SCARDHANDLE hCard)
|
|
{
|
|
SCODE ret = SCARD_S_SUCCESS;
|
|
LPMYSCARDHANDLE phTmp = (LPMYSCARDHANDLE)hCard;
|
|
|
|
LOG_BEGIN_PROXY(hScwDetachFromCard);
|
|
|
|
__try {
|
|
|
|
if (phTmp == NULL)
|
|
RaiseException(STATUS_INVALID_PARAM, 0, 0, 0);
|
|
|
|
if (phTmp->dwFlags & FLAG_MY_ATTACH)
|
|
{
|
|
(*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnDisconnect)(phTmp->hCard, SCARD_LEAVE_CARD);
|
|
(*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnRelease)(phTmp->hCtx);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, phTmp);
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
switch(GetExceptionCode())
|
|
{
|
|
case STATUS_INVALID_PARAM:
|
|
ret = MAKESCODE(SCW_E_INVALIDPARAM);
|
|
break;
|
|
|
|
default:
|
|
ret = SCARD_F_UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static LONG WINAPI hScwSetEndianness(SCARDHANDLE hCard, BOOL bEnd)
|
|
{
|
|
SCODE ret = SCARD_S_SUCCESS;
|
|
LPMYSCARDHANDLE phTmp = (LPMYSCARDHANDLE)hCard;
|
|
|
|
LOG_BEGIN_PROXY(hScwSetEndianness);
|
|
|
|
__try {
|
|
|
|
if (phTmp == NULL)
|
|
RaiseException(STATUS_INVALID_PARAM, 0, 0, 0);
|
|
|
|
if (bEnd)
|
|
phTmp->dwFlags |= FLAG_BIGENDIAN;
|
|
else
|
|
phTmp->dwFlags &= ~FLAG_BIGENDIAN;
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
switch(GetExceptionCode())
|
|
{
|
|
case STATUS_INVALID_PARAM:
|
|
ret = MAKESCODE(SCW_E_INVALIDPARAM);
|
|
break;
|
|
|
|
default:
|
|
ret = SCARD_F_UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// This is the right time to get proxy information
|
|
// Is proxy supported, what's the endianness and the buffer size
|
|
SCODE WINAPI hScwSetTransmitCallback(SCARDHANDLE hCard, LPFNSCWTRANSMITPROC lpfnProc)
|
|
{
|
|
SCODE ret = SCARD_S_SUCCESS;
|
|
LPMYSCARDHANDLE phTmp = (LPMYSCARDHANDLE)hCard;
|
|
|
|
__try {
|
|
|
|
if ((phTmp == NULL) || (lpfnProc == NULL))
|
|
RaiseException(STATUS_INVALID_PARAM, 0, 0, 0);
|
|
|
|
phTmp->lpfnTransmit = lpfnProc;
|
|
|
|
// Get the proxy info
|
|
{
|
|
ISO_HEADER xHdr;
|
|
BYTE rgData[] = {2, 108, 0, 116, 0, 0}; // 2 param, 0 as UINT8 by ref, 0 as UINT16 by ref
|
|
BYTE rgRes[1+1+2]; // RetCode + Endianness + TheBuffer size
|
|
TCOUNT OutLen = sizeof(rgRes);
|
|
UINT16 wSW;
|
|
|
|
xHdr.CLA = 0;
|
|
xHdr.INS = phTmp->byINS;
|
|
xHdr.P1 = 0xFF; // Get proxy config
|
|
xHdr.P2 = 0x00;
|
|
ret = hScwExecute(hCard, &xHdr, rgData, sizeof(rgData), rgRes, &OutLen, &wSW);
|
|
if (SCARD_S_SUCCESS == ret)
|
|
{ // Status OK & expected length & RC=SCW_S_OK
|
|
if ((wSW == 0x9000) && (OutLen == sizeof(rgRes)) && (rgRes[0] == 0)) // Version 1.0
|
|
{
|
|
hScwSetEndianness(hCard, rgRes[1]);
|
|
if (rgRes[1] == 0) // LITTLE_ENDIAN
|
|
phTmp->bResLen = rgRes[2] - 2; // SW!!!
|
|
else
|
|
phTmp->bResLen = rgRes[3] - 2; // SW!!!
|
|
|
|
phTmp->dwFlags |= FLAG_ISPROXY;
|
|
phTmp->dwFlags |= VERSION_1_0;
|
|
}
|
|
else if ((wSW == 0x9011) && (OutLen == sizeof(rgRes) - 1)) // Version 1.1
|
|
{
|
|
hScwSetEndianness(hCard, rgRes[0]);
|
|
if (rgRes[0] == 0) // LITTLE_ENDIAN
|
|
phTmp->bResLen = rgRes[1] - 2; // SW!!!
|
|
else
|
|
phTmp->bResLen = rgRes[2] - 2; // SW!!!
|
|
|
|
phTmp->dwFlags |= FLAG_ISPROXY;
|
|
phTmp->dwFlags |= VERSION_1_1;
|
|
}
|
|
// else there will be no proxy support but you can still use the Dll
|
|
}
|
|
else // There will be no proxy support though but you can still use the Dll
|
|
ret = SCARD_S_SUCCESS;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
switch(GetExceptionCode())
|
|
{
|
|
case STATUS_INVALID_PARAM:
|
|
ret = MAKESCODE(SCW_E_INVALIDPARAM);
|
|
break;
|
|
|
|
default:
|
|
ret = SCARD_F_UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
LONG WINAPI SCWTransmit(SCARDHANDLE hCard, LPCBYTE lpbIn, DWORD dwIn, LPBYTE lpBOut, LPDWORD pdwOut)
|
|
{
|
|
SCODE ret = SCARD_S_SUCCESS;
|
|
LPMYSCARDHANDLE phTmp = (LPMYSCARDHANDLE)hCard;
|
|
|
|
__try {
|
|
|
|
if (phTmp == NULL)
|
|
RaiseException(STATUS_INVALID_PARAM, 0, 0, 0);
|
|
|
|
DebugPrintBytes(L"bytes transmitted", (PBYTE) lpbIn, dwIn);
|
|
|
|
ret = (*phTmp->lpfnTransmit)(hCard, lpbIn, dwIn, lpBOut, pdwOut);
|
|
|
|
if (NULL != pdwOut)
|
|
DebugPrintBytes(L"bytes received", lpBOut, *pdwOut);
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
switch(GetExceptionCode())
|
|
{
|
|
case STATUS_INVALID_PARAM:
|
|
ret = MAKESCODE(SCW_E_INVALIDPARAM);
|
|
break;
|
|
|
|
default:
|
|
ret = SCARD_F_UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
const SCARD_IO_REQUEST
|
|
g_xIORT0 = { SCARD_PROTOCOL_T0, sizeof(SCARD_IO_REQUEST) },
|
|
g_xIORT1 = { SCARD_PROTOCOL_T1, sizeof(SCARD_IO_REQUEST) };
|
|
|
|
static LONG WINAPI _MySCWTransmit(SCARDHANDLE hCard, LPCBYTE lpbIn, DWORD dwIn, LPBYTE lpBOut, LPDWORD pdwOut)
|
|
{
|
|
SCARD_IO_REQUEST xIOR;
|
|
LONG ret = SCARD_S_SUCCESS;
|
|
LPMYSCARDHANDLE phTmp = (LPMYSCARDHANDLE)hCard;
|
|
|
|
__try {
|
|
|
|
if (phTmp == NULL)
|
|
RaiseException(STATUS_INVALID_PARAM, 0, 0, 0);
|
|
|
|
if (phTmp->dwProtocol == SCARD_PROTOCOL_T1)
|
|
{
|
|
memcpy(&xIOR, &g_xIORT1, sizeof(xIOR));
|
|
ret = (*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnSCardTransmit)(phTmp->hCard,
|
|
&xIOR, lpbIn, dwIn,
|
|
&xIOR, lpBOut, pdwOut);
|
|
}
|
|
else
|
|
{
|
|
DWORD dwOut = *pdwOut;
|
|
|
|
memcpy(&xIOR, &g_xIORT0, sizeof(xIOR));
|
|
|
|
__try {
|
|
|
|
ret = (*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnSCardBeginTransaction)(phTmp->hCard);
|
|
|
|
if (ret == SCARD_S_SUCCESS)
|
|
{
|
|
ret = (*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnSCardTransmit)(phTmp->hCard,
|
|
&xIOR, lpbIn, dwIn,
|
|
&xIOR, lpBOut, &dwOut);
|
|
}
|
|
|
|
if (ret == SCARD_S_SUCCESS)
|
|
{
|
|
if ((dwOut == 2) && ((lpBOut[0] == 0x61) || (lpBOut[0] == 0x9F)))
|
|
{
|
|
BYTE abGR[] = {0x00, 0xC0, 0x00, 0x00, 0x00};
|
|
|
|
abGR[4] = lpBOut[1];
|
|
ret = (*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnSCardTransmit)(phTmp->hCard,
|
|
&xIOR, abGR, 5,
|
|
&xIOR, lpBOut, pdwOut);
|
|
}
|
|
else
|
|
*pdwOut = dwOut;
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
(*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnSCardEndTransaction)(phTmp->hCard, SCARD_LEAVE_CARD);
|
|
}
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
switch(GetExceptionCode())
|
|
{
|
|
case STATUS_INVALID_PARAM:
|
|
ret = MAKESCODE(SCW_E_INVALIDPARAM);
|
|
break;
|
|
|
|
default:
|
|
ret = SCARD_F_UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static TCHAR lpstrGroupNames[] = _TEXT("SCard$DefaultReaders\0");
|
|
|
|
static LONG _GetCardHandle(LPCWSTR mszCardNames, LPMYSCARDHANDLE phCard)
|
|
{
|
|
LONG lRes;
|
|
OPENCARDNAME xOCN;
|
|
TCHAR wszReader[MAX_NAME];
|
|
TCHAR wszCard[MAX_NAME];
|
|
TCHAR wszCN[MAX_NAME];
|
|
|
|
DWORD len;
|
|
LPCWSTR lpwstr = mszCardNames;
|
|
LPTSTR lpstrCardNames = wszCN;
|
|
xOCN.nMaxCardNames = 0;
|
|
|
|
#if (!defined(UNICODE) && !defined(_UNICODE))
|
|
while (*lpwstr)
|
|
{
|
|
wsprintf(lpstrCardNames, "%S", lpwstr); // Conversion
|
|
len = wcslen(lpwstr) + 1; // Add the trailing 0
|
|
xOCN.nMaxCardNames += len;
|
|
lpwstr += len;
|
|
lpstrCardNames += len;
|
|
}
|
|
#else
|
|
while (*lpwstr)
|
|
{
|
|
wcscpy(lpstrCardNames, lpwstr);
|
|
len = wcslen(lpwstr) + 1; // Add the trailing 0
|
|
xOCN.nMaxCardNames += len;
|
|
lpwstr += len;
|
|
lpstrCardNames += len;
|
|
}
|
|
#endif
|
|
xOCN.nMaxCardNames++; // Add the trailing 0
|
|
*lpstrCardNames = 0;
|
|
|
|
lRes = (*axCtx[phCard->dwFlags & FLAG_MASKPCSC].lpfnEstablish)(SCARD_SCOPE_USER, NULL, NULL, &phCard->hCtx);
|
|
|
|
if (lRes == SCARD_S_SUCCESS)
|
|
{
|
|
xOCN.dwStructSize = sizeof(xOCN);
|
|
xOCN.hwndOwner = NULL; // probably called from console anyway
|
|
xOCN.hSCardContext = phCard->hCtx;
|
|
xOCN.lpstrGroupNames = lpstrGroupNames;
|
|
xOCN.nMaxGroupNames = sizeof(lpstrGroupNames)/sizeof(TCHAR);
|
|
xOCN.lpstrCardNames = wszCN;
|
|
xOCN.rgguidInterfaces = NULL;
|
|
xOCN.cguidInterfaces = 0;
|
|
xOCN.lpstrRdr = wszReader;
|
|
xOCN.nMaxRdr = MAX_NAME/sizeof(TCHAR);
|
|
xOCN.lpstrCard = wszCard;
|
|
xOCN.nMaxCard = MAX_NAME/sizeof(TCHAR);
|
|
xOCN.lpstrTitle = _TEXT("Insert Card:");
|
|
xOCN.dwFlags = SC_DLG_MINIMAL_UI;
|
|
xOCN.pvUserData = NULL;
|
|
xOCN.dwShareMode = SCARD_SHARE_SHARED;
|
|
xOCN.dwPreferredProtocols = SCARD_PROTOCOL_T1 | SCARD_PROTOCOL_T0;
|
|
xOCN.lpfnConnect = NULL;
|
|
xOCN.lpfnCheck = NULL;
|
|
xOCN.lpfnDisconnect = NULL;
|
|
|
|
lRes = (*axCtx[phCard->dwFlags & FLAG_MASKPCSC].lpfnOpenCard)(&xOCN);
|
|
}
|
|
|
|
if (lRes == SCARD_S_SUCCESS)
|
|
{
|
|
phCard->hCard = xOCN.hCardHandle;
|
|
}
|
|
|
|
return lRes;
|
|
}
|
|
|
|
SCODE WINAPI hScwSCardBeginTransaction(SCARDHANDLE hCard)
|
|
{
|
|
SCODE ret;
|
|
LPMYSCARDHANDLE phTmp = (LPMYSCARDHANDLE)hCard;
|
|
|
|
if ((phTmp->dwFlags & FLAG_REALPCSC) == FLAG_REALPCSC)
|
|
ret = (*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnSCardBeginTransaction)(phTmp->hCard);
|
|
else
|
|
ret = SCARD_S_SUCCESS; // No transactions on simulator
|
|
|
|
return ret;
|
|
}
|
|
|
|
SCODE WINAPI hScwSCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
|
|
{
|
|
SCODE ret;
|
|
LPMYSCARDHANDLE phTmp = (LPMYSCARDHANDLE)hCard;
|
|
|
|
if ((phTmp->dwFlags & FLAG_REALPCSC) == FLAG_REALPCSC)
|
|
ret = (*axCtx[phTmp->dwFlags & FLAG_MASKPCSC].lpfnSCardEndTransaction)(phTmp->hCard, dwDisposition);
|
|
else
|
|
ret = SCARD_S_SUCCESS; // No transactions on simulator
|
|
|
|
return ret;
|
|
}
|