//#define DISABLE_PCSC_SCARD_AUTOALLOCATE
+typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
+typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
+
struct _PCSC_SCARDCONTEXT
{
+ SCARDHANDLE owner;
CRITICAL_SECTION lock;
SCARDCONTEXT hContext;
DWORD dwCardHandleCount;
BOOL isTransactionLocked;
};
-typedef struct _PCSC_SCARDCONTEXT PCSC_SCARDCONTEXT;
struct _PCSC_SCARDHANDLE
{
- CRITICAL_SECTION lock;
+ BOOL shared;
SCARDCONTEXT hSharedContext;
SCARDCONTEXT hPrivateContext;
};
-typedef struct _PCSC_SCARDHANDLE PCSC_SCARDHANDLE;
struct _PCSC_READER
{
static BOOL g_SCardAutoAllocate = FALSE;
static BOOL g_PnP_Notification = TRUE;
+
#ifdef __MACOSX__
static unsigned int OSXVersion = 0;
#endif
return pCard->hPrivateContext;
}
+BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
+{
+ BOOL status = TRUE;
+ PCSC_SCARDHANDLE* pCard = NULL;
+ PCSC_SCARDCONTEXT* pContext = NULL;
+
+ if (!hCard)
+ {
+ /* SCardConnect */
+
+ pContext = PCSC_GetCardContextData(hContext);
+
+ if (!pContext)
+ return FALSE;
+
+ if (!pContext->owner)
+ return TRUE;
+
+ /* wait for card ownership */
+
+ return TRUE;
+ }
+
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return FALSE;
+
+ shared = pCard->shared;
+ hContext = pCard->hSharedContext;
+
+ pContext = PCSC_GetCardContextData(hContext);
+
+ if (!pContext)
+ return FALSE;
+
+ if (!pContext->owner)
+ {
+ /* card is not owned */
+
+ if (!shared)
+ pContext->owner = hCard;
+
+ return TRUE;
+ }
+
+ if (pContext->owner == hCard)
+ {
+ /* already card owner */
+ }
+ else
+ {
+ /* wait for card ownership */
+ }
+
+ return status;
+}
+
+BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard)
+{
+ PCSC_SCARDHANDLE* pCard = NULL;
+ PCSC_SCARDCONTEXT* pContext = NULL;
+
+ if (!hCard)
+ {
+ /* release current owner */
+
+ pContext = PCSC_GetCardContextData(hContext);
+
+ if (!pContext)
+ return FALSE;
+
+ hCard = pContext->owner;
+
+ if (!hCard)
+ return TRUE;
+
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return FALSE;
+
+ /* release card ownership */
+
+ pContext->owner = 0;
+
+ return TRUE;
+ }
+
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return FALSE;
+
+ hContext = pCard->hSharedContext;
+
+ pContext = PCSC_GetCardContextData(hContext);
+
+ if (!pContext)
+ return FALSE;
+
+ if (pContext->owner == hCard)
+ {
+ /* release card ownership */
+
+ pContext->owner = 0;
+ }
+
+ return TRUE;
+}
+
PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDCONTEXT hPrivateContext, SCARDHANDLE hCard)
{
PCSC_SCARDHANDLE* pCard;
pCard->hSharedContext = hSharedContext;
pCard->hPrivateContext = hPrivateContext;
- InitializeCriticalSectionAndSpinCount(&(pCard->lock), 4000);
pContext->dwCardHandleCount++;
if (!g_CardHandles)
g_CardHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_CardHandles, (void*) hCard, (void*) pCard);
+
return pCard;
}
{
PCSC_SCARDHANDLE* pCard;
PCSC_SCARDCONTEXT* pContext;
+
pCard = PCSC_GetCardHandleData(hCard);
if (!pCard)
return;
- DeleteCriticalSection(&(pCard->lock));
pContext = PCSC_GetCardContextData(pCard->hSharedContext);
PCSC_SCardReleaseContext_Internal(pCard->hPrivateContext);
free(pCard);
pContext->dwCardHandleCount--;
}
-BOOL PCSC_LockCardHandle(SCARDHANDLE hCard)
-{
- PCSC_SCARDHANDLE* pCard;
- pCard = PCSC_GetCardHandleData(hCard);
-
- if (!pCard)
- {
- WLog_ERR(TAG, "PCSC_LockCardHandle: invalid handle (%p)", (void*) hCard);
- return FALSE;
- }
-
- EnterCriticalSection(&(pCard->lock));
- return TRUE;
-}
-
-BOOL PCSC_UnlockCardHandle(SCARDHANDLE hCard)
-{
- PCSC_SCARDHANDLE* pCard;
- pCard = PCSC_GetCardHandleData(hCard);
-
- if (!pCard)
- {
- WLog_ERR(TAG, "PCSC_UnlockCardHandle: invalid handle (%p)", (void*) hCard);
- return FALSE;
- }
-
- LeaveCriticalSection(&(pCard->lock));
- return TRUE;
-}
-
-BOOL PCSC_LockCardTransaction(SCARDHANDLE hCard)
-{
- PCSC_SCARDHANDLE* pCard;
- return TRUE; /* disable for now because it deadlocks */
- pCard = PCSC_GetCardHandleData(hCard);
-
- if (!pCard)
- {
- WLog_ERR(TAG, "PCSC_LockCardTransaction: invalid handle (%p)", (void*) hCard);
- return FALSE;
- }
-
- EnterCriticalSection(&(pCard->lock));
- return TRUE;
-}
-
-BOOL PCSC_UnlockCardTransaction(SCARDHANDLE hCard)
-{
- PCSC_SCARDHANDLE* pCard;
- return TRUE; /* disable for now because it deadlocks */
- pCard = PCSC_GetCardHandleData(hCard);
-
- if (!pCard)
- {
- WLog_ERR(TAG, "PCSC_UnlockCardTransaction: invalid handle (%p)", (void*) hCard);
- return FALSE;
- }
-
- LeaveCriticalSection(&(pCard->lock));
- return TRUE;
-}
-
char* PCSC_GetReaderNameFromAlias(char* nameWinSCard)
{
int index;
LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
+ BOOL shared;
+ BOOL access;
char* szReaderPCSC;
LONG status = SCARD_S_SUCCESS;
+ PCSC_SCARDHANDLE* pCard = NULL;
SCARDCONTEXT hPrivateContext = 0;
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
if (!g_PCSC.pfnSCardConnect)
return SCARD_E_NO_SERVICE;
+ shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE;
+
+ access = PCSC_WaitForCardAccess(hContext, 0, shared);
+
status = PCSC_SCardEstablishContext_Internal(SCARD_SCOPE_SYSTEM, NULL, NULL, &hPrivateContext);
if (status != SCARD_S_SUCCESS)
if (status == SCARD_S_SUCCESS)
{
- PCSC_ConnectCardHandle(hContext, hPrivateContext, *phCard);
+ pCard = PCSC_ConnectCardHandle(hContext, hPrivateContext, *phCard);
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
+
+ pCard->shared = shared;
+ PCSC_WaitForCardAccess(hContext, pCard->hSharedContext, shared);
}
else
{
WINSCARDAPI LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard,
DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
{
+ BOOL shared;
+ BOOL access;
LONG status = SCARD_S_SUCCESS;
PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD) dwShareMode;
PCSC_DWORD pcsc_dwPreferredProtocols = 0;
if (!g_PCSC.pfnSCardReconnect)
return SCARD_E_NO_SERVICE;
+ shared = (dwShareMode == SCARD_SHARE_DIRECT) ? TRUE : FALSE;
+
+ access = PCSC_WaitForCardAccess(0, hCard, shared);
+
pcsc_dwPreferredProtocols = (PCSC_DWORD) PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
status = (LONG) g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode,
pcsc_dwPreferredProtocols, pcsc_dwInitialization, &pcsc_dwActiveProtocol);
status = PCSC_MapErrorCodeToWinSCard(status);
*pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwActiveProtocol);
+
return status;
}
PCSC_DisconnectCardHandle(hCard);
}
+ PCSC_ReleaseCardAccess(0, hCard);
+
return status;
}
if (!pContext)
return SCARD_E_INVALID_HANDLE;
+ PCSC_ReleaseCardAccess(0, hCard);
+
if (!pContext->isTransactionLocked)
return SCARD_S_SUCCESS; /* disable nested transactions */
}
pContext->isTransactionLocked = FALSE;
+
return status;
}
WINSCARDAPI LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
{
- return 0;
+ return SCARD_S_SUCCESS;
}
WINSCARDAPI LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard,
- LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
+ LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
{
PCSC_DWORD cchReaderLen;
SCARDCONTEXT hContext = 0;
LPSTR mszReaderNames = NULL;
LONG status = SCARD_S_SUCCESS;
+ PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_dwState = 0;
PCSC_DWORD pcsc_dwProtocol = 0;
PCSC_DWORD pcsc_cbAtrLen = (PCSC_DWORD) *pcbAtrLen;
if (!g_PCSC.pfnSCardStatus)
return SCARD_E_NO_SERVICE;
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return SCARD_E_INVALID_VALUE;
+
+ PCSC_WaitForCardAccess(0, hCard, pCard->shared);
+
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext)
cchReaderLen = SCARD_AUTOALLOCATE;
status = (LONG) g_PCSC.pfnSCardStatus(hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
- &pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
+ &pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
if (mszReaderNames)
*pdwState = (DWORD) pcsc_dwState;
*pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD) pcsc_dwProtocol);
*pcbAtrLen = (DWORD) pcsc_cbAtrLen;
+
return status;
}
LPBYTE* pPbAtr = (LPBYTE*) pbAtr;
LPSTR* pMszReaderNames = (LPSTR*) mszReaderNames;
LONG status = SCARD_S_SUCCESS;
+ PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_cchReaderLen = 0;
PCSC_DWORD pcsc_dwState = 0;
PCSC_DWORD pcsc_dwProtocol = 0;
if (!g_PCSC.pfnSCardStatus)
return SCARD_E_NO_SERVICE;
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return SCARD_E_INVALID_VALUE;
+
+ PCSC_WaitForCardAccess(0, hCard, pCard->shared);
+
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext || !pcchReaderLen || !pdwState || !pdwProtocol || !pcbAtrLen)
pcsc_cbAtrLen = 0;
status = (LONG) g_PCSC.pfnSCardStatus(hCard,
- (pcchReaderLenAlloc) ? NULL : mszReaderNames, &pcsc_cchReaderLen,
- &pcsc_dwState, &pcsc_dwProtocol,
- (pcbAtrLenAlloc) ? NULL : pbAtr, &pcsc_cbAtrLen);
+ (pcchReaderLenAlloc) ? NULL : mszReaderNames, &pcsc_cchReaderLen,
+ &pcsc_dwState, &pcsc_dwProtocol,
+ (pcbAtrLenAlloc) ? NULL : pbAtr, &pcsc_cbAtrLen);
if (status == SCARD_S_SUCCESS)
{
}
status = (LONG) g_PCSC.pfnSCardStatus(hCard,
- *pMszReaderNames, &pcsc_cchReaderLen,
- &pcsc_dwState, &pcsc_dwProtocol,
- pbAtr, &pcsc_cbAtrLen);
+ *pMszReaderNames, &pcsc_cchReaderLen,
+ &pcsc_dwState, &pcsc_dwProtocol,
+ pbAtr, &pcsc_cbAtrLen);
if (status != SCARD_S_SUCCESS)
{
else
{
status = (LONG) g_PCSC.pfnSCardStatus(hCard, mszReaderNames, &pcsc_cchReaderLen,
- &pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
+ &pcsc_dwState, &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen);
}
status = PCSC_MapErrorCodeToWinSCard(status);
LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
{
LONG status = SCARD_S_SUCCESS;
+ PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD cbExtraBytes = 0;
BYTE* pbExtraBytes = NULL;
BYTE* pcsc_pbExtraBytes = NULL;
if (!g_PCSC.pfnSCardTransmit)
return SCARD_E_NO_SERVICE;
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return SCARD_E_INVALID_VALUE;
+
+ PCSC_WaitForCardAccess(0, hCard, pCard->shared);
+
if (!pcbRecvLength)
return SCARD_E_INVALID_PARAMETER;
WINSCARDAPI LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount)
{
- return 0;
+ PCSC_SCARDHANDLE* pCard = NULL;
+
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return SCARD_E_INVALID_VALUE;
+
+ PCSC_WaitForCardAccess(0, hCard, pCard->shared);
+
+ return SCARD_S_SUCCESS;
}
WINSCARDAPI LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard,
DWORD IoCtlDeviceType = 0;
BOOL getFeatureRequest = FALSE;
LONG status = SCARD_S_SUCCESS;
+ PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_dwControlCode = 0;
PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD) cbInBufferSize;
PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD) cbOutBufferSize;
if (!g_PCSC.pfnSCardControl)
return SCARD_E_NO_SERVICE;
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return SCARD_E_INVALID_VALUE;
+
+ PCSC_WaitForCardAccess(0, hCard, pCard->shared);
+
/**
* PCSCv2 Part 10:
* http://www.pcscworkgroup.com/specifications/files/pcsc10_v2.02.09.pdf
BOOL pcbAttrLenAlloc = FALSE;
LPBYTE* pPbAttr = (LPBYTE*) pbAttr;
LONG status = SCARD_S_SUCCESS;
+ PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
PCSC_DWORD pcsc_cbAttrLen = 0;
if (!g_PCSC.pfnSCardGetAttrib)
return SCARD_E_NO_SERVICE;
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return SCARD_E_INVALID_VALUE;
+
+ PCSC_WaitForCardAccess(0, hCard, pCard->shared);
+
hContext = PCSC_GetCardContextFromHandle(hCard);
if (!hContext)
WINSCARDAPI LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
{
LONG status = SCARD_S_SUCCESS;
+ PCSC_SCARDHANDLE* pCard = NULL;
PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD) dwAttrId;
PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD) cbAttrLen;
if (!g_PCSC.pfnSCardSetAttrib)
return SCARD_E_NO_SERVICE;
+ pCard = PCSC_GetCardHandleData(hCard);
+
+ if (!pCard)
+ return SCARD_E_INVALID_VALUE;
+
+ PCSC_WaitForCardAccess(0, hCard, pCard->shared);
+
status = (LONG) g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
status = PCSC_MapErrorCodeToWinSCard(status);
+
return status;
}