From da56c8af62fd84075e9da345b9bf381ca1f5b55f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 9 Apr 2014 14:27:44 -0400 Subject: [PATCH] channels/smartcard: pcsc-lite fixes --- .../smartcard/client/smartcard_operations.c | 10 ++-- channels/smartcard/client/smartcard_pack.c | 5 +- winpr/libwinpr/smartcard/smartcard_pcsc.c | 47 ++++++++++++++++--- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index 46d01d639..b5ec6f95e 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -155,7 +155,7 @@ size_t smartcard_multi_string_length_a(const char* msz) while ((p[0] != 0) && (p[1] != 0)) p++; - return (p - msz); + return (p - msz) + 1; } size_t smartcard_multi_string_length_w(const WCHAR* msz) @@ -168,7 +168,7 @@ size_t smartcard_multi_string_length_w(const WCHAR* msz) while ((p[0] != 0) && (p[1] != 0)) p++; - return (p - msz); + return (p - msz) + 1; } static UINT32 smartcard_EstablishContext(SMARTCARD_DEVICE* smartcard, IRP* irp) @@ -262,7 +262,7 @@ static UINT32 smartcard_ListReadersA(SMARTCARD_DEVICE* smartcard, IRP* irp) return status; ret.msz = (BYTE*) mszReaders; - ret.cBytes = smartcard_multi_string_length_a((char*) ret.msz) + 2; + ret.cBytes = cchReaders; status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret); @@ -302,7 +302,7 @@ static UINT32 smartcard_ListReadersW(SMARTCARD_DEVICE* smartcard, IRP* irp) return status; ret.msz = (BYTE*) mszReaders; - ret.cBytes = (smartcard_multi_string_length_w((WCHAR*) ret.msz) + 2) * 2; + ret.cBytes = cchReaders; status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret); @@ -1032,7 +1032,7 @@ void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp) WLog_Print(smartcard->log, WLOG_DEBUG, "%s (0x%08X) FileId: %d CompletionId: %d", smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId); -#if 0 +#if 1 printf("%s (0x%08X) FileId: %d CompletionId: %d\n", smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId); #endif diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index ed1c2774f..4de589846 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -523,7 +523,7 @@ UINT32 smartcard_pack_list_readers_return(SMARTCARD_DEVICE* smartcard, wStream* Stream_Write(s, ret->msz, ret->cBytes); else Stream_Zero(s, ret->cBytes); - + smartcard_pack_write_size_align(smartcard, s, ret->cBytes, 4); return SCARD_S_SUCCESS; @@ -776,8 +776,7 @@ UINT32 smartcard_unpack_get_status_change_a_call(SMARTCARD_DEVICE* smartcard, wS Stream_Read(s, readerState->Common.rgbAtr, 32); /* rgbAtr [0..32] (32 bytes) */ Stream_Seek_UINT32(s); /* rgbAtr [32..36] (4 bytes) */ - /* what is this used for? */ - readerState->Common.dwCurrentState &= 0x0000FFFF; + readerState->Common.dwCurrentState &= 0xFFFF; readerState->Common.dwEventState = 0; } diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index e42dc1875..91823fded 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -67,7 +67,7 @@ size_t PCSC_MultiStringLengthA(const char* msz) while ((p[0] != 0) && (p[1] != 0)) p++; - return (p - msz); + return (p - msz) + 1; } size_t PCSC_MultiStringLengthW(const WCHAR* msz) @@ -80,7 +80,7 @@ size_t PCSC_MultiStringLengthW(const WCHAR* msz) while ((p[0] != 0) && (p[1] != 0)) p++; - return (p - msz); + return (p - msz) + 1; } void PCSC_AddSmartCardHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard) @@ -152,6 +152,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope, if (g_PCSC.pfnSCardEstablishContext) { + dwScope = SCARD_SCOPE_SYSTEM; /* this is the only scope supported by pcsc-lite */ + status = g_PCSC.pfnSCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext); status = PCSC_MapErrorCodeToWinSCard(status); } @@ -228,6 +230,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext, BOOL pcchReadersWrapAlloc = FALSE; LPSTR* pMszReaders = (LPSTR*) mszReaders; + mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */ + if ((*pcchReaders == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) pcchReadersWrapAlloc = TRUE; @@ -270,12 +274,13 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, if (g_PCSC.pfnSCardListReaders) { - UINT32 length; LPSTR mszGroupsA = NULL; LPSTR mszReadersA = NULL; BOOL pcchReadersWrapAlloc = FALSE; LPSTR* pMszReadersA = &mszReadersA; + mszGroups = NULL; /* mszGroups is not supported by pcsc-lite */ + if ((*pcchReaders == SCARD_AUTOALLOCATE) && !g_SCardAutoAllocate) pcchReadersWrapAlloc = TRUE; @@ -299,8 +304,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, if (status && *pMszReadersA) { - length = (UINT32) PCSC_MultiStringLengthA(*pMszReadersA); - ConvertToUnicode(CP_UTF8, 0, *pMszReadersA, length + 2, (WCHAR**) mszReaders, 0); + *pcchReaders = ConvertToUnicode(CP_UTF8, 0, *pMszReadersA, *pcchReaders, (WCHAR**) mszReaders, 0); PCSC_AddMemoryBlock(hContext, mszReaders); } @@ -313,8 +317,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, if (mszReadersA) { - length = (UINT32) PCSC_MultiStringLengthA(mszReadersA); - ConvertToUnicode(CP_UTF8, 0, mszReadersA, length + 2, (WCHAR**) mszReaders, 0); + *pcchReaders = ConvertToUnicode(CP_UTF8, 0, mszReadersA, *pcchReaders, (WCHAR**) mszReaders, 0) * 2; PCSC_AddMemoryBlock(hContext, mszReaders); PCSC_SCardFreeMemory(hContext, mszReadersA); @@ -541,8 +544,30 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext, if (g_PCSC.pfnSCardGetStatusChange) { + DWORD index; + + /** + * 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++; + + for (index = 0; index < cReaders; index++) + { + rgReaderStates[index].dwCurrentState &= 0xFFFF; + rgReaderStates[index].dwEventState = 0; + } + status = g_PCSC.pfnSCardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders); status = PCSC_MapErrorCodeToWinSCard(status); + + for (index = 0; index < cReaders; index++) + { + /* pcsc-lite puts an event count in the higher bits of dwEventState */ + rgReaderStates[index].dwEventState &= 0xFFFF; + } } return status; @@ -558,6 +583,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext, DWORD index; LPSCARD_READERSTATEA rgReaderStatesA; + if (!dwTimeout) + dwTimeout++; + rgReaderStatesA = (LPSCARD_READERSTATEA) calloc(cReaders, sizeof(SCARD_READERSTATEA)); for (index = 0; index < cReaders; index++) @@ -567,6 +595,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext, ConvertFromUnicode(CP_UTF8, 0, rgReaderStates[index].szReader, -1, (char**) &rgReaderStatesA[index].szReader, 0, NULL, NULL); + rgReaderStates[index].dwCurrentState &= 0xFFFF; + rgReaderStates[index].dwEventState = 0; + rgReaderStatesA[index].pvUserData = rgReaderStates[index].pvUserData; rgReaderStatesA[index].dwCurrentState = rgReaderStates[index].dwCurrentState; rgReaderStatesA[index].dwEventState = rgReaderStates[index].dwEventState; @@ -586,6 +617,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext, rgReaderStates[index].dwEventState = rgReaderStatesA[index].dwEventState; rgReaderStates[index].cbAtr = rgReaderStatesA[index].cbAtr; CopyMemory(&(rgReaderStates[index].rgbAtr), &(rgReaderStatesA[index].rgbAtr), 36); + + rgReaderStates[index].dwEventState &= 0xFFFF; } free(rgReaderStatesA);