From b91c10392f3842046bcfe2fdf9b1ee0ab36b900c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 8 Apr 2014 23:52:24 -0400 Subject: [PATCH] channels/smartcard: improve SCardGetAttrib --- .../smartcard/client/smartcard_operations.c | 37 +---- winpr/include/winpr/smartcard.h | 1 + winpr/libwinpr/smartcard/smartcard.c | 141 ++++++++++++++++++ winpr/libwinpr/smartcard/smartcard_pcsc.c | 140 ++++++++++++++--- 4 files changed, 268 insertions(+), 51 deletions(-) diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index c29acd3ed..e9261e50e 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -932,39 +932,18 @@ static UINT32 smartcard_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp) hContext = (ULONG_PTR) call.hCard.Context.pbContext; ret.pbAttr = NULL; - cbAttrLen = (!call.cbAttrLen || call.fpbAttrIsNULL) ? 0 : SCARD_AUTOALLOCATE; - status = ret.ReturnCode = SCardGetAttrib(hCard, call.dwAttrId, - (cbAttrLen == 0) ? NULL : (BYTE*) &ret.pbAttr, &cbAttrLen); + if (call.fpbAttrIsNULL) + call.cbAttrLen = 0; - if (status) - cbAttrLen = (call.cbAttrLen == 0) ? 0 : SCARD_AUTOALLOCATE; + if (call.cbAttrLen) + ret.pbAttr = malloc(call.cbAttrLen); - if ((call.dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) && (status == SCARD_E_UNSUPPORTED_FEATURE)) - { - status = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, - (cbAttrLen == 0) ? NULL : (BYTE*) &ret.pbAttr, &cbAttrLen); + cbAttrLen = call.cbAttrLen; - if (status) - cbAttrLen = (call.cbAttrLen == 0) ? 0 : SCARD_AUTOALLOCATE; - } + status = ret.ReturnCode = SCardGetAttrib(hCard, call.dwAttrId, ret.pbAttr, &cbAttrLen); - if ((call.dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W) && (status == SCARD_E_UNSUPPORTED_FEATURE)) - { - status = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, - (cbAttrLen == 0) ? NULL : (BYTE*) &ret.pbAttr, &cbAttrLen); - - if (status) - cbAttrLen = (call.cbAttrLen == 0) ? 0 : SCARD_AUTOALLOCATE; - } - - if ((cbAttrLen > call.cbAttrLen) && (ret.pbAttr)) - status = SCARD_E_INSUFFICIENT_BUFFER; - - ret.ReturnCode = status; - - call.cbAttrLen = cbAttrLen; - ret.cbAttrLen = call.cbAttrLen; + ret.cbAttrLen = cbAttrLen; if (ret.ReturnCode) { @@ -977,7 +956,7 @@ static UINT32 smartcard_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp) if (status) return status; - SCardFreeMemory(hContext, ret.pbAttr); + free(ret.pbAttr); return ret.ReturnCode; } diff --git a/winpr/include/winpr/smartcard.h b/winpr/include/winpr/smartcard.h index ef9dc2af6..f9dae7539 100644 --- a/winpr/include/winpr/smartcard.h +++ b/winpr/include/winpr/smartcard.h @@ -1104,6 +1104,7 @@ extern "C" { #endif WINSCARDAPI const char* WINAPI SCardGetErrorString(LONG errorCode); +WINSCARDAPI const char* WINAPI SCardGetAttributeString(DWORD dwAttrId); #ifdef __cplusplus } diff --git a/winpr/libwinpr/smartcard/smartcard.c b/winpr/libwinpr/smartcard/smartcard.c index 69cfcc6c7..3ecd931bf 100644 --- a/winpr/libwinpr/smartcard/smartcard.c +++ b/winpr/libwinpr/smartcard/smartcard.c @@ -640,6 +640,147 @@ WINSCARDAPI const char* WINAPI SCardGetErrorString(LONG errorCode) return "SCARD_E_UNKNOWN"; } +WINSCARDAPI const char* WINAPI SCardGetAttributeString(DWORD dwAttrId) +{ + switch (dwAttrId) + { + case SCARD_ATTR_VENDOR_NAME: + return "SCARD_ATTR_VENDOR_NAME"; + break; + case SCARD_ATTR_VENDOR_IFD_TYPE: + return "SCARD_ATTR_VENDOR_IFD_TYPE"; + break; + case SCARD_ATTR_VENDOR_IFD_VERSION: + return "SCARD_ATTR_VENDOR_IFD_VERSION"; + break; + case SCARD_ATTR_VENDOR_IFD_SERIAL_NO: + return "SCARD_ATTR_VENDOR_IFD_SERIAL_NO"; + break; + case SCARD_ATTR_CHANNEL_ID: + return "SCARD_ATTR_CHANNEL_ID"; + break; + case SCARD_ATTR_PROTOCOL_TYPES: + return "SCARD_ATTR_PROTOCOL_TYPES"; + break; + case SCARD_ATTR_DEFAULT_CLK: + return "SCARD_ATTR_DEFAULT_CLK"; + break; + case SCARD_ATTR_MAX_CLK: + return "SCARD_ATTR_MAX_CLK"; + break; + case SCARD_ATTR_DEFAULT_DATA_RATE: + return "SCARD_ATTR_DEFAULT_DATA_RATE"; + break; + case SCARD_ATTR_MAX_DATA_RATE: + return "SCARD_ATTR_MAX_DATA_RATE"; + break; + case SCARD_ATTR_MAX_IFSD: + return "SCARD_ATTR_MAX_IFSD"; + break; + case SCARD_ATTR_POWER_MGMT_SUPPORT: + return "SCARD_ATTR_POWER_MGMT_SUPPORT"; + break; + case SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE: + return "SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE"; + break; + case SCARD_ATTR_USER_AUTH_INPUT_DEVICE: + return "SCARD_ATTR_USER_AUTH_INPUT_DEVICE"; + break; + case SCARD_ATTR_CHARACTERISTICS: + return "SCARD_ATTR_CHARACTERISTICS"; + break; + case SCARD_ATTR_CURRENT_PROTOCOL_TYPE: + return "SCARD_ATTR_CURRENT_PROTOCOL_TYPE"; + break; + case SCARD_ATTR_CURRENT_CLK: + return "SCARD_ATTR_CURRENT_CLK"; + break; + case SCARD_ATTR_CURRENT_F: + return "SCARD_ATTR_CURRENT_F"; + break; + case SCARD_ATTR_CURRENT_D: + return "SCARD_ATTR_CURRENT_D"; + break; + case SCARD_ATTR_CURRENT_N: + return "SCARD_ATTR_CURRENT_N"; + break; + case SCARD_ATTR_CURRENT_W: + return "SCARD_ATTR_CURRENT_W"; + break; + case SCARD_ATTR_CURRENT_IFSC: + return "SCARD_ATTR_CURRENT_IFSC"; + break; + case SCARD_ATTR_CURRENT_IFSD: + return "SCARD_ATTR_CURRENT_IFSD"; + break; + case SCARD_ATTR_CURRENT_BWT: + return "SCARD_ATTR_CURRENT_BWT"; + break; + case SCARD_ATTR_CURRENT_CWT: + return "SCARD_ATTR_CURRENT_CWT"; + break; + case SCARD_ATTR_CURRENT_EBC_ENCODING: + return "SCARD_ATTR_CURRENT_EBC_ENCODING"; + break; + case SCARD_ATTR_EXTENDED_BWT: + return "SCARD_ATTR_EXTENDED_BWT"; + break; + case SCARD_ATTR_ICC_PRESENCE: + return "SCARD_ATTR_ICC_PRESENCE"; + break; + case SCARD_ATTR_ICC_INTERFACE_STATUS: + return "SCARD_ATTR_ICC_INTERFACE_STATUS"; + break; + case SCARD_ATTR_CURRENT_IO_STATE: + return "SCARD_ATTR_CURRENT_IO_STATE"; + break; + case SCARD_ATTR_ATR_STRING: + return "SCARD_ATTR_ATR_STRING"; + break; + case SCARD_ATTR_ICC_TYPE_PER_ATR: + return "SCARD_ATTR_ICC_TYPE_PER_ATR"; + break; + case SCARD_ATTR_ESC_RESET: + return "SCARD_ATTR_ESC_RESET"; + break; + case SCARD_ATTR_ESC_CANCEL: + return "SCARD_ATTR_ESC_CANCEL"; + break; + case SCARD_ATTR_ESC_AUTHREQUEST: + return "SCARD_ATTR_ESC_AUTHREQUEST"; + break; + case SCARD_ATTR_MAXINPUT: + return "SCARD_ATTR_MAXINPUT"; + break; + case SCARD_ATTR_DEVICE_UNIT: + return "SCARD_ATTR_DEVICE_UNIT"; + break; + case SCARD_ATTR_DEVICE_IN_USE: + return "SCARD_ATTR_DEVICE_IN_USE"; + break; + case SCARD_ATTR_DEVICE_FRIENDLY_NAME_A: + return "SCARD_ATTR_DEVICE_FRIENDLY_NAME_A"; + break; + case SCARD_ATTR_DEVICE_SYSTEM_NAME_A: + return "SCARD_ATTR_DEVICE_SYSTEM_NAME_A"; + break; + case SCARD_ATTR_DEVICE_FRIENDLY_NAME_W: + return "SCARD_ATTR_DEVICE_FRIENDLY_NAME_W"; + break; + case SCARD_ATTR_DEVICE_SYSTEM_NAME_W: + return "SCARD_ATTR_DEVICE_SYSTEM_NAME_W"; + break; + case SCARD_ATTR_SUPRESS_T1_IFS_REQUEST: + return "SCARD_ATTR_SUPRESS_T1_IFS_REQUEST"; + break; + default: + return "SCARD_ATTR_UNKNOWN"; + break; + } + + return "SCARD_ATTR_UNKNOWN"; +} + void InitializeSCardApiStubs(void) { g_Initialized = TRUE; diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index 37c3302e4..cc80a31e9 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -38,6 +38,8 @@ static BOOL g_SCardAutoAllocate = FALSE; static wListDictionary* g_SmartCards = NULL; static wListDictionary* g_MemoryBlocks = NULL; +WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem); + LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode) { /** @@ -315,10 +317,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, ConvertToUnicode(CP_UTF8, 0, mszReadersA, length + 2, (WCHAR**) mszReaders, 0); PCSC_AddMemoryBlock(hContext, mszReaders); - if (g_PCSC.pfnSCardFreeMemory) - { - g_PCSC.pfnSCardFreeMemory(hContext, mszReadersA); - } + PCSC_SCardFreeMemory(hContext, mszReadersA); } } @@ -484,14 +483,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMe { LONG status = SCARD_S_SUCCESS; - if (g_PCSC.pfnSCardFreeMemory) + if (PCSC_RemoveMemoryBlock(hContext, (void*) pvMem)) { - if (PCSC_RemoveMemoryBlock(hContext, (void*) pvMem)) - { - free((void*) pvMem); - status = SCARD_S_SUCCESS; - } - else + free((void*) pvMem); + status = SCARD_S_SUCCESS; + } + else + { + if (g_PCSC.pfnSCardFreeMemory) { status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem); status = PCSC_MapErrorCodeToWinSCard(status); @@ -735,12 +734,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, if (mszReaderNames) { - if (g_PCSC.pfnSCardFreeMemory) - { - hContext = PCSC_GetSmartCardContextFromHandle(hCard); - - g_PCSC.pfnSCardFreeMemory(hContext, mszReaderNames); - } + hContext = PCSC_GetSmartCardContextFromHandle(hCard); + PCSC_SCardFreeMemory(hContext, mszReaderNames); } } @@ -926,10 +921,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard, PCSC_AddMemoryBlock(hContext, mszReaderNames); - if (g_PCSC.pfnSCardFreeMemory) - { - g_PCSC.pfnSCardFreeMemory(hContext, mszReaderNamesA); - } + PCSC_SCardFreeMemory(hContext, mszReaderNamesA); } } @@ -974,7 +966,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard, return status; } -WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) +WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) { LONG status = SCARD_S_SUCCESS; @@ -1024,6 +1016,110 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L return status; } +WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen) +{ + LONG status = SCARD_S_SUCCESS; + + status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen); + + if (status == SCARD_E_UNSUPPORTED_FEATURE) + { + DWORD cbAttrLen; + SCARDCONTEXT hContext; + BOOL attrAutoAlloc = FALSE; + LPBYTE* pPbAttr = (LPBYTE*) pbAttr; + + cbAttrLen = *pcbAttrLen; + + if (*pcbAttrLen == SCARD_AUTOALLOCATE) + attrAutoAlloc = TRUE; + + hContext = PCSC_GetSmartCardContextFromHandle(hCard); + + if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) + { + WCHAR* pbAttrW = NULL; + + *pcbAttrLen = SCARD_AUTOALLOCATE; + + status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, + (LPBYTE) &pbAttrW, pcbAttrLen); + + if (status) + { + int length; + char* pbAttrA = NULL; + + length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) pbAttrW, + *pcbAttrLen, (char**) &pbAttrA, 0, NULL, NULL); + + PCSC_SCardFreeMemory(hContext, pbAttrW); + + if (attrAutoAlloc) + { + PCSC_AddMemoryBlock(hContext, pbAttrA); + *pPbAttr = (BYTE*) pbAttrA; + *pcbAttrLen = length; + } + else + { + if (length > cbAttrLen) + { + free(pbAttrA); + return SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + CopyMemory(pbAttr, (BYTE*) pbAttrA, length); + *pcbAttrLen = length; + } + } + } + } + else if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W) + { + char* pbAttrA = NULL; + + *pcbAttrLen = SCARD_AUTOALLOCATE; + + status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, + (LPBYTE) &pbAttrA, pcbAttrLen); + + if (status) + { + int length; + WCHAR* pbAttrW = NULL; + + length = ConvertToUnicode(CP_UTF8, 0, (char*) pbAttr, *pcbAttrLen, &pbAttrW, 0) * 2; + + PCSC_SCardFreeMemory(hContext, pbAttrA); + + if (attrAutoAlloc) + { + PCSC_AddMemoryBlock(hContext, pbAttrW); + *pPbAttr = (BYTE*) pbAttrW; + *pcbAttrLen = length; + } + else + { + if (length > cbAttrLen) + { + free(pbAttrW); + return SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + CopyMemory(pbAttr, (BYTE*) pbAttrW, length); + *pcbAttrLen = length; + } + } + } + } + } + + return status; +} + WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen) { LONG status = SCARD_S_SUCCESS;