diff --git a/channels/smartcard/client/smartcard_operations.c b/channels/smartcard/client/smartcard_operations.c index a50651472..47f77c4e9 100644 --- a/channels/smartcard/client/smartcard_operations.c +++ b/channels/smartcard/client/smartcard_operations.c @@ -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) diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index b80a619a7..10a891d2e 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -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, "}"); } diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index 3553db8e8..83c0fce93 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -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)