22#include <winpr/config.h>
29#include <sys/sysctl.h>
39#include <winpr/assert.h>
40#include <winpr/synch.h>
41#include <winpr/library.h>
42#include <winpr/smartcard.h>
43#include <winpr/collections.h>
44#include <winpr/environment.h>
46#include "smartcard_pcsc.h"
49#define TAG WINPR_TAG("smartcard")
52#define MIN(x, y) (((x) < (y)) ? (x) : (y))
55#define WINSCARD_LOAD_PROC_EX(module, pcsc, _fname, _name) \
58 WINPR_PRAGMA_DIAG_PUSH \
59 WINPR_PRAGMA_DIAG_IGNORED_PEDANTIC \
60 pcsc.pfn##_fname = GetProcAddressAs(module, #_name, fnPCSC##_fname); \
61 WINPR_PRAGMA_DIAG_POP \
64#define WINSCARD_LOAD_PROC(module, pcsc, _name) WINSCARD_LOAD_PROC_EX(module, pcsc, _name, _name)
129#include "smartcard_pcsc.h"
131#define PCSC_SCARD_PCI_T0 (&g_PCSC_rgSCardT0Pci)
132#define PCSC_SCARD_PCI_T1 (&g_PCSC_rgSCardT1Pci)
133#define PCSC_SCARD_PCI_RAW (&g_PCSC_rgSCardRawPci)
135typedef PCSC_LONG (*fnPCSCSCardEstablishContext)(PCSC_DWORD dwScope, LPCVOID pvReserved1,
136 LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
137typedef PCSC_LONG (*fnPCSCSCardReleaseContext)(SCARDCONTEXT hContext);
138typedef PCSC_LONG (*fnPCSCSCardIsValidContext)(SCARDCONTEXT hContext);
139typedef PCSC_LONG (*fnPCSCSCardConnect)(SCARDCONTEXT hContext, LPCSTR szReader,
140 PCSC_DWORD dwShareMode, PCSC_DWORD dwPreferredProtocols,
141 LPSCARDHANDLE phCard, PCSC_LPDWORD pdwActiveProtocol);
142typedef PCSC_LONG (*fnPCSCSCardReconnect)(SCARDHANDLE hCard, PCSC_DWORD dwShareMode,
143 PCSC_DWORD dwPreferredProtocols,
144 PCSC_DWORD dwInitialization,
145 PCSC_LPDWORD pdwActiveProtocol);
146typedef PCSC_LONG (*fnPCSCSCardDisconnect)(SCARDHANDLE hCard, PCSC_DWORD dwDisposition);
147typedef PCSC_LONG (*fnPCSCSCardBeginTransaction)(SCARDHANDLE hCard);
148typedef PCSC_LONG (*fnPCSCSCardEndTransaction)(SCARDHANDLE hCard, PCSC_DWORD dwDisposition);
149typedef PCSC_LONG (*fnPCSCSCardStatus)(SCARDHANDLE hCard, LPSTR mszReaderName,
150 PCSC_LPDWORD pcchReaderLen, PCSC_LPDWORD pdwState,
151 PCSC_LPDWORD pdwProtocol, LPBYTE pbAtr,
152 PCSC_LPDWORD pcbAtrLen);
153typedef PCSC_LONG (*fnPCSCSCardGetStatusChange)(SCARDCONTEXT hContext, PCSC_DWORD dwTimeout,
155 PCSC_DWORD cReaders);
156typedef PCSC_LONG (*fnPCSCSCardControl)(SCARDHANDLE hCard, PCSC_DWORD dwControlCode,
157 LPCVOID pbSendBuffer, PCSC_DWORD cbSendLength,
158 LPVOID pbRecvBuffer, PCSC_DWORD cbRecvLength,
159 PCSC_LPDWORD lpBytesReturned);
161 LPCBYTE pbSendBuffer, PCSC_DWORD cbSendLength,
163 PCSC_LPDWORD pcbRecvLength);
164typedef PCSC_LONG (*fnPCSCSCardListReaderGroups)(SCARDCONTEXT hContext, LPSTR mszGroups,
165 PCSC_LPDWORD pcchGroups);
166typedef PCSC_LONG (*fnPCSCSCardListReaders)(SCARDCONTEXT hContext, LPCSTR mszGroups,
167 LPSTR mszReaders, PCSC_LPDWORD pcchReaders);
168typedef PCSC_LONG (*fnPCSCSCardFreeMemory)(SCARDCONTEXT hContext, LPCVOID pvMem);
169typedef PCSC_LONG (*fnPCSCSCardCancel)(SCARDCONTEXT hContext);
170typedef PCSC_LONG (*fnPCSCSCardGetAttrib)(SCARDHANDLE hCard, PCSC_DWORD dwAttrId, LPBYTE pbAttr,
171 PCSC_LPDWORD pcbAttrLen);
172typedef PCSC_LONG (*fnPCSCSCardSetAttrib)(SCARDHANDLE hCard, PCSC_DWORD dwAttrId, LPCBYTE pbAttr,
173 PCSC_DWORD cbAttrLen);
177 WINPR_ATTR_NODISCARD fnPCSCSCardEstablishContext pfnSCardEstablishContext;
178 WINPR_ATTR_NODISCARD fnPCSCSCardReleaseContext pfnSCardReleaseContext;
179 WINPR_ATTR_NODISCARD fnPCSCSCardIsValidContext pfnSCardIsValidContext;
180 WINPR_ATTR_NODISCARD fnPCSCSCardConnect pfnSCardConnect;
181 WINPR_ATTR_NODISCARD fnPCSCSCardReconnect pfnSCardReconnect;
182 WINPR_ATTR_NODISCARD fnPCSCSCardDisconnect pfnSCardDisconnect;
183 WINPR_ATTR_NODISCARD fnPCSCSCardBeginTransaction pfnSCardBeginTransaction;
184 WINPR_ATTR_NODISCARD fnPCSCSCardEndTransaction pfnSCardEndTransaction;
185 WINPR_ATTR_NODISCARD fnPCSCSCardStatus pfnSCardStatus;
186 WINPR_ATTR_NODISCARD fnPCSCSCardGetStatusChange pfnSCardGetStatusChange;
187 WINPR_ATTR_NODISCARD fnPCSCSCardControl pfnSCardControl;
188 WINPR_ATTR_NODISCARD fnPCSCSCardTransmit pfnSCardTransmit;
189 WINPR_ATTR_NODISCARD fnPCSCSCardListReaderGroups pfnSCardListReaderGroups;
190 WINPR_ATTR_NODISCARD fnPCSCSCardListReaders pfnSCardListReaders;
191 fnPCSCSCardFreeMemory pfnSCardFreeMemory;
192 fnPCSCSCardCancel pfnSCardCancel;
193 WINPR_ATTR_NODISCARD fnPCSCSCardGetAttrib pfnSCardGetAttrib;
194 WINPR_ATTR_NODISCARD fnPCSCSCardSetAttrib pfnSCardSetAttrib;
208 SCARDCONTEXT hContext;
209 DWORD dwCardHandleCount;
210 BOOL isTransactionLocked;
217 SCARDCONTEXT hSharedContext;
220static HMODULE g_PCSCModule =
nullptr;
221static PCSCFunctionTable g_PCSC = WINPR_C_ARRAY_INIT;
223static HANDLE g_StartedEvent =
nullptr;
224static int g_StartedEventRefCount = 0;
226static BOOL g_SCardAutoAllocate = FALSE;
227static BOOL g_PnP_Notification = TRUE;
230static unsigned int OSXVersion = 0;
233static wListDictionary* g_CardHandles =
nullptr;
234static wListDictionary* g_CardContexts =
nullptr;
235static wListDictionary* g_MemoryBlocks =
nullptr;
236static INIT_ONCE g_CardHandleInitializer = INIT_ONCE_STATIC_INIT;
238static const char SMARTCARD_PNP_NOTIFICATION_A[] =
"\\\\?PnP?\\Notification";
247static void clearHandles(
void)
249 ListDictionary_Free(g_CardHandles);
250 ListDictionary_Free(g_CardContexts);
251 ListDictionary_Free(g_MemoryBlocks);
253 g_CardHandles =
nullptr;
254 g_CardContexts =
nullptr;
255 g_MemoryBlocks =
nullptr;
259static wListDictionary* setupWithValueObjectFree(BOOL key)
261 wListDictionary* list = ListDictionary_New(TRUE);
266 wObject* obj = ListDictionary_ValueObject(list);
268 obj = ListDictionary_KeyObject(list);
275static void cardContextFree(PCSC_SCARDCONTEXT* pContext)
280 DeleteCriticalSection(&(pContext->lock));
281 HashTable_Free(pContext->cache);
285static void cardContextFreeVoid(
void* obj)
287 PCSC_SCARDCONTEXT* pContext = obj;
288 cardContextFree(pContext);
292static BOOL initializeHandles(WINPR_ATTR_UNUSED
PINIT_ONCE InitOnce,
293 WINPR_ATTR_UNUSED PVOID Parameter, WINPR_ATTR_UNUSED PVOID* Context)
295 (void)atexit(clearHandles);
296 g_CardHandles = setupWithValueObjectFree(FALSE);
299 g_CardContexts = ListDictionary_New(TRUE);
303 wObject* obj = ListDictionary_ValueObject(g_CardContexts);
309 g_MemoryBlocks = setupWithValueObjectFree(TRUE);
310 return g_MemoryBlocks !=
nullptr;
314static BOOL init(
void)
316 return InitOnceExecuteOnce(&g_CardHandleInitializer, initializeHandles,
nullptr,
nullptr);
319static LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPVOID pvMem);
322static LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1,
324 LPSCARDCONTEXT phContext);
327static LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext);
330static LONG PCSC_SCard_LogError(
const char* what)
332 WLog_WARN(TAG,
"Missing function pointer %s=nullptr", what);
333 return SCARD_E_UNSUPPORTED_FEATURE;
337static LONG PCSC_MapErrorCodeToWinSCard(PCSC_LONG errorCode)
347 if (errorCode != SCARD_S_SUCCESS)
349 if (errorCode == SCARD_E_UNEXPECTED)
350 errorCode = SCARD_E_UNSUPPORTED_FEATURE;
353 return (LONG)errorCode;
357static DWORD PCSC_ConvertCardStateToWinSCard(DWORD dwCardState, PCSC_LONG status)
375 if (status == SCARD_S_SUCCESS)
377 if ((dwCardState & PCSC_SCARD_NEGOTIABLE) || (dwCardState & PCSC_SCARD_SPECIFIC))
378 return SCARD_SPECIFIC;
381 if (dwCardState & PCSC_SCARD_POWERED)
382 return SCARD_POWERED;
384 if (dwCardState & PCSC_SCARD_NEGOTIABLE)
385 return SCARD_NEGOTIABLE;
387 if (dwCardState & PCSC_SCARD_SPECIFIC)
388 return SCARD_SPECIFIC;
390 if (dwCardState & PCSC_SCARD_ABSENT)
393 if (dwCardState & PCSC_SCARD_PRESENT)
394 return SCARD_PRESENT;
396 if (dwCardState & PCSC_SCARD_SWALLOWED)
397 return SCARD_SWALLOWED;
399 if (dwCardState & PCSC_SCARD_UNKNOWN)
400 return SCARD_UNKNOWN;
402 return SCARD_UNKNOWN;
406static DWORD PCSC_ConvertProtocolsToWinSCard(PCSC_DWORD dwProtocols)
412 if (dwProtocols & PCSC_SCARD_PROTOCOL_RAW)
414 dwProtocols &= ~PCSC_SCARD_PROTOCOL_RAW;
415 dwProtocols |= SCARD_PROTOCOL_RAW;
418 if (dwProtocols & PCSC_SCARD_PROTOCOL_T15)
420 dwProtocols &= ~PCSC_SCARD_PROTOCOL_T15;
423 return (DWORD)dwProtocols;
427static DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols)
433 if (dwProtocols & SCARD_PROTOCOL_RAW)
435 dwProtocols &= ~SCARD_PROTOCOL_RAW;
436 dwProtocols |= PCSC_SCARD_PROTOCOL_RAW;
439 if (dwProtocols & SCARD_PROTOCOL_DEFAULT)
441 dwProtocols &= ~SCARD_PROTOCOL_DEFAULT;
444 if (dwProtocols == SCARD_PROTOCOL_UNDEFINED)
446 dwProtocols = SCARD_PROTOCOL_Tx;
453static PCSC_SCARDCONTEXT* PCSC_GetCardContextData(SCARDCONTEXT hContext)
458 PCSC_SCARDCONTEXT* pContext =
459 (PCSC_SCARDCONTEXT*)ListDictionary_GetItemValue(g_CardContexts, (
void*)hContext);
467static void pcsc_cache_item_free(
void* ptr)
469 PCSC_CACHE_ITEM* data = ptr;
475static PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext)
480 PCSC_SCARDCONTEXT* pContext = (PCSC_SCARDCONTEXT*)calloc(1,
sizeof(PCSC_SCARDCONTEXT));
485 pContext->hContext = hContext;
487 if (!InitializeCriticalSectionAndSpinCount(&(pContext->lock), 4000))
490 pContext->cache = HashTable_New(FALSE);
491 if (!pContext->cache)
493 if (!HashTable_SetupForStringData(pContext->cache, FALSE))
496 wObject* obj = HashTable_ValueObject(pContext->cache);
500 if (!ListDictionary_Add(g_CardContexts, (
void*)hContext, (
void*)pContext))
505 cardContextFree(pContext);
509static void PCSC_ReleaseCardContext(SCARDCONTEXT hContext)
513 PCSC_SCARDCONTEXT* pContext = ListDictionary_Take(g_CardContexts, (
void*)hContext);
514 cardContextFree(pContext);
519static BOOL PCSC_LockCardContext(SCARDCONTEXT hContext)
521 PCSC_SCARDCONTEXT* pContext =
nullptr;
522 pContext = PCSC_GetCardContextData(hContext);
526 WLog_ERR(TAG,
"PCSC_LockCardContext: invalid context (%p)", (
void*)hContext);
530 EnterCriticalSection(&(pContext->lock));
535static BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext)
537 PCSC_SCARDCONTEXT* pContext =
nullptr;
538 pContext = PCSC_GetCardContextData(hContext);
542 WLog_ERR(TAG,
"PCSC_UnlockCardContext: invalid context (%p)", (
void*)hContext);
546 LeaveCriticalSection(&(pContext->lock));
551static PCSC_SCARDHANDLE* PCSC_GetCardHandleData(SCARDHANDLE hCard)
556 PCSC_SCARDHANDLE* pCard =
557 (PCSC_SCARDHANDLE*)ListDictionary_GetItemValue(g_CardHandles, (
void*)hCard);
566static SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
568 PCSC_SCARDHANDLE* pCard =
nullptr;
569 pCard = PCSC_GetCardHandleData(hCard);
574 return pCard->hSharedContext;
577static BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
580 PCSC_SCARDHANDLE* pCard =
nullptr;
581 PCSC_SCARDCONTEXT* pContext =
nullptr;
586 pContext = PCSC_GetCardContextData(hContext);
591 if (!pContext->owner)
598 pCard = PCSC_GetCardHandleData(hCard);
603 shared = pCard->shared;
604 hContext = pCard->hSharedContext;
605 pContext = PCSC_GetCardContextData(hContext);
610 if (!pContext->owner)
614 pContext->owner = hCard;
619 if (pContext->owner == hCard)
631static BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard)
633 PCSC_SCARDHANDLE* pCard =
nullptr;
634 PCSC_SCARDCONTEXT* pContext =
nullptr;
639 pContext = PCSC_GetCardContextData(hContext);
644 hCard = pContext->owner;
649 pCard = PCSC_GetCardHandleData(hCard);
659 pCard = PCSC_GetCardHandleData(hCard);
664 hContext = pCard->hSharedContext;
665 pContext = PCSC_GetCardContextData(hContext);
670 if (pContext->owner == hCard)
679static void PCSC_DisconnectCardHandle(PCSC_SCARDHANDLE* pCard)
684 PCSC_SCARDCONTEXT* pContext = PCSC_GetCardContextData(pCard->hSharedContext);
686 ListDictionary_Remove(g_CardHandles, (
void*)pCard);
690 WLog_ERR(TAG,
"PCSC_DisconnectCardHandle: null pContext!");
694 pContext->dwCardHandleCount--;
697WINPR_ATTR_MALLOC(PCSC_DisconnectCardHandle, 1)
698static PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDHANDLE hCard)
703 PCSC_SCARDCONTEXT* pContext = PCSC_GetCardContextData(hSharedContext);
707 WLog_ERR(TAG,
"PCSC_ConnectCardHandle: null pContext!");
711 PCSC_SCARDHANDLE* pCard = (PCSC_SCARDHANDLE*)calloc(1,
sizeof(PCSC_SCARDHANDLE));
716 pCard->hSharedContext = hSharedContext;
718 if (!ListDictionary_Add(g_CardHandles, (
void*)hCard, (
void*)pCard))
721 pContext->dwCardHandleCount++;
728static BOOL PCSC_AddMemoryBlock(SCARDCONTEXT hContext,
void* pvMem)
732 return ListDictionary_Add(g_MemoryBlocks, pvMem, (
void*)hContext);
736static void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext,
void* pvMem)
738 WINPR_UNUSED(hContext);
743 return ListDictionary_Take(g_MemoryBlocks, pvMem);
750static LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1,
752 LPSCARDCONTEXT phContext)
754 WINPR_UNUSED(dwScope);
755 PCSC_LONG status = SCARD_S_SUCCESS;
757 if (!g_PCSC.pfnSCardEstablishContext)
758 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEstablishContext");
761 g_PCSC.pfnSCardEstablishContext(SCARD_SCOPE_SYSTEM, pvReserved1, pvReserved2, phContext);
762 return PCSC_MapErrorCodeToWinSCard(status);
766static LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
767 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
771 status = PCSC_SCardEstablishContext_Internal(dwScope, pvReserved1, pvReserved2, phContext);
773 if (status == SCARD_S_SUCCESS)
774 PCSC_EstablishCardContext(*phContext);
780static LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext)
782 PCSC_LONG status = SCARD_S_SUCCESS;
784 if (!g_PCSC.pfnSCardReleaseContext)
785 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardReleaseContext");
789 WLog_ERR(TAG,
"SCardReleaseContext: null hContext");
790 return PCSC_MapErrorCodeToWinSCard(SCARD_E_INVALID_HANDLE);
793 status = g_PCSC.pfnSCardReleaseContext(hContext);
794 return PCSC_MapErrorCodeToWinSCard(status);
798static LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
800 LONG status = SCARD_S_SUCCESS;
802 status = PCSC_SCardReleaseContext_Internal(hContext);
803 PCSC_ReleaseCardContext(hContext);
809static LONG WINAPI PCSC_SCardIsValidContext(SCARDCONTEXT hContext)
811 PCSC_LONG status = SCARD_S_SUCCESS;
813 if (!g_PCSC.pfnSCardIsValidContext)
814 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardIsValidContext");
816 status = g_PCSC.pfnSCardIsValidContext(hContext);
817 return PCSC_MapErrorCodeToWinSCard(status);
821static LONG WINAPI PCSC_SCardListReaderGroups_Internal(SCARDCONTEXT hContext, LPSTR mszGroups,
824 PCSC_LONG status = SCARD_S_SUCCESS;
825 BOOL pcchGroupsAlloc = FALSE;
826 PCSC_DWORD pcsc_cchGroups = 0;
829 return SCARD_E_INVALID_PARAMETER;
831 if (!g_PCSC.pfnSCardListReaderGroups)
832 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
834 if (*pcchGroups == SCARD_AUTOALLOCATE)
835 pcchGroupsAlloc = TRUE;
837 pcsc_cchGroups = pcchGroupsAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcchGroups;
839 if (pcchGroupsAlloc && !g_SCardAutoAllocate)
842 status = g_PCSC.pfnSCardListReaderGroups(hContext,
nullptr, &pcsc_cchGroups);
844 if (status == SCARD_S_SUCCESS)
846 LPSTR tmp = calloc(1, pcsc_cchGroups);
849 return SCARD_E_NO_MEMORY;
851 status = g_PCSC.pfnSCardListReaderGroups(hContext, tmp, &pcsc_cchGroups);
853 if (status != SCARD_S_SUCCESS)
859 PCSC_AddMemoryBlock(hContext, tmp);
861 *(LPSTR*)mszGroups = tmp;
866 status = g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, &pcsc_cchGroups);
869 *pcchGroups = (DWORD)pcsc_cchGroups;
870 return PCSC_MapErrorCodeToWinSCard(status);
874static LONG WINAPI PCSC_SCardListReaderGroupsA(SCARDCONTEXT hContext, LPSTR mszGroups,
877 LONG status = SCARD_S_SUCCESS;
879 if (!g_PCSC.pfnSCardListReaderGroups)
880 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
882 if (!PCSC_LockCardContext(hContext))
883 return SCARD_E_INVALID_HANDLE;
885 status = PCSC_SCardListReaderGroups_Internal(hContext, mszGroups, pcchGroups);
887 if (!PCSC_UnlockCardContext(hContext))
888 return SCARD_E_INVALID_HANDLE;
894static LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext, LPWSTR mszGroups,
897 LPSTR mszGroupsA =
nullptr;
898 LPSTR* pMszGroupsA = &mszGroupsA;
899 LONG status = SCARD_S_SUCCESS;
901 if (!g_PCSC.pfnSCardListReaderGroups)
902 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
904 if (!PCSC_LockCardContext(hContext))
905 return SCARD_E_INVALID_HANDLE;
907 status = PCSC_SCardListReaderGroups_Internal(hContext, (LPSTR)&mszGroupsA, pcchGroups);
909 if (status == SCARD_S_SUCCESS)
912 WCHAR* str = ConvertMszUtf8NToWCharAlloc(*pMszGroupsA, *pcchGroups, &size);
915 status = SCARD_E_NO_MEMORY;
918 *(WCHAR**)mszGroups = str;
919 *pcchGroups = (DWORD)size;
920 PCSC_AddMemoryBlock(hContext, str);
921 PCSC_SCardFreeMemory_Internal(hContext, *pMszGroupsA);
925 if (!PCSC_UnlockCardContext(hContext))
926 return SCARD_E_INVALID_HANDLE;
932static LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext, LPCSTR mszGroups,
933 LPSTR mszReaders, LPDWORD pcchReaders)
935 PCSC_LONG status = SCARD_S_SUCCESS;
936 BOOL pcchReadersAlloc = FALSE;
937 PCSC_DWORD pcsc_cchReaders = 0;
939 return SCARD_E_INVALID_PARAMETER;
941 if (!g_PCSC.pfnSCardListReaders)
942 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
946 if (*pcchReaders == SCARD_AUTOALLOCATE)
947 pcchReadersAlloc = TRUE;
949 pcsc_cchReaders = pcchReadersAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcchReaders;
951 if (pcchReadersAlloc && !g_SCardAutoAllocate)
954 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups,
nullptr, &pcsc_cchReaders);
956 if (status == SCARD_S_SUCCESS)
958 char* tmp = calloc(1, pcsc_cchReaders);
961 return SCARD_E_NO_MEMORY;
963 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, tmp, &pcsc_cchReaders);
965 if (status != SCARD_S_SUCCESS)
971 PCSC_AddMemoryBlock(hContext, tmp);
973 *(
char**)mszReaders = tmp;
978 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, &pcsc_cchReaders);
981 *pcchReaders = (DWORD)pcsc_cchReaders;
982 return PCSC_MapErrorCodeToWinSCard(status);
986static LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
989 LONG status = SCARD_S_SUCCESS;
990 BOOL nullCardContext = FALSE;
992 if (!g_PCSC.pfnSCardListReaders)
993 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
997 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
999 if (status != SCARD_S_SUCCESS)
1003 nullCardContext = TRUE;
1006 if (!PCSC_LockCardContext(hContext))
1008 status = SCARD_E_INVALID_HANDLE;
1012 status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders);
1014 if (!PCSC_UnlockCardContext(hContext))
1015 status = SCARD_E_INVALID_HANDLE;
1018 if (nullCardContext)
1020 const LONG rc = PCSC_SCardReleaseContext(hContext);
1021 if (rc != SCARD_S_SUCCESS)
1029static LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, LPCWSTR mszGroups,
1030 LPWSTR mszReaders, LPDWORD pcchReaders)
1032 LPSTR mszGroupsA =
nullptr;
1033 LPSTR mszReadersA =
nullptr;
1034 LONG status = SCARD_S_SUCCESS;
1035 BOOL nullCardContext = FALSE;
1037 if (!g_PCSC.pfnSCardListReaders)
1038 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
1042 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1044 if (status != SCARD_S_SUCCESS)
1048 nullCardContext = TRUE;
1051 if (!PCSC_LockCardContext(hContext))
1053 status = SCARD_E_INVALID_HANDLE;
1059 mszGroupsA = ConvertWCharToUtf8Alloc(mszGroups,
nullptr);
1062 status = SCARD_E_NO_MEMORY;
1072 cnv.ppc = &mszReadersA;
1074 status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, cnv.pc, pcchReaders);
1076 if (status == SCARD_S_SUCCESS)
1079 WCHAR* str = ConvertMszUtf8NToWCharAlloc(mszReadersA, *pcchReaders, &size);
1080 PCSC_SCardFreeMemory_Internal(hContext, mszReadersA);
1081 if (!str || (size > UINT32_MAX))
1083 status = SCARD_E_NO_MEMORY;
1088 *(LPWSTR*)mszReaders = str;
1089 *pcchReaders = (DWORD)size;
1090 PCSC_AddMemoryBlock(hContext, str);
1094 if (!PCSC_UnlockCardContext(hContext))
1095 status = SCARD_E_INVALID_HANDLE;
1098 if (nullCardContext)
1100 const LONG rc = PCSC_SCardReleaseContext(hContext);
1101 if (rc != SCARD_S_SUCCESS)
1112 const char* cardName;
1115static PcscKnownAtr knownAtrs[] = {
1117 { { 0x3B, 0xFD, 0x13, 0x00, 0x00, 0x81, 0x31, 0xFE, 0x15, 0x80, 0x73, 0xC0,
1118 0x21, 0xC0, 0x57, 0x59, 0x75, 0x62, 0x69, 0x4B, 0x65, 0x79, 0x40 },
1120 "NIST SP 800-73 [PIV]" },
1122 { { 0x3B, 0xFC, 0x18, 0x00, 0x00, 0x81, 0x31, 0x80, 0x45, 0x90, 0x67,
1123 0x46, 0x4A, 0x00, 0x64, 0x16, 0x06, 0xF2, 0x72, 0x7E, 0x00, 0xE0 },
1125 "PIVKey Feitian (E0)" }
1129#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a)[0])
1133static const char* findCardByAtr(LPCBYTE pbAtr)
1135 for (
size_t i = 0; i < ARRAY_LENGTH(knownAtrs); i++)
1137 if (memcmp(knownAtrs[i].atr, pbAtr, knownAtrs[i].atrLen) == 0)
1138 return knownAtrs[i].cardName;
1145static LONG WINAPI PCSC_SCardListCardsA(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, LPCBYTE pbAtr,
1146 LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
1147 CHAR* mszCards, LPDWORD pcchCards)
1149 const char* cardName =
nullptr;
1150 DWORD outputLen = 1;
1151 CHAR* output =
nullptr;
1152 BOOL autoAllocate = 0;
1154 if (!pbAtr || rgquidInterfaces || cguidInterfaceCount)
1155 return SCARD_E_UNSUPPORTED_FEATURE;
1158 return SCARD_E_INVALID_PARAMETER;
1160 autoAllocate = (*pcchCards == SCARD_AUTOALLOCATE);
1162 cardName = findCardByAtr(pbAtr);
1164 outputLen += strlen(cardName) + 1;
1166 *pcchCards = outputLen;
1169 output = malloc(outputLen);
1171 return SCARD_E_NO_MEMORY;
1173 *((LPSTR*)mszCards) = output;
1178 return SCARD_S_SUCCESS;
1180 if (*pcchCards < outputLen)
1181 return SCARD_E_INSUFFICIENT_BUFFER;
1188 size_t toCopy = strlen(cardName) + 1;
1189 memcpy(output, cardName, toCopy);
1195 return SCARD_S_SUCCESS;
1198WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardListCardsW(
1199 WINPR_ATTR_UNUSED SCARDCONTEXT hContext, LPCBYTE pbAtr, LPCGUID rgquidInterfaces,
1200 DWORD cguidInterfaceCount, WCHAR* mszCards, LPDWORD pcchCards)
1202 const char* cardName =
nullptr;
1203 DWORD outputLen = 1;
1204 WCHAR* output =
nullptr;
1205 BOOL autoAllocate = 0;
1207 if (!pbAtr || rgquidInterfaces || cguidInterfaceCount)
1208 return SCARD_E_UNSUPPORTED_FEATURE;
1211 return SCARD_E_INVALID_PARAMETER;
1213 autoAllocate = (*pcchCards == SCARD_AUTOALLOCATE);
1215 cardName = findCardByAtr(pbAtr);
1217 outputLen += strlen(cardName) + 1;
1219 *pcchCards = outputLen;
1222 output = calloc(outputLen,
sizeof(WCHAR));
1224 return SCARD_E_NO_MEMORY;
1226 *((LPWSTR*)mszCards) = output;
1231 return SCARD_S_SUCCESS;
1233 if (*pcchCards < outputLen)
1234 return SCARD_E_INSUFFICIENT_BUFFER;
1241 size_t toCopy = strlen(cardName) + 1;
1242 if (ConvertUtf8ToWChar(cardName, output, toCopy) < 0)
1243 return SCARD_F_INTERNAL_ERROR;
1249 return SCARD_S_SUCCESS;
1254PCSC_SCardListInterfacesA(SCARDCONTEXT hContext, LPCSTR szCard, LPGUID pguidInterfaces,
1255 LPDWORD pcguidInterfaces )
1257 WINPR_UNUSED(hContext);
1258 WINPR_UNUSED(szCard);
1259 WINPR_UNUSED(pguidInterfaces);
1260 WINPR_UNUSED(pcguidInterfaces);
1261 return SCARD_E_UNSUPPORTED_FEATURE;
1266PCSC_SCardListInterfacesW(SCARDCONTEXT hContext, LPCWSTR szCard, LPGUID pguidInterfaces,
1267 LPDWORD pcguidInterfaces )
1269 WINPR_UNUSED(hContext);
1270 WINPR_UNUSED(szCard);
1271 WINPR_UNUSED(pguidInterfaces);
1272 WINPR_UNUSED(pcguidInterfaces);
1273 return SCARD_E_UNSUPPORTED_FEATURE;
1276WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetProviderIdA(SCARDCONTEXT hContext,
1278 LPGUID pguidProviderId)
1280 WINPR_UNUSED(hContext);
1281 WINPR_UNUSED(szCard);
1282 WINPR_UNUSED(pguidProviderId);
1283 return SCARD_E_UNSUPPORTED_FEATURE;
1286WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetProviderIdW(SCARDCONTEXT hContext,
1288 LPGUID pguidProviderId)
1290 WINPR_UNUSED(hContext);
1291 WINPR_UNUSED(szCard);
1292 WINPR_UNUSED(pguidProviderId);
1293 return SCARD_E_UNSUPPORTED_FEATURE;
1296WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetCardTypeProviderNameA(
1297 SCARDCONTEXT hContext, LPCSTR szCardName, DWORD dwProviderId,
1299 LPDWORD pcchProvider )
1301 WINPR_UNUSED(hContext);
1302 WINPR_UNUSED(szCardName);
1303 WINPR_UNUSED(dwProviderId);
1304 WINPR_UNUSED(szProvider);
1305 WINPR_UNUSED(pcchProvider);
1306 return SCARD_E_UNSUPPORTED_FEATURE;
1309WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetCardTypeProviderNameW(
1310 SCARDCONTEXT hContext, LPCWSTR szCardName, DWORD dwProviderId,
1312 LPDWORD pcchProvider )
1314 WINPR_UNUSED(hContext);
1315 WINPR_UNUSED(szCardName);
1316 WINPR_UNUSED(dwProviderId);
1317 WINPR_UNUSED(szProvider);
1318 WINPR_UNUSED(pcchProvider);
1319 return SCARD_E_UNSUPPORTED_FEATURE;
1322WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderGroupA(SCARDCONTEXT hContext,
1325 WINPR_UNUSED(hContext);
1326 WINPR_UNUSED(szGroupName);
1327 return SCARD_E_UNSUPPORTED_FEATURE;
1330WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderGroupW(SCARDCONTEXT hContext,
1331 LPCWSTR szGroupName)
1333 WINPR_UNUSED(hContext);
1334 WINPR_UNUSED(szGroupName);
1335 return SCARD_E_UNSUPPORTED_FEATURE;
1338WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderGroupA(SCARDCONTEXT hContext,
1341 WINPR_UNUSED(hContext);
1342 WINPR_UNUSED(szGroupName);
1343 return SCARD_E_UNSUPPORTED_FEATURE;
1346WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderGroupW(SCARDCONTEXT hContext,
1347 LPCWSTR szGroupName)
1349 WINPR_UNUSED(hContext);
1350 WINPR_UNUSED(szGroupName);
1351 return SCARD_E_UNSUPPORTED_FEATURE;
1354WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderA(SCARDCONTEXT hContext,
1355 LPCSTR szReaderName,
1356 LPCSTR szDeviceName)
1358 WINPR_UNUSED(hContext);
1359 WINPR_UNUSED(szReaderName);
1360 WINPR_UNUSED(szDeviceName);
1361 return SCARD_E_UNSUPPORTED_FEATURE;
1364WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderW(SCARDCONTEXT hContext,
1365 LPCWSTR szReaderName,
1366 LPCWSTR szDeviceName)
1368 WINPR_UNUSED(hContext);
1369 WINPR_UNUSED(szReaderName);
1370 WINPR_UNUSED(szDeviceName);
1371 return SCARD_E_UNSUPPORTED_FEATURE;
1374WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderA(SCARDCONTEXT hContext,
1375 LPCSTR szReaderName)
1377 WINPR_UNUSED(hContext);
1378 WINPR_UNUSED(szReaderName);
1379 return SCARD_E_UNSUPPORTED_FEATURE;
1382WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderW(SCARDCONTEXT hContext,
1383 LPCWSTR szReaderName)
1385 WINPR_UNUSED(hContext);
1386 WINPR_UNUSED(szReaderName);
1387 return SCARD_E_UNSUPPORTED_FEATURE;
1390WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardAddReaderToGroupA(SCARDCONTEXT hContext,
1391 LPCSTR szReaderName,
1394 WINPR_UNUSED(hContext);
1395 WINPR_UNUSED(szReaderName);
1396 WINPR_UNUSED(szGroupName);
1397 return SCARD_E_UNSUPPORTED_FEATURE;
1400WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardAddReaderToGroupW(SCARDCONTEXT hContext,
1401 LPCWSTR szReaderName,
1402 LPCWSTR szGroupName)
1404 WINPR_UNUSED(hContext);
1405 WINPR_UNUSED(szReaderName);
1406 WINPR_UNUSED(szGroupName);
1407 return SCARD_E_UNSUPPORTED_FEATURE;
1410WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardRemoveReaderFromGroupA(SCARDCONTEXT hContext,
1411 LPCSTR szReaderName,
1414 WINPR_UNUSED(hContext);
1415 WINPR_UNUSED(szReaderName);
1416 WINPR_UNUSED(szGroupName);
1417 return SCARD_E_UNSUPPORTED_FEATURE;
1420WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardRemoveReaderFromGroupW(SCARDCONTEXT hContext,
1421 LPCWSTR szReaderName,
1422 LPCWSTR szGroupName)
1424 WINPR_UNUSED(hContext);
1425 WINPR_UNUSED(szReaderName);
1426 WINPR_UNUSED(szGroupName);
1427 return SCARD_E_UNSUPPORTED_FEATURE;
1430WINPR_ATTR_NODISCARD
static LONG WINAPI
1431PCSC_SCardIntroduceCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName, LPCGUID pguidPrimaryProvider,
1432 LPCGUID rgguidInterfaces, DWORD dwInterfaceCount, LPCBYTE pbAtr,
1433 LPCBYTE pbAtrMask, DWORD cbAtrLen)
1435 WINPR_UNUSED(hContext);
1436 WINPR_UNUSED(szCardName);
1437 WINPR_UNUSED(pguidPrimaryProvider);
1438 WINPR_UNUSED(rgguidInterfaces);
1439 WINPR_UNUSED(dwInterfaceCount);
1440 WINPR_UNUSED(pbAtr);
1441 WINPR_UNUSED(pbAtrMask);
1442 WINPR_UNUSED(cbAtrLen);
1443 return SCARD_E_UNSUPPORTED_FEATURE;
1446WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceCardTypeW(
1447 SCARDCONTEXT hContext, LPCWSTR szCardName, LPCGUID pguidPrimaryProvider,
1448 LPCGUID rgguidInterfaces, DWORD dwInterfaceCount, LPCBYTE pbAtr, LPCBYTE pbAtrMask,
1451 WINPR_UNUSED(hContext);
1452 WINPR_UNUSED(szCardName);
1453 WINPR_UNUSED(pguidPrimaryProvider);
1454 WINPR_UNUSED(rgguidInterfaces);
1455 WINPR_UNUSED(dwInterfaceCount);
1456 WINPR_UNUSED(pbAtr);
1457 WINPR_UNUSED(pbAtrMask);
1458 WINPR_UNUSED(cbAtrLen);
1459 return SCARD_E_UNSUPPORTED_FEATURE;
1462WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetCardTypeProviderNameA(SCARDCONTEXT hContext,
1467 WINPR_UNUSED(hContext);
1468 WINPR_UNUSED(szCardName);
1469 WINPR_UNUSED(dwProviderId);
1470 WINPR_UNUSED(szProvider);
1471 return SCARD_E_UNSUPPORTED_FEATURE;
1474WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetCardTypeProviderNameW(SCARDCONTEXT hContext,
1479 WINPR_UNUSED(hContext);
1480 WINPR_UNUSED(szCardName);
1481 WINPR_UNUSED(dwProviderId);
1482 WINPR_UNUSED(szProvider);
1483 return SCARD_E_UNSUPPORTED_FEATURE;
1486WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetCardTypeA(SCARDCONTEXT hContext,
1489 WINPR_UNUSED(hContext);
1490 WINPR_UNUSED(szCardName);
1491 return SCARD_E_UNSUPPORTED_FEATURE;
1494WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetCardTypeW(SCARDCONTEXT hContext,
1497 WINPR_UNUSED(hContext);
1498 WINPR_UNUSED(szCardName);
1499 return SCARD_E_UNSUPPORTED_FEATURE;
1502static LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPVOID pvMem)
1504 PCSC_LONG status = SCARD_S_SUCCESS;
1506 if (PCSC_RemoveMemoryBlock(hContext, pvMem))
1507 status = SCARD_S_SUCCESS;
1510 if (g_PCSC.pfnSCardFreeMemory)
1512 status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
1516 return PCSC_MapErrorCodeToWinSCard(status);
1519WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPVOID pvMem)
1521 LONG status = SCARD_S_SUCCESS;
1525 if (!PCSC_LockCardContext(hContext))
1526 return SCARD_E_INVALID_HANDLE;
1529 status = PCSC_SCardFreeMemory_Internal(hContext, pvMem);
1533 if (!PCSC_UnlockCardContext(hContext))
1534 return SCARD_E_INVALID_HANDLE;
1541static HANDLE WINAPI PCSC_SCardAccessStartedEvent(
void)
1544 SCARDCONTEXT hContext = 0;
1546 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1548 if (status != SCARD_S_SUCCESS)
1551 status = PCSC_SCardReleaseContext(hContext);
1553 if (status != SCARD_S_SUCCESS)
1556 if (!g_StartedEvent)
1558 if (!(g_StartedEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
1561 if (!SetEvent(g_StartedEvent))
1563 (void)CloseHandle(g_StartedEvent);
1568 g_StartedEventRefCount++;
1569 return g_StartedEvent;
1572static void WINAPI PCSC_SCardReleaseStartedEvent(
void)
1574 g_StartedEventRefCount--;
1576 if (g_StartedEventRefCount == 0)
1580 (void)CloseHandle(g_StartedEvent);
1581 g_StartedEvent =
nullptr;
1586WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardLocateCardsA(SCARDCONTEXT hContext,
1591 WINPR_UNUSED(hContext);
1592 WINPR_UNUSED(mszCards);
1593 WINPR_UNUSED(rgReaderStates);
1594 WINPR_UNUSED(cReaders);
1595 return SCARD_E_UNSUPPORTED_FEATURE;
1598WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardLocateCardsW(SCARDCONTEXT hContext,
1603 WINPR_UNUSED(hContext);
1604 WINPR_UNUSED(mszCards);
1605 WINPR_UNUSED(rgReaderStates);
1606 WINPR_UNUSED(cReaders);
1607 return SCARD_E_UNSUPPORTED_FEATURE;
1610WINPR_ATTR_NODISCARD
static LONG WINAPI
1611PCSC_SCardLocateCardsByATRA(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs,
1614 WINPR_UNUSED(hContext);
1615 WINPR_UNUSED(rgAtrMasks);
1616 WINPR_UNUSED(cAtrs);
1617 WINPR_UNUSED(rgReaderStates);
1618 WINPR_UNUSED(cReaders);
1619 return SCARD_E_UNSUPPORTED_FEATURE;
1622WINPR_ATTR_NODISCARD
static LONG WINAPI
1623PCSC_SCardLocateCardsByATRW(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs,
1626 WINPR_UNUSED(hContext);
1627 WINPR_UNUSED(rgAtrMasks);
1628 WINPR_UNUSED(cAtrs);
1629 WINPR_UNUSED(rgReaderStates);
1630 WINPR_UNUSED(cReaders);
1631 return SCARD_E_UNSUPPORTED_FEATURE;
1634WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetStatusChange_Internal(
1637 INT64* map =
nullptr;
1638 PCSC_DWORD cMappedReaders = 0;
1640 PCSC_LONG status = SCARD_S_SUCCESS;
1641 PCSC_DWORD pcsc_dwTimeout = (PCSC_DWORD)dwTimeout;
1642 PCSC_DWORD pcsc_cReaders = (PCSC_DWORD)cReaders;
1644 if (!g_PCSC.pfnSCardGetStatusChange)
1645 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetStatusChange");
1648 return SCARD_S_SUCCESS;
1651 pcsc_dwTimeout = pcsc_dwTimeout ? pcsc_dwTimeout : 1;
1665 map = (INT64*)calloc(pcsc_cReaders,
sizeof(INT64));
1668 return SCARD_E_NO_MEMORY;
1675 return SCARD_E_NO_MEMORY;
1679 for (PCSC_DWORD i = 0; i < pcsc_cReaders; i++)
1681 if (!g_PnP_Notification)
1684 if (!reader->szReader)
1686 if (0 == _stricmp(reader->szReader, SMARTCARD_PNP_NOTIFICATION_A))
1694 states[j].szReader = rgReaderStates[i].szReader;
1695 states[j].dwCurrentState = rgReaderStates[i].dwCurrentState;
1696 states[j].pvUserData = rgReaderStates[i].pvUserData;
1697 states[j].dwEventState = rgReaderStates[i].dwEventState;
1698 states[j].cbAtr = rgReaderStates[i].cbAtr;
1699 CopyMemory(&(states[j].rgbAtr), &(rgReaderStates[i].rgbAtr), PCSC_MAX_ATR_SIZE);
1705 if (cMappedReaders > 0)
1707 status = g_PCSC.pfnSCardGetStatusChange(hContext, pcsc_dwTimeout, states, cMappedReaders);
1711 status = SCARD_S_SUCCESS;
1714 for (PCSC_DWORD i = 0; i < pcsc_cReaders; i++)
1719 PCSC_DWORD k = (PCSC_DWORD)map[i];
1720 rgReaderStates[i].dwCurrentState = (DWORD)states[k].dwCurrentState;
1721 rgReaderStates[i].cbAtr = (DWORD)states[k].cbAtr;
1722 CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[k].rgbAtr), PCSC_MAX_ATR_SIZE);
1723 rgReaderStates[i].dwEventState = (DWORD)states[k].dwEventState;
1728 return PCSC_MapErrorCodeToWinSCard(status);
1732static LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext, DWORD dwTimeout,
1735 LONG status = SCARD_S_SUCCESS;
1737 if (!PCSC_LockCardContext(hContext))
1738 return SCARD_E_INVALID_HANDLE;
1740 status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, rgReaderStates, cReaders);
1742 if (!PCSC_UnlockCardContext(hContext))
1743 return SCARD_E_INVALID_HANDLE;
1749static LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext, DWORD dwTimeout,
1753 LONG status = SCARD_S_SUCCESS;
1755 if (!g_PCSC.pfnSCardGetStatusChange)
1756 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetStatusChange");
1758 if (!PCSC_LockCardContext(hContext))
1759 return SCARD_E_INVALID_HANDLE;
1765 if (!PCSC_UnlockCardContext(hContext))
1766 return SCARD_E_INVALID_HANDLE;
1767 return SCARD_E_NO_MEMORY;
1770 for (DWORD index = 0; index < cReaders; index++)
1775 cur->szReader = ConvertWCharToUtf8Alloc(curReader->szReader,
nullptr);
1776 cur->pvUserData = curReader->pvUserData;
1777 cur->dwCurrentState = curReader->dwCurrentState;
1778 cur->dwEventState = curReader->dwEventState;
1779 cur->cbAtr = curReader->cbAtr;
1780 CopyMemory(&(cur->rgbAtr), &(curReader->rgbAtr), ARRAYSIZE(cur->rgbAtr));
1783 status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, states, cReaders);
1785 for (DWORD index = 0; index < cReaders; index++)
1787 free((
void*)states[index].szReader);
1788 rgReaderStates[index].pvUserData = states[index].pvUserData;
1789 rgReaderStates[index].dwCurrentState = states[index].dwCurrentState;
1790 rgReaderStates[index].dwEventState = states[index].dwEventState;
1791 rgReaderStates[index].cbAtr = states[index].cbAtr;
1792 CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36);
1797 if (!PCSC_UnlockCardContext(hContext))
1798 return SCARD_E_INVALID_HANDLE;
1803static LONG WINAPI PCSC_SCardCancel(SCARDCONTEXT hContext)
1805 PCSC_LONG status = SCARD_S_SUCCESS;
1807 if (!g_PCSC.pfnSCardCancel)
1808 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardCancel");
1810 status = g_PCSC.pfnSCardCancel(hContext);
1811 return PCSC_MapErrorCodeToWinSCard(status);
1814WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnect_Internal(
1815 SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
1816 LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
1819 const char* szReaderPCSC =
nullptr;
1820 PCSC_LONG status = SCARD_S_SUCCESS;
1821 PCSC_SCARDHANDLE* pCard =
nullptr;
1822 PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD)dwShareMode;
1823 PCSC_DWORD pcsc_dwPreferredProtocols = 0;
1824 PCSC_DWORD pcsc_dwActiveProtocol = 0;
1826 if (!g_PCSC.pfnSCardConnect)
1827 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardConnect");
1829 shared = (dwShareMode == SCARD_SHARE_DIRECT) != 0;
1830 PCSC_WaitForCardAccess(hContext, 0, shared);
1831 szReaderPCSC = szReader;
1840 if (pcsc_dwShareMode == SCARD_SHARE_DIRECT && dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED)
1841 pcsc_dwPreferredProtocols = SCARD_PROTOCOL_UNDEFINED;
1843 pcsc_dwPreferredProtocols =
1844 (PCSC_DWORD)PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
1846 status = g_PCSC.pfnSCardConnect(hContext, szReaderPCSC, pcsc_dwShareMode,
1847 pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol);
1849 if (status == SCARD_S_SUCCESS)
1851 pCard = PCSC_ConnectCardHandle(hContext, *phCard);
1852 *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwActiveProtocol);
1853 pCard->shared = shared;
1856 PCSC_WaitForCardAccess(hContext, pCard->hSharedContext, shared);
1859 return PCSC_MapErrorCodeToWinSCard(status);
1862WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext, LPCSTR szReader,
1864 DWORD dwPreferredProtocols,
1865 LPSCARDHANDLE phCard,
1866 LPDWORD pdwActiveProtocol)
1868 LONG status = SCARD_S_SUCCESS;
1870 if (!PCSC_LockCardContext(hContext))
1871 return SCARD_E_INVALID_HANDLE;
1873 status = PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode, dwPreferredProtocols,
1874 phCard, pdwActiveProtocol);
1876 if (!PCSC_UnlockCardContext(hContext))
1877 return SCARD_E_INVALID_HANDLE;
1882WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext, LPCWSTR szReader,
1884 DWORD dwPreferredProtocols,
1885 LPSCARDHANDLE phCard,
1886 LPDWORD pdwActiveProtocol)
1888 LPSTR szReaderA =
nullptr;
1889 LONG status = SCARD_S_SUCCESS;
1891 if (!PCSC_LockCardContext(hContext))
1892 return SCARD_E_INVALID_HANDLE;
1896 szReaderA = ConvertWCharToUtf8Alloc(szReader,
nullptr);
1899 status = SCARD_E_INSUFFICIENT_BUFFER;
1904 status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode, dwPreferredProtocols,
1905 phCard, pdwActiveProtocol);
1909 if (!PCSC_UnlockCardContext(hContext))
1910 return SCARD_E_INVALID_HANDLE;
1915WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
1916 DWORD dwPreferredProtocols,
1917 DWORD dwInitialization,
1918 LPDWORD pdwActiveProtocol)
1920 PCSC_LONG status = SCARD_S_SUCCESS;
1921 PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD)dwShareMode;
1922 PCSC_DWORD pcsc_dwPreferredProtocols = 0;
1923 PCSC_DWORD pcsc_dwInitialization = (PCSC_DWORD)dwInitialization;
1924 PCSC_DWORD pcsc_dwActiveProtocol = 0;
1926 if (!g_PCSC.pfnSCardReconnect)
1927 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardReconnect");
1929 const BOOL shared = (dwShareMode == SCARD_SHARE_DIRECT) != 0;
1930 PCSC_WaitForCardAccess(0, hCard, shared);
1931 pcsc_dwPreferredProtocols = (PCSC_DWORD)PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
1932 status = g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode, pcsc_dwPreferredProtocols,
1933 pcsc_dwInitialization, &pcsc_dwActiveProtocol);
1935 *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwActiveProtocol);
1936 return PCSC_MapErrorCodeToWinSCard(status);
1939WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
1941 PCSC_LONG status = SCARD_S_SUCCESS;
1942 PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD)dwDisposition;
1944 if (!g_PCSC.pfnSCardDisconnect)
1945 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardDisconnect");
1947 status = g_PCSC.pfnSCardDisconnect(hCard, pcsc_dwDisposition);
1949 if (status == SCARD_S_SUCCESS)
1951 PCSC_SCARDHANDLE* pCard = PCSC_GetCardHandleData(hCard);
1952 PCSC_DisconnectCardHandle(pCard);
1955 PCSC_ReleaseCardAccess(0, hCard);
1956 return PCSC_MapErrorCodeToWinSCard(status);
1959WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardBeginTransaction(SCARDHANDLE hCard)
1961 PCSC_LONG status = SCARD_S_SUCCESS;
1962 PCSC_SCARDHANDLE* pCard =
nullptr;
1963 PCSC_SCARDCONTEXT* pContext =
nullptr;
1965 if (!g_PCSC.pfnSCardBeginTransaction)
1966 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardBeginTransaction");
1968 pCard = PCSC_GetCardHandleData(hCard);
1971 return SCARD_E_INVALID_HANDLE;
1973 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
1976 return SCARD_E_INVALID_HANDLE;
1978 if (pContext->isTransactionLocked)
1979 return SCARD_S_SUCCESS;
1981 status = g_PCSC.pfnSCardBeginTransaction(hCard);
1983 pContext->isTransactionLocked = TRUE;
1984 return PCSC_MapErrorCodeToWinSCard(status);
1987WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard,
1988 DWORD dwDisposition)
1990 PCSC_LONG status = SCARD_S_SUCCESS;
1991 PCSC_SCARDHANDLE* pCard =
nullptr;
1992 PCSC_SCARDCONTEXT* pContext =
nullptr;
1993 PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD)dwDisposition;
1995 if (!g_PCSC.pfnSCardEndTransaction)
1996 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEndTransaction");
1998 pCard = PCSC_GetCardHandleData(hCard);
2001 return SCARD_E_INVALID_HANDLE;
2003 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
2006 return SCARD_E_INVALID_HANDLE;
2008 PCSC_ReleaseCardAccess(0, hCard);
2010 if (!pContext->isTransactionLocked)
2011 return SCARD_S_SUCCESS;
2013 status = g_PCSC.pfnSCardEndTransaction(hCard, pcsc_dwDisposition);
2015 pContext->isTransactionLocked = FALSE;
2016 return PCSC_MapErrorCodeToWinSCard(status);
2019static LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
2021 WINPR_UNUSED(hCard);
2022 return SCARD_S_SUCCESS;
2029WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatus_Internal(
2030 SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
2031 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen, BOOL unicode)
2033 PCSC_SCARDHANDLE* pCard =
nullptr;
2034 SCARDCONTEXT hContext = 0;
2035 PCSC_LONG status = 0;
2036 PCSC_DWORD pcsc_cchReaderLen = 0;
2037 PCSC_DWORD pcsc_cbAtrLen = 0;
2038 PCSC_DWORD pcsc_dwState = 0;
2039 PCSC_DWORD pcsc_dwProtocol = 0;
2040 BOOL allocateReader = FALSE;
2041 BOOL allocateAtr = FALSE;
2042 LPSTR readerNames = mszReaderNames;
2044 LPSTR tReader =
nullptr;
2045 LPBYTE tATR =
nullptr;
2047 if (!g_PCSC.pfnSCardStatus)
2048 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardStatus");
2050 pCard = PCSC_GetCardHandleData(hCard);
2053 return SCARD_E_INVALID_VALUE;
2055 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2056 hContext = PCSC_GetCardContextFromHandle(hCard);
2059 return SCARD_E_INVALID_VALUE;
2061 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &pcsc_cchReaderLen,
nullptr,
nullptr,
nullptr,
2064 if (status != STATUS_SUCCESS)
2065 return PCSC_MapErrorCodeToWinSCard(status);
2067 pcsc_cchReaderLen++;
2070 pcsc_cchReaderLen *= 2;
2074 if (*pcchReaderLen == SCARD_AUTOALLOCATE)
2075 allocateReader = TRUE;
2076 else if (mszReaderNames && (*pcchReaderLen < pcsc_cchReaderLen))
2077 return SCARD_E_INSUFFICIENT_BUFFER;
2079 pcsc_cchReaderLen = *pcchReaderLen;
2084 if (*pcbAtrLen == SCARD_AUTOALLOCATE)
2086 else if (pbAtr && (*pcbAtrLen < pcsc_cbAtrLen))
2087 return SCARD_E_INSUFFICIENT_BUFFER;
2089 pcsc_cbAtrLen = *pcbAtrLen;
2092 if (allocateReader && pcsc_cchReaderLen > 0 && mszReaderNames)
2099 if (OSXVersion == 0x10100000)
2100 pcsc_cchReaderLen++;
2103 tReader = calloc(
sizeof(CHAR), pcsc_cchReaderLen + 1);
2107 status = ERROR_NOT_ENOUGH_MEMORY;
2111 readerNames = tReader;
2114 if (allocateAtr && pcsc_cbAtrLen > 0 && pbAtr)
2116 tATR = calloc(1, pcsc_cbAtrLen);
2120 status = ERROR_NOT_ENOUGH_MEMORY;
2127 status = g_PCSC.pfnSCardStatus(hCard, readerNames, &pcsc_cchReaderLen, &pcsc_dwState,
2128 &pcsc_dwProtocol, atr, &pcsc_cbAtrLen);
2130 if (status != STATUS_SUCCESS)
2135 PCSC_AddMemoryBlock(hContext, tATR);
2136 *(BYTE**)pbAtr = tATR;
2144 WCHAR* tmp = ConvertMszUtf8NToWCharAlloc(tReader, pcsc_cchReaderLen + 1, &size);
2148 status = ERROR_NOT_ENOUGH_MEMORY;
2154 PCSC_AddMemoryBlock(hContext, tmp);
2155 *(WCHAR**)mszReaderNames = tmp;
2159 tReader[pcsc_cchReaderLen - 1] =
'\0';
2160 PCSC_AddMemoryBlock(hContext, tReader);
2161 *(
char**)mszReaderNames = tReader;
2165 pcsc_dwState &= 0xFFFF;
2168 *pdwState = PCSC_ConvertCardStateToWinSCard((DWORD)pcsc_dwState, status);
2171 *pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwProtocol);
2174 *pcbAtrLen = (DWORD)pcsc_cbAtrLen;
2178 WINPR_ASSERT(pcsc_cchReaderLen < UINT32_MAX);
2179 *pcchReaderLen = (DWORD)pcsc_cchReaderLen + 1u;
2182 return (LONG)status;
2186 return (LONG)status;
2189WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, LPDWORD pdwState,
2190 LPDWORD pdwProtocol, LPBYTE pbAtr,
2193 DWORD cchReaderLen = 0;
2194 SCARDCONTEXT hContext = 0;
2195 LPSTR mszReaderNames =
nullptr;
2196 PCSC_LONG status = SCARD_S_SUCCESS;
2197 PCSC_SCARDHANDLE* pCard =
nullptr;
2198 DWORD pcsc_dwState = 0;
2199 DWORD pcsc_dwProtocol = 0;
2200 DWORD pcsc_cbAtrLen = 0;
2203 pcsc_cbAtrLen = (DWORD)*pcbAtrLen;
2205 if (!g_PCSC.pfnSCardStatus)
2206 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardStatus");
2208 pCard = PCSC_GetCardHandleData(hCard);
2211 return SCARD_E_INVALID_VALUE;
2213 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2214 hContext = PCSC_GetCardContextFromHandle(hCard);
2217 return SCARD_E_INVALID_VALUE;
2219 cchReaderLen = SCARD_AUTOALLOCATE;
2220 status = PCSC_SCardStatus_Internal(hCard, (LPSTR)&mszReaderNames, &cchReaderLen, &pcsc_dwState,
2221 &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen, FALSE);
2224 PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames);
2226 *pdwState = pcsc_dwState;
2227 *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(pcsc_dwProtocol);
2229 *pcbAtrLen = pcsc_cbAtrLen;
2230 return PCSC_MapErrorCodeToWinSCard(status);
2233WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard, LPSTR mszReaderNames,
2234 LPDWORD pcchReaderLen, LPDWORD pdwState,
2235 LPDWORD pdwProtocol, LPBYTE pbAtr,
2239 return PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol,
2240 pbAtr, pcbAtrLen, FALSE);
2243WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard, LPWSTR mszReaderNames,
2244 LPDWORD pcchReaderLen, LPDWORD pdwState,
2245 LPDWORD pdwProtocol, LPBYTE pbAtr,
2249 return PCSC_SCardStatus_Internal(hCard, (LPSTR)mszReaderNames, pcchReaderLen, pdwState,
2250 pdwProtocol, pbAtr, pcbAtrLen, TRUE);
2253WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardTransmit(
2254 SCARDHANDLE hCard,
LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength,
2257 PCSC_LONG status = SCARD_S_SUCCESS;
2258 PCSC_SCARDHANDLE* pCard =
nullptr;
2259 PCSC_DWORD cbExtraBytes = 0;
2260 BYTE* pbExtraBytes =
nullptr;
2261 BYTE* pcsc_pbExtraBytes =
nullptr;
2262 PCSC_DWORD pcsc_cbSendLength = (PCSC_DWORD)cbSendLength;
2263 PCSC_DWORD pcsc_cbRecvLength = 0;
2271 } sendPci, recvPci, inRecvPci, inSendPci;
2273 sendPci.ps =
nullptr;
2274 recvPci.ps =
nullptr;
2275 inRecvPci.lps = pioRecvPci;
2276 inSendPci.lpcs = pioSendPci;
2278 if (!g_PCSC.pfnSCardTransmit)
2279 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardTransmit");
2281 pCard = PCSC_GetCardHandleData(hCard);
2284 return SCARD_E_INVALID_VALUE;
2286 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2289 return SCARD_E_INVALID_PARAMETER;
2291 if (*pcbRecvLength == SCARD_AUTOALLOCATE)
2292 return SCARD_E_INVALID_PARAMETER;
2294 pcsc_cbRecvLength = (PCSC_DWORD)*pcbRecvLength;
2296 if (!inSendPci.lpcs)
2298 PCSC_DWORD dwState = 0;
2299 PCSC_DWORD cbAtrLen = 0;
2300 PCSC_DWORD dwProtocol = 0;
2301 PCSC_DWORD cchReaderLen = 0;
2306 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReaderLen, &dwState, &dwProtocol,
2307 nullptr, &cbAtrLen);
2309 if (status == SCARD_S_SUCCESS)
2311 if (dwProtocol == SCARD_PROTOCOL_T0)
2312 sendPci.pcs = PCSC_SCARD_PCI_T0;
2313 else if (dwProtocol == SCARD_PROTOCOL_T1)
2314 sendPci.pcs = PCSC_SCARD_PCI_T1;
2315 else if (dwProtocol == PCSC_SCARD_PROTOCOL_RAW)
2316 sendPci.pcs = PCSC_SCARD_PCI_RAW;
2325 return SCARD_E_NO_MEMORY;
2327 sendPci.ps->dwProtocol = (PCSC_DWORD)inSendPci.lpcs->dwProtocol;
2331 CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
2344 return SCARD_E_NO_MEMORY;
2347 recvPci.ps->dwProtocol = (PCSC_DWORD)inRecvPci.lps->dwProtocol;
2351 CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
2354 status = g_PCSC.pfnSCardTransmit(hCard, sendPci.ps, pbSendBuffer, pcsc_cbSendLength, recvPci.ps,
2355 pbRecvBuffer, &pcsc_cbRecvLength);
2357 *pcbRecvLength = (DWORD)pcsc_cbRecvLength;
2368 CopyMemory(pbExtraBytes, pcsc_pbExtraBytes, cbExtraBytes);
2373 return PCSC_MapErrorCodeToWinSCard(status);
2376WINPR_ATTR_NODISCARD
static LONG WINAPI
2377PCSC_SCardGetTransmitCount(SCARDHANDLE hCard, WINPR_ATTR_UNUSED LPDWORD pcTransmitCount)
2379 PCSC_SCARDHANDLE* pCard =
nullptr;
2381 pCard = PCSC_GetCardHandleData(hCard);
2384 return SCARD_E_INVALID_VALUE;
2386 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2387 return SCARD_S_SUCCESS;
2390WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
2391 LPCVOID lpInBuffer, DWORD cbInBufferSize,
2392 LPVOID lpOutBuffer, DWORD cbOutBufferSize,
2393 LPDWORD lpBytesReturned)
2395 DWORD IoCtlFunction = 0;
2396 DWORD IoCtlDeviceType = 0;
2397 BOOL getFeatureRequest = FALSE;
2398 PCSC_LONG status = SCARD_S_SUCCESS;
2399 PCSC_SCARDHANDLE* pCard =
nullptr;
2400 PCSC_DWORD pcsc_dwControlCode = 0;
2401 PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD)cbInBufferSize;
2402 PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD)cbOutBufferSize;
2403 PCSC_DWORD pcsc_BytesReturned = 0;
2405 if (!g_PCSC.pfnSCardControl)
2406 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardControl");
2408 pCard = PCSC_GetCardHandleData(hCard);
2411 return SCARD_E_INVALID_VALUE;
2413 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2424 IoCtlFunction = FUNCTION_FROM_CTL_CODE(dwControlCode);
2425 IoCtlDeviceType = DEVICE_TYPE_FROM_CTL_CODE(dwControlCode);
2427 if (dwControlCode == IOCTL_SMARTCARD_GET_FEATURE_REQUEST)
2428 getFeatureRequest = TRUE;
2430 if (IoCtlDeviceType == FILE_DEVICE_SMARTCARD)
2431 dwControlCode = PCSC_SCARD_CTL_CODE(IoCtlFunction);
2433 pcsc_dwControlCode = (PCSC_DWORD)dwControlCode;
2434 status = g_PCSC.pfnSCardControl(hCard, pcsc_dwControlCode, lpInBuffer, pcsc_cbInBufferSize,
2435 lpOutBuffer, pcsc_cbOutBufferSize, &pcsc_BytesReturned);
2437 *lpBytesReturned = (DWORD)pcsc_BytesReturned;
2439 if (getFeatureRequest)
2445 return SCARD_E_UNEXPECTED;
2449 for (DWORD index = 0; index < count; index++)
2451 if (tlv[index].length != 4)
2452 return SCARD_E_UNEXPECTED;
2456 return PCSC_MapErrorCodeToWinSCard(status);
2459WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard,
2460 DWORD dwAttrId, LPBYTE pbAttr,
2463 SCARDCONTEXT hContext = 0;
2464 BOOL pcbAttrLenAlloc = FALSE;
2465 PCSC_LONG status = SCARD_S_SUCCESS;
2466 PCSC_SCARDHANDLE* pCard =
nullptr;
2467 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
2468 PCSC_DWORD pcsc_cbAttrLen = 0;
2470 if (!g_PCSC.pfnSCardGetAttrib)
2471 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetAttrib");
2473 pCard = PCSC_GetCardHandleData(hCard);
2476 return SCARD_E_INVALID_VALUE;
2478 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2479 hContext = PCSC_GetCardContextFromHandle(hCard);
2482 return SCARD_E_INVALID_HANDLE;
2485 return SCARD_E_INVALID_PARAMETER;
2487 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2490 return SCARD_E_INVALID_PARAMETER;
2491 pcbAttrLenAlloc = TRUE;
2494 pcsc_cbAttrLen = pcbAttrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcbAttrLen;
2496 if (pcbAttrLenAlloc && !g_SCardAutoAllocate)
2499 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId,
nullptr, &pcsc_cbAttrLen);
2501 if (status == SCARD_S_SUCCESS)
2503 BYTE* tmp = (BYTE*)calloc(1, pcsc_cbAttrLen);
2506 return SCARD_E_NO_MEMORY;
2508 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, tmp, &pcsc_cbAttrLen);
2510 if (status != SCARD_S_SUCCESS)
2516 PCSC_AddMemoryBlock(hContext, tmp);
2517 *(BYTE**)pbAttr = tmp;
2522 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, pbAttr, &pcsc_cbAttrLen);
2525 if (status == SCARD_S_SUCCESS)
2526 *pcbAttrLen = (DWORD)pcsc_cbAttrLen;
2527 return PCSC_MapErrorCodeToWinSCard(status);
2530WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard,
2535 char* namePCSC =
nullptr;
2536 char* pbAttrA =
nullptr;
2538 SCARDCONTEXT hContext = PCSC_GetCardContextFromHandle(hCard);
2541 return SCARD_E_INVALID_HANDLE;
2544 return SCARD_E_INVALID_PARAMETER;
2545 const DWORD cbAttrLen = *pcbAttrLen;
2546 *pcbAttrLen = SCARD_AUTOALLOCATE;
2547 LONG status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A,
2548 (LPBYTE)&pbAttrA, pcbAttrLen);
2550 if (status != SCARD_S_SUCCESS)
2552 WCHAR* pbAttrW =
nullptr;
2554 *pcbAttrLen = SCARD_AUTOALLOCATE;
2555 status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W,
2556 (LPBYTE)&pbAttrW, pcbAttrLen);
2558 if (status != SCARD_S_SUCCESS)
2561 namePCSC = ConvertMszWCharNToUtf8Alloc(pbAttrW, *pcbAttrLen,
nullptr);
2562 PCSC_SCardFreeMemory_Internal(hContext, pbAttrW);
2566 namePCSC = strndup(pbAttrA, *pcbAttrLen);
2569 return SCARD_E_NO_MEMORY;
2571 PCSC_SCardFreeMemory_Internal(hContext, pbAttrA);
2574 size_t length = strnlen(namePCSC, *pcbAttrLen);
2576 if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W)
2579 WCHAR* friendlyNameW = ConvertUtf8NToWCharAlloc(namePCSC, length, &size);
2583 status = SCARD_E_NO_MEMORY;
2588 if (cbAttrLen == SCARD_AUTOALLOCATE)
2590 WINPR_ASSERT(length <= UINT32_MAX /
sizeof(WCHAR));
2591 *(WCHAR**)pbAttr = friendlyNameW;
2592 *pcbAttrLen = (UINT32)length *
sizeof(WCHAR);
2593 PCSC_AddMemoryBlock(hContext, friendlyNameW);
2597 const size_t wlen = length *
sizeof(WCHAR);
2598 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(uint32_t, wlen);
2599 if ((wlen > cbAttrLen) && pbAttr)
2600 status = SCARD_E_INSUFFICIENT_BUFFER;
2602 CopyMemory(pbAttr, friendlyNameW, (length *
sizeof(WCHAR)));
2604 free(friendlyNameW);
2612 if (cbAttrLen == SCARD_AUTOALLOCATE)
2614 *(CHAR**)pbAttr = namePCSC;
2615 WINPR_ASSERT(length <= UINT32_MAX);
2616 *pcbAttrLen = (UINT32)length;
2617 PCSC_AddMemoryBlock(hContext, namePCSC);
2621 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(uint32_t, length);
2622 if ((length > cbAttrLen) && pbAttr)
2623 status = SCARD_E_INSUFFICIENT_BUFFER;
2625 CopyMemory(pbAttr, namePCSC, length);
2634static LONG PCSC_ReadDeviceSystemNameGet(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2635 DWORD dwAttrId, LPBYTE* pbAttr, LPDWORD pcbAttrLen)
2637 PCSC_DWORD cchReader = 0;
2638 PCSC_DWORD cbAtr = 0;
2639 PCSC_DWORD dwState = 0;
2640 PCSC_DWORD dwProtocol = 0;
2642 const PCSC_LONG rc =
2643 g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReader, &dwState, &dwProtocol,
nullptr, &cbAtr);
2644 if (rc != SCARD_S_SUCCESS)
2647 void* tmp = calloc(cchReader + 1,
sizeof(CHAR));
2649 return SCARD_E_NO_MEMORY;
2650 const PCSC_LONG rc2 =
2651 g_PCSC.pfnSCardStatus(hCard, tmp, &cchReader, &dwState, &dwProtocol,
nullptr, &cbAtr);
2652 if (rc2 != SCARD_S_SUCCESS)
2658 if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2661 void* data = ConvertMszUtf8NToWCharAlloc(tmp, cchReader, &len);
2665 return SCARD_E_NO_MEMORY;
2667 len *=
sizeof(WCHAR);
2669 cchReader = WINPR_ASSERTING_INT_CAST(PCSC_DWORD, len);
2675 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, cchReader);
2676 return SCARD_S_SUCCESS;
2679static LONG PCSC_ReadDeviceSystemName(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2680 DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
2682 BYTE* tmp =
nullptr;
2683 DWORD cbAttrLen = 0;
2684 const LONG rc = PCSC_ReadDeviceSystemNameGet(hContext, hCard, dwAttrId, &tmp, &cbAttrLen);
2685 if (rc != SCARD_S_SUCCESS)
2688 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2690 if (!PCSC_AddMemoryBlock(hContext, tmp))
2693 return SCARD_E_NO_MEMORY;
2696 *pcbAttrLen = cbAttrLen;
2697 *(BYTE**)pbAttr = tmp;
2698 return SCARD_S_SUCCESS;
2702 memcpy(pbAttr, tmp, MIN(cbAttrLen, *pcbAttrLen));
2707 if (cbAttrLen > *pcbAttrLen)
2708 return SCARD_E_INSUFFICIENT_BUFFER;
2711 *pcbAttrLen = cbAttrLen;
2713 return SCARD_S_SUCCESS;
2716WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
2717 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2719 DWORD cbAttrLen = 0;
2720 SCARDCONTEXT hContext = 0;
2721 BOOL pcbAttrLenAlloc = FALSE;
2722 PCSC_LONG status = SCARD_S_SUCCESS;
2724 if (
nullptr == pcbAttrLen)
2725 return SCARD_E_INVALID_PARAMETER;
2727 cbAttrLen = *pcbAttrLen;
2729 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2731 if (
nullptr == pbAttr)
2732 return SCARD_E_INVALID_PARAMETER;
2734 pcbAttrLenAlloc = TRUE;
2735 *(BYTE**)pbAttr =
nullptr;
2743 if (*pcbAttrLen > PCSC_MAX_BUFFER_SIZE)
2744 *pcbAttrLen = PCSC_MAX_BUFFER_SIZE;
2747 hContext = PCSC_GetCardContextFromHandle(hCard);
2750 return SCARD_E_INVALID_HANDLE;
2752 if ((dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) ||
2753 (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W))
2755 return PCSC_SCardGetAttrib_FriendlyName(hCard, dwAttrId, pbAttr, pcbAttrLen);
2758 status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen);
2760 if (status == SCARD_S_SUCCESS)
2762 if (dwAttrId == SCARD_ATTR_VENDOR_NAME)
2766 const char* vendorName =
nullptr;
2773 if (pcbAttrLenAlloc)
2774 vendorName = (
char*)*(BYTE**)pbAttr;
2776 vendorName = (
char*)pbAttr;
2780 size_t len = strnlen(vendorName, *pcbAttrLen);
2781 WINPR_ASSERT(len < UINT32_MAX);
2782 *pcbAttrLen = (DWORD)len + 1;
2791 if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
2793 if (!pcbAttrLenAlloc)
2795 PCSC_DWORD dwState = 0;
2796 PCSC_DWORD cbAtrLen = 0;
2797 PCSC_DWORD dwProtocol = 0;
2798 PCSC_DWORD cchReaderLen = 0;
2799 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReaderLen, &dwState, &dwProtocol,
2800 nullptr, &cbAtrLen);
2802 if (status == SCARD_S_SUCCESS)
2804 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2805 return SCARD_E_INSUFFICIENT_BUFFER;
2808 *(DWORD*)pbAttr = PCSC_ConvertProtocolsToWinSCard(dwProtocol);
2809 *pcbAttrLen =
sizeof(DWORD);
2813 else if (dwAttrId == SCARD_ATTR_CHANNEL_ID)
2815 if (!pcbAttrLenAlloc)
2817 UINT32 channelType = 0x20;
2818 UINT32 channelNumber = 0;
2820 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2821 return SCARD_E_INSUFFICIENT_BUFFER;
2823 status = SCARD_S_SUCCESS;
2825 *(DWORD*)pbAttr = (channelType << 16u) | channelNumber;
2826 *pcbAttrLen =
sizeof(DWORD);
2829 else if (dwAttrId == SCARD_ATTR_VENDOR_IFD_TYPE)
2832 else if (dwAttrId == SCARD_ATTR_DEFAULT_CLK)
2835 else if (dwAttrId == SCARD_ATTR_DEFAULT_DATA_RATE)
2838 else if (dwAttrId == SCARD_ATTR_MAX_CLK)
2841 else if (dwAttrId == SCARD_ATTR_MAX_DATA_RATE)
2844 else if (dwAttrId == SCARD_ATTR_MAX_IFSD)
2847 else if (dwAttrId == SCARD_ATTR_CHARACTERISTICS)
2850 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_A)
2852 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
2854 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2856 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
2858 else if (dwAttrId == SCARD_ATTR_DEVICE_UNIT)
2861 else if (dwAttrId == SCARD_ATTR_POWER_MGMT_SUPPORT)
2864 else if (dwAttrId == SCARD_ATTR_CURRENT_CLK)
2867 else if (dwAttrId == SCARD_ATTR_CURRENT_F)
2870 else if (dwAttrId == SCARD_ATTR_CURRENT_D)
2873 else if (dwAttrId == SCARD_ATTR_CURRENT_N)
2876 else if (dwAttrId == SCARD_ATTR_CURRENT_CWT)
2879 else if (dwAttrId == SCARD_ATTR_CURRENT_BWT)
2882 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSC)
2885 else if (dwAttrId == SCARD_ATTR_CURRENT_EBC_ENCODING)
2888 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSD)
2891 else if (dwAttrId == SCARD_ATTR_ICC_TYPE_PER_ATR)
2896 return WINPR_ASSERTING_INT_CAST(LONG, status);
2899WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
2900 LPCBYTE pbAttr, DWORD cbAttrLen)
2902 PCSC_LONG status = SCARD_S_SUCCESS;
2903 PCSC_SCARDHANDLE* pCard =
nullptr;
2904 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
2905 PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD)cbAttrLen;
2907 if (!g_PCSC.pfnSCardSetAttrib)
2908 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardSetAttrib");
2910 pCard = PCSC_GetCardHandleData(hCard);
2913 return SCARD_E_INVALID_VALUE;
2915 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2916 status = g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
2917 return PCSC_MapErrorCodeToWinSCard(status);
2920WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc)
2922 WINPR_UNUSED(pDlgStruc);
2924 return SCARD_E_UNSUPPORTED_FEATURE;
2927WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pDlgStruc)
2929 WINPR_UNUSED(pDlgStruc);
2930 return SCARD_E_UNSUPPORTED_FEATURE;
2933WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_GetOpenCardNameA(
LPOPENCARDNAMEA pDlgStruc)
2935 WINPR_UNUSED(pDlgStruc);
2936 return SCARD_E_UNSUPPORTED_FEATURE;
2939WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_GetOpenCardNameW(
LPOPENCARDNAMEW pDlgStruc)
2941 WINPR_UNUSED(pDlgStruc);
2942 return SCARD_E_UNSUPPORTED_FEATURE;
2945WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardDlgExtendedError(
void)
2948 return SCARD_E_UNSUPPORTED_FEATURE;
2952static char* card_id_and_name_a(
const UUID* CardIdentifier, LPCSTR LookupName)
2954 WINPR_ASSERT(CardIdentifier);
2955 WINPR_ASSERT(LookupName);
2957 size_t len = strlen(LookupName) + 34;
2958 char*
id = malloc(len);
2962 (void)snprintf(
id, len,
"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X\\%s",
2963 CardIdentifier->Data1, CardIdentifier->Data2, CardIdentifier->Data3,
2964 CardIdentifier->Data4[0], CardIdentifier->Data4[1], CardIdentifier->Data4[2],
2965 CardIdentifier->Data4[3], CardIdentifier->Data4[4], CardIdentifier->Data4[5],
2966 CardIdentifier->Data4[6], CardIdentifier->Data4[7], LookupName);
2971static char* card_id_and_name_w(
const UUID* CardIdentifier, LPCWSTR LookupName)
2973 char* res =
nullptr;
2974 char* tmp = ConvertWCharToUtf8Alloc(LookupName,
nullptr);
2977 res = card_id_and_name_a(CardIdentifier, tmp);
2982WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReadCacheA(SCARDCONTEXT hContext,
2983 UUID* CardIdentifier,
2984 DWORD FreshnessCounter,
2985 LPSTR LookupName, PBYTE Data,
2988 PCSC_CACHE_ITEM* data =
nullptr;
2989 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
2991 return SCARD_E_INVALID_HANDLE;
2993 char*
id = card_id_and_name_a(CardIdentifier, LookupName);
2995 data = HashTable_GetItemValue(ctx->cache,
id);
3000 return SCARD_W_CACHE_ITEM_NOT_FOUND;
3003 if (FreshnessCounter != data->freshness)
3006 return SCARD_W_CACHE_ITEM_STALE;
3009 if (*DataLen == SCARD_AUTOALLOCATE)
3011 BYTE* mem = calloc(1, data->len);
3013 return SCARD_E_NO_MEMORY;
3015 if (!PCSC_AddMemoryBlock(hContext, mem))
3018 return SCARD_E_NO_MEMORY;
3021 memcpy(mem, data->data, data->len);
3022 *(BYTE**)Data = mem;
3025 memcpy(Data, data->data, data->len);
3026 *DataLen = data->len;
3027 return SCARD_S_SUCCESS;
3030WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReadCacheW(SCARDCONTEXT hContext,
3031 UUID* CardIdentifier,
3032 DWORD FreshnessCounter,
3033 LPWSTR LookupName, PBYTE Data,
3036 PCSC_CACHE_ITEM* data =
nullptr;
3037 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3039 return SCARD_E_INVALID_HANDLE;
3041 char*
id = card_id_and_name_w(CardIdentifier, LookupName);
3043 data = HashTable_GetItemValue(ctx->cache,
id);
3049 return SCARD_W_CACHE_ITEM_NOT_FOUND;
3052 if (FreshnessCounter != data->freshness)
3055 return SCARD_W_CACHE_ITEM_STALE;
3058 if (*DataLen == SCARD_AUTOALLOCATE)
3060 BYTE* mem = calloc(1, data->len);
3062 return SCARD_E_NO_MEMORY;
3064 if (!PCSC_AddMemoryBlock(hContext, mem))
3067 return SCARD_E_NO_MEMORY;
3070 memcpy(mem, data->data, data->len);
3071 *(BYTE**)Data = mem;
3074 memcpy(Data, data->data, data->len);
3075 *DataLen = data->len;
3076 return SCARD_S_SUCCESS;
3079WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardWriteCacheA(SCARDCONTEXT hContext,
3080 UUID* CardIdentifier,
3081 DWORD FreshnessCounter,
3082 LPSTR LookupName, PBYTE Data,
3085 PCSC_CACHE_ITEM* data =
nullptr;
3086 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3090 return SCARD_E_FILE_NOT_FOUND;
3092 id = card_id_and_name_a(CardIdentifier, LookupName);
3095 return SCARD_E_NO_MEMORY;
3097 data = malloc(
sizeof(PCSC_CACHE_ITEM));
3101 return SCARD_E_NO_MEMORY;
3103 data->data = calloc(DataLen, 1);
3108 return SCARD_E_NO_MEMORY;
3110 data->len = DataLen;
3111 data->freshness = FreshnessCounter;
3112 memcpy(data->data, Data, data->len);
3114 HashTable_Remove(ctx->cache,
id);
3115 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
3120 pcsc_cache_item_free(data);
3121 return SCARD_E_NO_MEMORY;
3125 return SCARD_S_SUCCESS;
3128WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardWriteCacheW(SCARDCONTEXT hContext,
3129 UUID* CardIdentifier,
3130 DWORD FreshnessCounter,
3131 LPWSTR LookupName, PBYTE Data,
3134 PCSC_CACHE_ITEM* data =
nullptr;
3135 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3138 return SCARD_E_FILE_NOT_FOUND;
3140 id = card_id_and_name_w(CardIdentifier, LookupName);
3143 return SCARD_E_NO_MEMORY;
3145 data = malloc(
sizeof(PCSC_CACHE_ITEM));
3149 return SCARD_E_NO_MEMORY;
3151 data->data = malloc(DataLen);
3156 return SCARD_E_NO_MEMORY;
3158 data->len = DataLen;
3159 data->freshness = FreshnessCounter;
3160 memcpy(data->data, Data, data->len);
3162 HashTable_Remove(ctx->cache,
id);
3163 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
3168 pcsc_cache_item_free(data);
3169 return SCARD_E_NO_MEMORY;
3173 return SCARD_S_SUCCESS;
3176WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetReaderIconA(
3177 SCARDCONTEXT hContext, LPCSTR szReaderName,
3178 LPBYTE pbIcon , LPDWORD pcbIcon)
3180 WINPR_UNUSED(hContext);
3181 WINPR_UNUSED(szReaderName);
3182 WINPR_UNUSED(pbIcon);
3183 WINPR_ASSERT(pcbIcon);
3185 return SCARD_E_UNSUPPORTED_FEATURE;
3188WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetReaderIconW(
3189 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3190 LPBYTE pbIcon , LPDWORD pcbIcon)
3192 WINPR_UNUSED(hContext);
3193 WINPR_UNUSED(szReaderName);
3194 WINPR_UNUSED(pbIcon);
3195 WINPR_ASSERT(pcbIcon);
3197 return SCARD_E_UNSUPPORTED_FEATURE;
3200WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetDeviceTypeIdA(SCARDCONTEXT hContext,
3201 LPCSTR szReaderName,
3202 LPDWORD pdwDeviceTypeId)
3204 WINPR_UNUSED(hContext);
3205 WINPR_UNUSED(szReaderName);
3206 WINPR_UNUSED(pdwDeviceTypeId);
3207 if (pdwDeviceTypeId)
3208 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3209 return SCARD_S_SUCCESS;
3213static LONG WINAPI PCSC_SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
3214 LPDWORD pdwDeviceTypeId)
3216 WINPR_UNUSED(hContext);
3217 WINPR_UNUSED(szReaderName);
3218 if (pdwDeviceTypeId)
3219 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3220 return SCARD_S_SUCCESS;
3224static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdA(
3225 SCARDCONTEXT hContext, LPCSTR szReaderName,
3226 LPSTR szDeviceInstanceId ,
3227 LPDWORD pcchDeviceInstanceId )
3229 WINPR_UNUSED(hContext);
3230 WINPR_UNUSED(szReaderName);
3231 WINPR_UNUSED(szDeviceInstanceId);
3232 WINPR_UNUSED(pcchDeviceInstanceId);
3233 return SCARD_E_UNSUPPORTED_FEATURE;
3237static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdW(
3238 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3239 LPWSTR szDeviceInstanceId ,
3240 LPDWORD pcchDeviceInstanceId )
3242 WINPR_UNUSED(hContext);
3243 WINPR_UNUSED(szReaderName);
3244 WINPR_UNUSED(szDeviceInstanceId);
3245 WINPR_UNUSED(pcchDeviceInstanceId);
3246 return SCARD_E_UNSUPPORTED_FEATURE;
3250static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdA(
3251 SCARDCONTEXT hContext, LPCSTR szDeviceInstanceId,
3253 LPDWORD pcchReaders )
3255 WINPR_UNUSED(hContext);
3256 WINPR_UNUSED(szDeviceInstanceId);
3257 WINPR_UNUSED(mszReaders);
3258 WINPR_UNUSED(pcchReaders);
3259 return SCARD_E_UNSUPPORTED_FEATURE;
3263static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdW(
3264 SCARDCONTEXT hContext, LPCWSTR szDeviceInstanceId,
3266 LPDWORD pcchReaders )
3268 WINPR_UNUSED(hContext);
3269 WINPR_UNUSED(szDeviceInstanceId);
3270 WINPR_UNUSED(mszReaders);
3271 WINPR_UNUSED(pcchReaders);
3272 return SCARD_E_UNSUPPORTED_FEATURE;
3276static LONG WINAPI PCSC_SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent)
3279 WINPR_UNUSED(hContext);
3280 WINPR_UNUSED(dwEvent);
3281 return SCARD_E_UNSUPPORTED_FEATURE;
3286unsigned int determineMacOSXVersion(
void)
3290 char* kernelVersion =
nullptr;
3291 char* tok =
nullptr;
3292 unsigned int version = 0;
3293 long majorVersion = 0;
3294 long minorVersion = 0;
3295 long patchVersion = 0;
3297 char* context =
nullptr;
3299 mib[1] = KERN_OSRELEASE;
3301 if (sysctl(mib, 2,
nullptr, &len,
nullptr, 0) != 0)
3304 kernelVersion = calloc(len,
sizeof(
char));
3309 if (sysctl(mib, 2, kernelVersion, &len,
nullptr, 0) != 0)
3311 free(kernelVersion);
3315 tok = strtok_s(kernelVersion,
".", &context);
3323 majorVersion = strtol(tok,
nullptr, 0);
3331 minorVersion = strtol(tok,
nullptr, 0);
3339 patchVersion = strtol(tok,
nullptr, 0);
3347 tok = strtok_s(
nullptr,
".", &context);
3354 if (majorVersion < 5)
3356 if (minorVersion < 4)
3357 version = 0x10000000;
3359 version = 0x10010000;
3363 switch (majorVersion)
3366 version = 0x10010000;
3370 version = 0x10020000;
3374 version = 0x10030000;
3378 version = 0x10040000;
3382 version = 0x10050000;
3386 version = 0x10060000;
3390 version = 0x10070000;
3394 version = 0x10080000;
3398 version = 0x10090000;
3402 version = 0x10100000;
3406 version |= (minorVersion << 8) | (patchVersion);
3410 free(kernelVersion);
3419 PCSC_SCardEstablishContext,
3420 PCSC_SCardReleaseContext,
3421 PCSC_SCardIsValidContext,
3422 PCSC_SCardListReaderGroupsA,
3423 PCSC_SCardListReaderGroupsW,
3424 PCSC_SCardListReadersA,
3425 PCSC_SCardListReadersW,
3426 PCSC_SCardListCardsA,
3427 PCSC_SCardListCardsW,
3428 PCSC_SCardListInterfacesA,
3429 PCSC_SCardListInterfacesW,
3430 PCSC_SCardGetProviderIdA,
3431 PCSC_SCardGetProviderIdW,
3432 PCSC_SCardGetCardTypeProviderNameA,
3433 PCSC_SCardGetCardTypeProviderNameW,
3434 PCSC_SCardIntroduceReaderGroupA,
3435 PCSC_SCardIntroduceReaderGroupW,
3436 PCSC_SCardForgetReaderGroupA,
3437 PCSC_SCardForgetReaderGroupW,
3438 PCSC_SCardIntroduceReaderA,
3439 PCSC_SCardIntroduceReaderW,
3440 PCSC_SCardForgetReaderA,
3441 PCSC_SCardForgetReaderW,
3442 PCSC_SCardAddReaderToGroupA,
3443 PCSC_SCardAddReaderToGroupW,
3444 PCSC_SCardRemoveReaderFromGroupA,
3445 PCSC_SCardRemoveReaderFromGroupW,
3446 PCSC_SCardIntroduceCardTypeA,
3447 PCSC_SCardIntroduceCardTypeW,
3448 PCSC_SCardSetCardTypeProviderNameA,
3449 PCSC_SCardSetCardTypeProviderNameW,
3450 PCSC_SCardForgetCardTypeA,
3451 PCSC_SCardForgetCardTypeW,
3452 PCSC_SCardFreeMemory,
3453 PCSC_SCardAccessStartedEvent,
3454 PCSC_SCardReleaseStartedEvent,
3455 PCSC_SCardLocateCardsA,
3456 PCSC_SCardLocateCardsW,
3457 PCSC_SCardLocateCardsByATRA,
3458 PCSC_SCardLocateCardsByATRW,
3459 PCSC_SCardGetStatusChangeA,
3460 PCSC_SCardGetStatusChangeW,
3464 PCSC_SCardReconnect,
3465 PCSC_SCardDisconnect,
3466 PCSC_SCardBeginTransaction,
3467 PCSC_SCardEndTransaction,
3468 PCSC_SCardCancelTransaction,
3473 PCSC_SCardGetTransmitCount,
3475 PCSC_SCardGetAttrib,
3476 PCSC_SCardSetAttrib,
3477 PCSC_SCardUIDlgSelectCardA,
3478 PCSC_SCardUIDlgSelectCardW,
3479 PCSC_GetOpenCardNameA,
3480 PCSC_GetOpenCardNameW,
3481 PCSC_SCardDlgExtendedError,
3482 PCSC_SCardReadCacheA,
3483 PCSC_SCardReadCacheW,
3484 PCSC_SCardWriteCacheA,
3485 PCSC_SCardWriteCacheW,
3486 PCSC_SCardGetReaderIconA,
3487 PCSC_SCardGetReaderIconW,
3488 PCSC_SCardGetDeviceTypeIdA,
3489 PCSC_SCardGetDeviceTypeIdW,
3490 PCSC_SCardGetReaderDeviceInstanceIdA,
3491 PCSC_SCardGetReaderDeviceInstanceIdW,
3492 PCSC_SCardListReadersWithDeviceInstanceIdA,
3493 PCSC_SCardListReadersWithDeviceInstanceIdW,
3499 return &PCSC_SCardApiFunctionTable;
3502int PCSC_InitializeSCardApi(
void)
3505 SetEnvironmentVariableA(
"PCSCLITE_NO_BLOCKING",
"1");
3507 g_PCSCModule = LoadLibraryX(
"/System/Library/Frameworks/PCSC.framework/PCSC");
3508 OSXVersion = determineMacOSXVersion();
3510 if (OSXVersion == 0)
3514 g_PCSCModule = LoadLibraryA(
"libpcsclite.so.1");
3517 g_PCSCModule = LoadLibraryA(
"libpcsclite.so");
3526#undef SCardListReaderGroups
3527#undef SCardListReaders
3528#undef SCardListCards
3529#undef SCardListInterfaces
3530#undef SCardGetProviderId
3531#undef SCardGetCardTypeProviderName
3532#undef SCardIntroduceReaderGroup
3533#undef SCardForgetReaderGroup
3534#undef SCardIntroduceReader
3535#undef SCardForgetReader
3536#undef SCardAddReaderToGroup
3537#undef SCardRemoveReaderFromGroup
3538#undef SCardIntroduceCardType
3539#undef SCardSetCardTypeProviderName
3540#undef SCardForgetCardType
3541#undef SCardLocateCards
3542#undef SCardLocateCardsByATR
3543#undef SCardGetStatusChange
3546#undef SCardUIDlgSelectCard
3547#undef GetOpenCardName
3548#undef SCardReadCache
3549#undef SCardWriteCache
3550#undef SCardGetReaderIcon
3551#undef SCardGetDeviceTypeId
3552#undef SCardGetReaderDeviceInstanceId
3553#undef SCardListReadersWithDeviceInstanceId
3555 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEstablishContext);
3556 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReleaseContext);
3557 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardIsValidContext);
3558 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardConnect);
3559 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReconnect);
3560 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardDisconnect);
3561 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardBeginTransaction);
3562 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEndTransaction);
3563 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardStatus);
3564 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetStatusChange);
3568 if (OSXVersion >= 0x10050600)
3570 WINSCARD_LOAD_PROC_EX(g_PCSCModule, g_PCSC, SCardControl, SCardControl132);
3574 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3577 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3579 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardTransmit);
3580 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaderGroups);
3581 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaders);
3582 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardCancel);
3583 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetAttrib);
3584 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardSetAttrib);
3585 g_PCSC.pfnSCardFreeMemory =
nullptr;
3587 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardFreeMemory);
3590 if (g_PCSC.pfnSCardFreeMemory)
3591 g_SCardAutoAllocate = TRUE;
3593#ifdef DISABLE_PCSC_SCARD_AUTOALLOCATE
3594 g_PCSC.pfnSCardFreeMemory =
nullptr;
3595 g_SCardAutoAllocate = FALSE;
3598 g_PnP_Notification = FALSE;
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree