mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
libwinpr-smartcard: improve GetStatusChange
This commit is contained in:
@@ -585,6 +585,14 @@ typedef struct
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const SCARD_IO_REQUEST g_rgSCardT0Pci;
|
||||
extern const SCARD_IO_REQUEST g_rgSCardT1Pci;
|
||||
extern const SCARD_IO_REQUEST g_rgSCardRawPci;
|
||||
|
||||
#define SCARD_PCI_T0 (&g_rgSCardT0Pci)
|
||||
#define SCARD_PCI_T1 (&g_rgSCardT1Pci)
|
||||
#define SCARD_PCI_RAW (&g_rgSCardRawPci)
|
||||
|
||||
WINSCARDAPI LONG WINAPI SCardEstablishContext(DWORD dwScope,
|
||||
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ static PSCardApiFunctionTable g_SCardApi = NULL;
|
||||
* Standard Windows Smart Card API
|
||||
*/
|
||||
|
||||
const SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
|
||||
const SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
|
||||
const SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
|
||||
|
||||
WINSCARDAPI LONG WINAPI SCardEstablishContext(DWORD dwScope,
|
||||
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
|
||||
{
|
||||
|
||||
@@ -1052,16 +1052,10 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext
|
||||
if (g_PCSC.pfnSCardGetStatusChange)
|
||||
{
|
||||
DWORD index;
|
||||
DWORD dwEventState;
|
||||
BOOL stateChanged = FALSE;
|
||||
LPSCARD_READERSTATEA states;
|
||||
|
||||
/**
|
||||
* pcsc-lite interprets value 0 as INFINITE, while it really shouldn't.
|
||||
* Work around this issue by using the smallest non-zero timeout value.
|
||||
*/
|
||||
|
||||
if (!dwTimeout)
|
||||
dwTimeout++;
|
||||
|
||||
states = (LPSCARD_READERSTATEA) calloc(cReaders, sizeof(SCARD_READERSTATEA));
|
||||
|
||||
if (!states)
|
||||
@@ -1081,30 +1075,49 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext
|
||||
CopyMemory(&(states[index].rgbAtr), &(rgReaderStates[index].rgbAtr), 36);
|
||||
}
|
||||
|
||||
status = g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout, states, cReaders);
|
||||
/**
|
||||
* pcsc-lite interprets dwTimeout value 0 as INFINITE, use value 1 as a workaround
|
||||
*/
|
||||
|
||||
status = g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout ? dwTimeout : 1, states, cReaders);
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
|
||||
for (index = 0; index < cReaders; index++)
|
||||
{
|
||||
rgReaderStates[index].pvUserData = states[index].pvUserData;
|
||||
rgReaderStates[index].dwCurrentState = states[index].dwCurrentState;
|
||||
rgReaderStates[index].dwEventState = states[index].dwEventState;
|
||||
rgReaderStates[index].cbAtr = states[index].cbAtr;
|
||||
CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36);
|
||||
|
||||
/* pcsc-lite puts an event count in the higher bits of dwEventState */
|
||||
rgReaderStates[index].dwEventState &= 0xFFFF;
|
||||
states[index].dwEventState &= 0xFFFF;
|
||||
|
||||
dwEventState = states[index].dwEventState & ~SCARD_STATE_CHANGED;
|
||||
|
||||
if (dwEventState != rgReaderStates[index].dwCurrentState)
|
||||
{
|
||||
rgReaderStates[index].dwEventState = states[index].dwEventState;
|
||||
stateChanged = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
rgReaderStates[index].dwEventState = dwEventState;
|
||||
}
|
||||
|
||||
if (rgReaderStates[index].dwEventState & SCARD_STATE_PRESENT)
|
||||
{
|
||||
rgReaderStates[index].dwEventState |= SCARD_STATE_INUSE;
|
||||
rgReaderStates[index].dwEventState |= 0x00010000; /* unknown value observed with WinSCard */
|
||||
}
|
||||
|
||||
if (rgReaderStates[index].dwCurrentState & SCARD_STATE_IGNORE)
|
||||
rgReaderStates[index].dwEventState = SCARD_STATE_IGNORE;
|
||||
}
|
||||
|
||||
if ((status == SCARD_S_SUCCESS) && !stateChanged)
|
||||
status = SCARD_E_TIMEOUT;
|
||||
else if ((status == SCARD_E_TIMEOUT) && stateChanged)
|
||||
return SCARD_S_SUCCESS;
|
||||
|
||||
free(states);
|
||||
}
|
||||
|
||||
@@ -1521,6 +1534,31 @@ WINSCARDAPI LONG WINAPI PCSC_SCardTransmit(SCARDHANDLE hCard,
|
||||
|
||||
if (g_PCSC.pfnSCardTransmit)
|
||||
{
|
||||
if (!pioSendPci)
|
||||
{
|
||||
DWORD dwState = 0;
|
||||
DWORD cbAtrLen = 0;
|
||||
DWORD dwProtocol = 0;
|
||||
DWORD cchReaderLen = 0;
|
||||
|
||||
/**
|
||||
* pcsc-lite cannot have a null pioSendPci parameter, unlike WinSCard.
|
||||
* Query the current protocol and use default SCARD_IO_REQUEST for it.
|
||||
*/
|
||||
|
||||
status = SCardStatusA(hCard, NULL, &cchReaderLen, &dwState, &dwProtocol, NULL, &cbAtrLen);
|
||||
|
||||
if (status == SCARD_S_SUCCESS)
|
||||
{
|
||||
if (dwProtocol == SCARD_PROTOCOL_T0)
|
||||
pioSendPci = SCARD_PCI_T0;
|
||||
else if (dwProtocol == SCARD_PROTOCOL_T1)
|
||||
pioSendPci = SCARD_PCI_T1;
|
||||
else if (dwProtocol == SCARD_PROTOCOL_RAW)
|
||||
pioSendPci = SCARD_PCI_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
status = g_PCSC.pfnSCardTransmit(hCard, pioSendPci, pbSendBuffer,
|
||||
cbSendLength, pioRecvPci, pbRecvBuffer, pcbRecvLength);
|
||||
status = PCSC_MapErrorCodeToWinSCard(status);
|
||||
|
||||
Reference in New Issue
Block a user