channels/smartcard: experiment with multiple card contexts

This commit is contained in:
Marc-André Moreau 2014-06-02 17:20:01 -04:00
parent 1359d7c27e
commit f5bfb98aca
3 changed files with 84 additions and 36 deletions

View File

@ -553,14 +553,14 @@ static UINT32 smartcard_ConnectA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
status = ret.ReturnCode = SCardConnectA(operation->hContext, (char*) call->szReader, call->Common.dwShareMode,
call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol);
if (status)
return status;
smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext);
smartcard_scard_handle_native_to_redir(smartcard, &(ret.hCard), hCard);
smartcard_trace_connect_return(smartcard, &ret);
if (status)
return status;
status = smartcard_pack_connect_return(smartcard, irp->output, &ret);
if (status)
@ -605,14 +605,14 @@ static UINT32 smartcard_ConnectW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
status = ret.ReturnCode = SCardConnectW(operation->hContext, (WCHAR*) call->szReader, call->Common.dwShareMode,
call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol);
if (status)
return status;
smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext);
smartcard_scard_handle_native_to_redir(smartcard, &(ret.hCard), hCard);
smartcard_trace_connect_return(smartcard, &ret);
if (status)
return status;
status = smartcard_pack_connect_return(smartcard, irp->output, &ret);
if (status)

View File

@ -1890,6 +1890,12 @@ void smartcard_trace_get_attrib_return(SMARTCARD_DEVICE* smartcard, GetAttrib_Re
{
WLog_Print(smartcard->log, WLOG_DEBUG, "pbAttr: %.*s", ret->cbAttrLen, (char*) ret->pbAttr);
}
else if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
{
UINT32 dwProtocolType = *((UINT32*) ret->pbAttr);
WLog_Print(smartcard->log, WLOG_DEBUG, "dwProtocolType: %s (0x%04X)",
SCardGetProtocolString(dwProtocolType), dwProtocolType);
}
WLog_Print(smartcard->log, WLOG_DEBUG, "}");
}

View File

