channels/smartcard: improve SCardGetAttrib

This commit is contained in:
Marc-André Moreau 2014-04-08 23:52:24 -04:00
parent 46686d391f
commit b91c10392f
4 changed files with 268 additions and 51 deletions

View File

@ -932,39 +932,18 @@ static UINT32 smartcard_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp)
hContext = (ULONG_PTR) call.hCard.Context.pbContext; hContext = (ULONG_PTR) call.hCard.Context.pbContext;
ret.pbAttr = NULL; ret.pbAttr = NULL;
cbAttrLen = (!call.cbAttrLen || call.fpbAttrIsNULL) ? 0 : SCARD_AUTOALLOCATE;
status = ret.ReturnCode = SCardGetAttrib(hCard, call.dwAttrId, if (call.fpbAttrIsNULL)
(cbAttrLen == 0) ? NULL : (BYTE*) &ret.pbAttr, &cbAttrLen); call.cbAttrLen = 0;
if (status) if (call.cbAttrLen)
cbAttrLen = (call.cbAttrLen == 0) ? 0 : SCARD_AUTOALLOCATE; ret.pbAttr = malloc(call.cbAttrLen);
if ((call.dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) && (status == SCARD_E_UNSUPPORTED_FEATURE)) cbAttrLen = call.cbAttrLen;
{
status = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W,
(cbAttrLen == 0) ? NULL : (BYTE*) &ret.pbAttr, &cbAttrLen);
if (status) status = ret.ReturnCode = SCardGetAttrib(hCard, call.dwAttrId, ret.pbAttr, &cbAttrLen);
cbAttrLen = (call.cbAttrLen == 0) ? 0 : SCARD_AUTOALLOCATE;
}
if ((call.dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W) && (status == SCARD_E_UNSUPPORTED_FEATURE)) ret.cbAttrLen = cbAttrLen;
{
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;
if (ret.ReturnCode) if (ret.ReturnCode)
{ {
@ -977,7 +956,7 @@ static UINT32 smartcard_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp)
if (status) if (status)
return status; return status;
SCardFreeMemory(hContext, ret.pbAttr); free(ret.pbAttr);
return ret.ReturnCode; return ret.ReturnCode;
} }

View File

@ -1104,6 +1104,7 @@ extern "C" {
#endif #endif
WINSCARDAPI const char* WINAPI SCardGetErrorString(LONG errorCode); WINSCARDAPI const char* WINAPI SCardGetErrorString(LONG errorCode);
WINSCARDAPI const char* WINAPI SCardGetAttributeString(DWORD dwAttrId);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -640,6 +640,147 @@ WINSCARDAPI const char* WINAPI SCardGetErrorString(LONG errorCode)
return "SCARD_E_UNKNOWN"; 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) void InitializeSCardApiStubs(void)
{ {
g_Initialized = TRUE; g_Initialized = TRUE;

View File

@ -38,6 +38,8 @@ static BOOL g_SCardAutoAllocate = FALSE;
static wListDictionary* g_SmartCards = NULL; static wListDictionary* g_SmartCards = NULL;
static wListDictionary* g_MemoryBlocks = NULL; static wListDictionary* g_MemoryBlocks = NULL;
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem);
LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode) 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); ConvertToUnicode(CP_UTF8, 0, mszReadersA, length + 2, (WCHAR**) mszReaders, 0);
PCSC_AddMemoryBlock(hContext, mszReaders); PCSC_AddMemoryBlock(hContext, mszReaders);
if (g_PCSC.pfnSCardFreeMemory) PCSC_SCardFreeMemory(hContext, mszReadersA);
{
g_PCSC.pfnSCardFreeMemory(hContext, mszReadersA);
}
} }
} }
@ -484,14 +483,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMe
{ {
LONG status = SCARD_S_SUCCESS; LONG status = SCARD_S_SUCCESS;
if (g_PCSC.pfnSCardFreeMemory)
{
if (PCSC_RemoveMemoryBlock(hContext, (void*) pvMem)) if (PCSC_RemoveMemoryBlock(hContext, (void*) pvMem))
{ {
free((void*) pvMem); free((void*) pvMem);
status = SCARD_S_SUCCESS; status = SCARD_S_SUCCESS;
} }
else else
{
if (g_PCSC.pfnSCardFreeMemory)
{ {
status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem); status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
status = PCSC_MapErrorCodeToWinSCard(status); status = PCSC_MapErrorCodeToWinSCard(status);
@ -734,13 +733,9 @@ WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
status = PCSC_MapErrorCodeToWinSCard(status); status = PCSC_MapErrorCodeToWinSCard(status);
if (mszReaderNames) if (mszReaderNames)
{
if (g_PCSC.pfnSCardFreeMemory)
{ {
hContext = PCSC_GetSmartCardContextFromHandle(hCard); hContext = PCSC_GetSmartCardContextFromHandle(hCard);
PCSC_SCardFreeMemory(hContext, mszReaderNames);
g_PCSC.pfnSCardFreeMemory(hContext, mszReaderNames);
}
} }
} }
@ -926,10 +921,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard,
PCSC_AddMemoryBlock(hContext, mszReaderNames); PCSC_AddMemoryBlock(hContext, mszReaderNames);
if (g_PCSC.pfnSCardFreeMemory) PCSC_SCardFreeMemory(hContext, mszReaderNamesA);
{
g_PCSC.pfnSCardFreeMemory(hContext, mszReaderNamesA);
}
} }
} }
@ -974,7 +966,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
return status; 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; LONG status = SCARD_S_SUCCESS;
@ -1024,6 +1016,110 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, L
return status; 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) WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
{ {
LONG status = SCARD_S_SUCCESS; LONG status = SCARD_S_SUCCESS;