@ -103,16 +103,17 @@
struct _PCSC_SCARDCONTEXT
{
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
CRITICAL_SECTION lock;
SCARDCONTEXT hContext;
DWORD dwCardHandleCount;
};
typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
struct _PCSC_SCARDHANDLE
{
SCARDCONTEXT hContext;
CRITICAL_SECTION lock;
SCARDCONTEXT hSharedContext;
SCARDCONTEXT hPrivateContext;
};
typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
@ -147,6 +148,9 @@ const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(PC
const PCSC_SCARD_IO_REQUEST g_PCSC_rgSCardRawPci = { PCSC_SCARD_PROTOCOL_RAW, sizeof(PCSC_SCARD_IO_REQUEST) };
WINSCARDAPI LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPCVOID pvMem);
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope,
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext);
LONG PCSC_MapErrorCodeToWinSCard(LONG errorCode)
{
@ -313,10 +317,15 @@ void PCSC_ReleaseCardContext(SCARDCONTEXT hContext)
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
{
printf("PCSC_ReleaseCardContext: null pContext!\n");
return;
}
DeleteCriticalSection(&(pContext->lock));
printf("PCSC_ReleaseCardContext: %d\n", pContext->dwCardHandleCount);
free(pContext);
if (!g_CardContexts)
@ -383,38 +392,35 @@ SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
if (!pCard)
return 0;
return pCard->hContext;
return pCard->hPrivateContext;
}
BOOL PCSC_IsCardHandleConnected(SCARDCONTEXT hContext)
{
PCSC_SCARDCONTEXT* pContext;
pContext = PCSC_GetCardContextData(hContext);
if (!pContext)
return FALSE;
return pContext->hCard ? TRUE : FALSE;
}
PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard)
PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDCONTEXT hPrivateContext, SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
PCSC_SCARDCONTEXT* pContext;
pContext = PCSC_GetCardContextData(hSharedContext);
if (!pContext)
{
printf("PCSC_ConnectCardHandle: null pContext!\n");
return NULL;
}
pCard = (PCSC_SCARDHANDLE*) calloc(1, sizeof(PCSC_SCARDHANDLE));
if (!pCard)
return NULL;
pCard->hContext = hContext;
pCard->hSharedContext = hSharedContext;
pCard->hPrivateContext = hPrivateContext;
InitializeCriticalSectionAndSpinCount(&(pCard->lock), 4000);
pContext = PCSC_GetCardContextData(hContext);
pContext->dwCardHandleCount++;
pContext->hCard = hCard;
printf("PCSC_ConnectCardHandle: %d\n", pContext->dwCardHandleCount);
if (!g_CardHandles)
g_CardHandles = ListDictionary_New(TRUE);
@ -436,9 +442,9 @@ void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
DeleteCriticalSection(&(pCard->lock));
pContext = PCSC_GetCardContextData(pCard->hContext);
pContext = PCSC_GetCardContextData(pCard->hSharedContext);
pContext->hCard = 0;
PCSC_SCardReleaseContext_Internal(pCard->hPrivateContext);
free(pCard);
@ -446,6 +452,16 @@ void PCSC_DisconnectCardHandle(SCARDHANDLE hCard)
return;
ListDictionary_Remove(g_CardHandles, (void*) hCard);
if (!pContext)
{
printf("PCSC_DisconnectCardHandle: null pContext!");
return;
}
pContext->dwCardHandleCount--;
printf("PCSC_DisconnectCardHandle: %d\n", pContext->dwCardHandleCount);
}
BOOL PCSC_LockCardHandle(SCARDHANDLE hCard)
@ -869,7 +885,7 @@ void* PCSC_SCardAllocMemory(SCARDCONTEXT hContext, size_t size)
* Standard Windows Smart Card API (PCSC)
*/
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope,
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope,
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
LONG status = SCARD_S_SUCCESS;
@ -883,13 +899,23 @@ WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope,
status = (LONG) g_PCSC.pfnSCardEstablishContext(pcsc_dwScope, pvReserved1, pvReserved2, phContext);
status = PCSC_MapErrorCodeToWinSCard(status);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope,
LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
LONG status = SCARD_S_SUCCESS;
status = PCSC_SCardEstablishContext_Internal(dwScope, pvReserved1, pvReserved2, phContext);
if (status == SCARD_S_SUCCESS)
PCSC_EstablishCardContext(*phContext);
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
@ -905,7 +931,16 @@ WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
status = (LONG) g_PCSC.pfnSCardReleaseContext(hContext);
status = PCSC_MapErrorCodeToWinSCard(status);
if (!status)
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
{
LONG status = SCARD_S_SUCCESS;
status = PCSC_SCardReleaseContext_Internal(hContext);
if (status != SCARD_S_SUCCESS)
PCSC_ReleaseCardContext(hContext);
return status;
@ -1612,6 +1647,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
{
char* szReaderPCSC;
LONG status = SCARD_S_SUCCESS;
SCARDCONTEXT hPrivateContext = 0;
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
PCSC_DWORD pcsc_dwActiveProtocol = 0;
@ -1619,8 +1655,10 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
if (!g_PCSC.pfnSCardConnect)
return SCARD_E_NO_SERVICE;
if (PCSC_IsCardHandleConnected(hContext))
return SCARD_E_SHARING_VIOLATION;
status = PCSC_SCardEstablishContext_Internal(SCARD_SCOPE_SYSTEM, NULL, NULL, &hPrivateContext);
if (status != SCARD_S_SUCCESS)
return status;
szReaderPCSC = PCSC_GetReaderNameFromAlias((char*) szReader);
@ -1629,15 +1667,19 @@ WINSCARDAPI LONG WINAPI PCSC_SCardConnect_Internal(SCARDCONTEXT hContext,
pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
status = (LONG) g_PCSC.pfnSCardConnect(hContext, szReaderPCSC,
status = (LONG) g_PCSC.pfnSCardConnect(hPrivateContext, szReaderPCSC,
pcsc_dwShareMode, pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol);
status = PCSC_MapErrorCodeToWinSCard(status);
if (status == SCARD_S_SUCCESS)
{
PCSC_ConnectCardHandle(hContext, *phCard);
PCSC_ConnectCardHandle(hContext, hPrivateContext, *phCard);
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
}
else
{
PCSC_SCardReleaseContext(hPrivateContext);
}
return status;
}
@ -2673,7 +2715,7 @@ extern int PCSC_InitializeSCardApi_Link(void);
int PCSC_InitializeSCardApi(void)
{
/* Disable pcsc-lite's (poor) blocking so we can handle it ourselves */
//SetEnvironmentVariableA("PCSCLITE_NO_BLOCKING", "1");
SetEnvironmentVariableA("PCSCLITE_NO_BLOCKING", "1");
#ifndef DISABLE_PCSC_LINK
if (PCSC_InitializeSCardApi_Link() >= 0)