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;
216 BOOL isTransactionLocked;
217 SCARDCONTEXT hSharedContext;
219 SCARDCONTEXT hPrivateContext;
224static HMODULE g_PCSCModule =
nullptr;
225static PCSCFunctionTable g_PCSC = WINPR_C_ARRAY_INIT;
227static HANDLE g_StartedEvent =
nullptr;
228static int g_StartedEventRefCount = 0;
230static BOOL g_SCardAutoAllocate = FALSE;
231static BOOL g_PnP_Notification = TRUE;
234static unsigned int OSXVersion = 0;
237static wListDictionary* g_CardHandles =
nullptr;
238static wListDictionary* g_CardContexts =
nullptr;
239static wListDictionary* g_MemoryBlocks =
nullptr;
241static wHashTable* g_TransmitCounts =
nullptr;
242static INIT_ONCE g_CardHandleInitializer = INIT_ONCE_STATIC_INIT;
244static const char SMARTCARD_PNP_NOTIFICATION_A[] =
"\\\\?PnP?\\Notification";
253static void clearHandles(
void)
255 ListDictionary_Free(g_CardHandles);
256 ListDictionary_Free(g_CardContexts);
257 ListDictionary_Free(g_MemoryBlocks);
258 HashTable_Free(g_TransmitCounts);
260 g_CardHandles =
nullptr;
261 g_CardContexts =
nullptr;
262 g_MemoryBlocks =
nullptr;
263 g_TransmitCounts =
nullptr;
267static wListDictionary* setupWithValueObjectFree(BOOL key)
269 wListDictionary* list = ListDictionary_New(TRUE);
274 wObject* obj = ListDictionary_ValueObject(list);
276 obj = ListDictionary_KeyObject(list);
283static void cardContextFree(PCSC_SCARDCONTEXT* pContext)
288 DeleteCriticalSection(&(pContext->lock));
289 HashTable_Free(pContext->cache);
293static void cardContextFreeVoid(
void* obj)
295 PCSC_SCARDCONTEXT* pContext = obj;
296 cardContextFree(pContext);
299static void cardHandleFreeVoid(
void* obj)
301 PCSC_SCARDHANDLE* pCard = obj;
305 free(pCard->szReader);
310static BOOL initializeHandles(WINPR_ATTR_UNUSED
PINIT_ONCE InitOnce,
311 WINPR_ATTR_UNUSED PVOID Parameter, WINPR_ATTR_UNUSED PVOID* Context)
313 (void)atexit(clearHandles);
314 g_CardHandles = ListDictionary_New(TRUE);
318 wObject* obj = ListDictionary_ValueObject(g_CardHandles);
323 g_TransmitCounts = HashTable_New(TRUE);
324 if (!g_TransmitCounts || !HashTable_SetupForStringData(g_TransmitCounts, FALSE))
326 g_CardContexts = ListDictionary_New(TRUE);
330 wObject* obj = ListDictionary_ValueObject(g_CardContexts);
336 g_MemoryBlocks = setupWithValueObjectFree(TRUE);
337 return g_MemoryBlocks !=
nullptr;
341static BOOL init(
void)
343 return InitOnceExecuteOnce(&g_CardHandleInitializer, initializeHandles,
nullptr,
nullptr);
348static uintptr_t PCSC_TransmitCountValue(
const char* szReader)
355 cnv.data = HashTable_GetItemValue(g_TransmitCounts, szReader);
360static void PCSC_AddTransmitCount(
const char* szReader)
362 if (!szReader || !init())
365 HashTable_Lock(g_TransmitCounts);
366 const uintptr_t count = PCSC_TransmitCountValue(szReader) + 1;
367 if (!HashTable_SetItemValue(g_TransmitCounts, szReader, (
void*)count))
369 if (!HashTable_Insert(g_TransmitCounts, szReader, (
void*)count))
370 WLog_WARN(TAG,
"failed to update transmit count of '%s'", szReader);
372 HashTable_Unlock(g_TransmitCounts);
376static DWORD PCSC_GetTransmitCountOfReader(
const char* szReader)
378 if (!szReader || !init())
381 const uintptr_t count = PCSC_TransmitCountValue(szReader);
382 return (DWORD)MIN(count, UINT32_MAX);
385static void PCSC_ResetTransmitCount(
const char* szReader)
387 if (!szReader || !init())
390 (void)HashTable_Remove(g_TransmitCounts, szReader);
393static LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPVOID pvMem);
396static LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1,
398 LPSCARDCONTEXT phContext);
401static LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext);
404static LONG PCSC_SCard_LogError(
const char* what)
406 WLog_WARN(TAG,
"Missing function pointer %s=nullptr", what);
407 return SCARD_E_UNSUPPORTED_FEATURE;
411static LONG PCSC_MapErrorCodeToWinSCard(PCSC_LONG errorCode)
421 if (errorCode != SCARD_S_SUCCESS)
423 if (errorCode == SCARD_E_UNEXPECTED)
424 errorCode = SCARD_E_UNSUPPORTED_FEATURE;
427 return (LONG)errorCode;
431static DWORD PCSC_ConvertCardStateToWinSCard(DWORD dwCardState, PCSC_LONG status)
449 if (status == SCARD_S_SUCCESS)
451 if ((dwCardState & PCSC_SCARD_NEGOTIABLE) || (dwCardState & PCSC_SCARD_SPECIFIC))
452 return SCARD_SPECIFIC;
455 if (dwCardState & PCSC_SCARD_POWERED)
456 return SCARD_POWERED;
458 if (dwCardState & PCSC_SCARD_NEGOTIABLE)
459 return SCARD_NEGOTIABLE;
461 if (dwCardState & PCSC_SCARD_SPECIFIC)
462 return SCARD_SPECIFIC;
464 if (dwCardState & PCSC_SCARD_ABSENT)
467 if (dwCardState & PCSC_SCARD_PRESENT)
468 return SCARD_PRESENT;
470 if (dwCardState & PCSC_SCARD_SWALLOWED)
471 return SCARD_SWALLOWED;
473 if (dwCardState & PCSC_SCARD_UNKNOWN)
474 return SCARD_UNKNOWN;
476 return SCARD_UNKNOWN;
480static DWORD PCSC_ConvertProtocolsToWinSCard(PCSC_DWORD dwProtocols)
486 if (dwProtocols & PCSC_SCARD_PROTOCOL_RAW)
488 dwProtocols &= ~PCSC_SCARD_PROTOCOL_RAW;
489 dwProtocols |= SCARD_PROTOCOL_RAW;
492 if (dwProtocols & PCSC_SCARD_PROTOCOL_T15)
494 dwProtocols &= ~PCSC_SCARD_PROTOCOL_T15;
497 return (DWORD)dwProtocols;
501static DWORD PCSC_ConvertProtocolsFromWinSCard(DWORD dwProtocols)
507 if (dwProtocols & SCARD_PROTOCOL_RAW)
509 dwProtocols &= ~SCARD_PROTOCOL_RAW;
510 dwProtocols |= PCSC_SCARD_PROTOCOL_RAW;
513 if (dwProtocols & SCARD_PROTOCOL_DEFAULT)
515 dwProtocols &= ~SCARD_PROTOCOL_DEFAULT;
518 if (dwProtocols == SCARD_PROTOCOL_UNDEFINED)
520 dwProtocols = SCARD_PROTOCOL_Tx;
527static PCSC_SCARDCONTEXT* PCSC_GetCardContextData(SCARDCONTEXT hContext)
532 PCSC_SCARDCONTEXT* pContext =
533 (PCSC_SCARDCONTEXT*)ListDictionary_GetItemValue(g_CardContexts, (
void*)hContext);
541static void pcsc_cache_item_free(
void* ptr)
543 PCSC_CACHE_ITEM* data = ptr;
549static PCSC_SCARDCONTEXT* PCSC_EstablishCardContext(SCARDCONTEXT hContext)
554 PCSC_SCARDCONTEXT* pContext = (PCSC_SCARDCONTEXT*)calloc(1,
sizeof(PCSC_SCARDCONTEXT));
559 pContext->hContext = hContext;
561 if (!InitializeCriticalSectionAndSpinCount(&(pContext->lock), 4000))
564 pContext->cache = HashTable_New(FALSE);
565 if (!pContext->cache)
567 if (!HashTable_SetupForStringData(pContext->cache, FALSE))
570 wObject* obj = HashTable_ValueObject(pContext->cache);
574 if (!ListDictionary_Add(g_CardContexts, (
void*)hContext, (
void*)pContext))
579 cardContextFree(pContext);
583static void PCSC_ReleasePrivateContext(SCARDCONTEXT hPrivateContext)
585 if (!hPrivateContext || !g_PCSC.pfnSCardReleaseContext)
589 const PCSC_LONG status = g_PCSC.pfnSCardReleaseContext(hPrivateContext);
590 if (status != SCARD_S_SUCCESS)
591 WLog_DBG(TAG,
"SCardReleaseContext of card handle context failed with %s",
592 SCardGetErrorString(PCSC_MapErrorCodeToWinSCard(status)));
595static void PCSC_ReleaseCardContext(SCARDCONTEXT hContext)
600 ULONG_PTR* keys =
nullptr;
601 SCARDCONTEXT* privateContexts =
nullptr;
602 size_t privateCount = 0;
604 ListDictionary_Lock(g_CardHandles);
605 const size_t count = ListDictionary_GetKeys(g_CardHandles, &keys);
607 privateContexts = calloc(count,
sizeof(SCARDCONTEXT));
608 for (
size_t x = 0; x < count; x++)
610 const PCSC_SCARDHANDLE* pCard =
611 ListDictionary_GetItemValue(g_CardHandles, (
void*)keys[x]);
612 if (!pCard || (pCard->hSharedContext != hContext))
615 privateContexts[privateCount++] = pCard->hPrivateContext;
616 ListDictionary_Remove(g_CardHandles, (
void*)keys[x]);
618 ListDictionary_Unlock(g_CardHandles);
622 for (
size_t x = 0; x < privateCount; x++)
623 PCSC_ReleasePrivateContext(privateContexts[x]);
624 free(privateContexts);
626 PCSC_SCARDCONTEXT* pContext = ListDictionary_Take(g_CardContexts, (
void*)hContext);
627 cardContextFree(pContext);
632static BOOL PCSC_LockCardContext(SCARDCONTEXT hContext)
634 PCSC_SCARDCONTEXT* pContext =
nullptr;
635 pContext = PCSC_GetCardContextData(hContext);
639 WLog_ERR(TAG,
"PCSC_LockCardContext: invalid context (%p)", (
void*)hContext);
643 EnterCriticalSection(&(pContext->lock));
648static BOOL PCSC_UnlockCardContext(SCARDCONTEXT hContext)
650 PCSC_SCARDCONTEXT* pContext =
nullptr;
651 pContext = PCSC_GetCardContextData(hContext);
655 WLog_ERR(TAG,
"PCSC_UnlockCardContext: invalid context (%p)", (
void*)hContext);
659 LeaveCriticalSection(&(pContext->lock));
664static PCSC_SCARDHANDLE* PCSC_GetCardHandleData(SCARDHANDLE hCard)
669 PCSC_SCARDHANDLE* pCard =
670 (PCSC_SCARDHANDLE*)ListDictionary_GetItemValue(g_CardHandles, (
void*)hCard);
679static SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
681 PCSC_SCARDHANDLE* pCard =
nullptr;
682 pCard = PCSC_GetCardHandleData(hCard);
687 return pCard->hSharedContext;
690static BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
693 PCSC_SCARDHANDLE* pCard =
nullptr;
694 PCSC_SCARDCONTEXT* pContext =
nullptr;
699 pContext = PCSC_GetCardContextData(hContext);
704 if (!pContext->owner)
711 pCard = PCSC_GetCardHandleData(hCard);
716 shared = pCard->shared;
717 hContext = pCard->hSharedContext;
718 pContext = PCSC_GetCardContextData(hContext);
723 if (!pContext->owner)
727 pContext->owner = hCard;
732 if (pContext->owner == hCard)
744static BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard)
746 PCSC_SCARDHANDLE* pCard =
nullptr;
747 PCSC_SCARDCONTEXT* pContext =
nullptr;
752 pContext = PCSC_GetCardContextData(hContext);
757 hCard = pContext->owner;
762 pCard = PCSC_GetCardHandleData(hCard);
772 pCard = PCSC_GetCardHandleData(hCard);
777 hContext = pCard->hSharedContext;
778 pContext = PCSC_GetCardContextData(hContext);
783 if (pContext->owner == hCard)
792static void PCSC_DisconnectCardHandle(PCSC_SCARDHANDLE* pCard)
797 PCSC_SCARDCONTEXT* pContext = PCSC_GetCardContextData(pCard->hSharedContext);
799 ListDictionary_Remove(g_CardHandles, (
void*)pCard->hCard);
803 WLog_ERR(TAG,
"PCSC_DisconnectCardHandle: null pContext!");
807 pContext->dwCardHandleCount--;
810WINPR_ATTR_MALLOC(PCSC_DisconnectCardHandle, 1)
811static PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDHANDLE hCard,
817 PCSC_SCARDCONTEXT* pContext = PCSC_GetCardContextData(hSharedContext);
821 WLog_ERR(TAG,
"PCSC_ConnectCardHandle: null pContext!");
825 PCSC_SCARDHANDLE* pCard = (PCSC_SCARDHANDLE*)calloc(1,
sizeof(PCSC_SCARDHANDLE));
830 pCard->hSharedContext = hSharedContext;
831 pCard->hCard = hCard;
834 pCard->szReader = _strdup(szReader);
835 if (!pCard->szReader)
839 if (!ListDictionary_Add(g_CardHandles, (
void*)hCard, (
void*)pCard))
842 pContext->dwCardHandleCount++;
845 cardHandleFreeVoid(pCard);
849static BOOL PCSC_AddMemoryBlock(SCARDCONTEXT hContext,
void* pvMem)
853 return ListDictionary_Add(g_MemoryBlocks, pvMem, (
void*)hContext);
857static void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext,
void* pvMem)
859 WINPR_UNUSED(hContext);
864 return ListDictionary_Take(g_MemoryBlocks, pvMem);
871static LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1,
873 LPSCARDCONTEXT phContext)
875 WINPR_UNUSED(dwScope);
876 PCSC_LONG status = SCARD_S_SUCCESS;
878 if (!g_PCSC.pfnSCardEstablishContext)
879 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEstablishContext");
882 g_PCSC.pfnSCardEstablishContext(SCARD_SCOPE_SYSTEM, pvReserved1, pvReserved2, phContext);
883 return PCSC_MapErrorCodeToWinSCard(status);
887static LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
888 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
892 status = PCSC_SCardEstablishContext_Internal(dwScope, pvReserved1, pvReserved2, phContext);
894 if (status == SCARD_S_SUCCESS)
895 PCSC_EstablishCardContext(*phContext);
901static LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext)
903 PCSC_LONG status = SCARD_S_SUCCESS;
905 if (!g_PCSC.pfnSCardReleaseContext)
906 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardReleaseContext");
910 WLog_ERR(TAG,
"SCardReleaseContext: null hContext");
911 return PCSC_MapErrorCodeToWinSCard(SCARD_E_INVALID_HANDLE);
914 status = g_PCSC.pfnSCardReleaseContext(hContext);
915 return PCSC_MapErrorCodeToWinSCard(status);
919static LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
921 LONG status = SCARD_S_SUCCESS;
923 status = PCSC_SCardReleaseContext_Internal(hContext);
924 PCSC_ReleaseCardContext(hContext);
930static LONG WINAPI PCSC_SCardIsValidContext(SCARDCONTEXT hContext)
932 PCSC_LONG status = SCARD_S_SUCCESS;
934 if (!g_PCSC.pfnSCardIsValidContext)
935 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardIsValidContext");
937 status = g_PCSC.pfnSCardIsValidContext(hContext);
938 return PCSC_MapErrorCodeToWinSCard(status);
942static LONG WINAPI PCSC_SCardListReaderGroups_Internal(SCARDCONTEXT hContext, LPSTR mszGroups,
945 PCSC_LONG status = SCARD_S_SUCCESS;
946 BOOL pcchGroupsAlloc = FALSE;
947 PCSC_DWORD pcsc_cchGroups = 0;
950 return SCARD_E_INVALID_PARAMETER;
952 if (!g_PCSC.pfnSCardListReaderGroups)
953 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
955 if (*pcchGroups == SCARD_AUTOALLOCATE)
956 pcchGroupsAlloc = TRUE;
958 pcsc_cchGroups = pcchGroupsAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcchGroups;
960 if (pcchGroupsAlloc && !g_SCardAutoAllocate)
963 status = g_PCSC.pfnSCardListReaderGroups(hContext,
nullptr, &pcsc_cchGroups);
965 if (status == SCARD_S_SUCCESS)
967 LPSTR tmp = calloc(1, pcsc_cchGroups);
970 return SCARD_E_NO_MEMORY;
972 status = g_PCSC.pfnSCardListReaderGroups(hContext, tmp, &pcsc_cchGroups);
974 if (status != SCARD_S_SUCCESS)
980 PCSC_AddMemoryBlock(hContext, tmp);
982 *(WINPR_PACKED_ALIGN_CAST(LPSTR*, mszGroups)) = tmp;
987 status = g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, &pcsc_cchGroups);
990 *pcchGroups = (DWORD)pcsc_cchGroups;
991 return PCSC_MapErrorCodeToWinSCard(status);
995static LONG WINAPI PCSC_SCardListReaderGroupsA(SCARDCONTEXT hContext, LPSTR mszGroups,
998 LONG status = SCARD_S_SUCCESS;
1000 if (!g_PCSC.pfnSCardListReaderGroups)
1001 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
1003 if (!PCSC_LockCardContext(hContext))
1004 return SCARD_E_INVALID_HANDLE;
1006 status = PCSC_SCardListReaderGroups_Internal(hContext, mszGroups, pcchGroups);
1008 if (!PCSC_UnlockCardContext(hContext))
1009 return SCARD_E_INVALID_HANDLE;
1015static LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext, LPWSTR mszGroups,
1018 LPSTR mszGroupsA =
nullptr;
1019 LPSTR* pMszGroupsA = &mszGroupsA;
1020 LONG status = SCARD_S_SUCCESS;
1022 if (!g_PCSC.pfnSCardListReaderGroups)
1023 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
1025 if (!PCSC_LockCardContext(hContext))
1026 return SCARD_E_INVALID_HANDLE;
1028 status = PCSC_SCardListReaderGroups_Internal(hContext, (LPSTR)&mszGroupsA, pcchGroups);
1030 if (status == SCARD_S_SUCCESS)
1033 WCHAR* str = ConvertMszUtf8NToWCharAlloc(*pMszGroupsA, *pcchGroups, &size);
1036 status = SCARD_E_NO_MEMORY;
1039 *(WINPR_PACKED_ALIGN_CAST(WCHAR**, mszGroups)) = str;
1040 *pcchGroups = (DWORD)size;
1041 PCSC_AddMemoryBlock(hContext, str);
1042 PCSC_SCardFreeMemory_Internal(hContext, *pMszGroupsA);
1046 if (!PCSC_UnlockCardContext(hContext))
1047 return SCARD_E_INVALID_HANDLE;
1053static LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext, LPCSTR mszGroups,
1054 LPSTR mszReaders, LPDWORD pcchReaders)
1056 PCSC_LONG status = SCARD_S_SUCCESS;
1057 BOOL pcchReadersAlloc = FALSE;
1058 PCSC_DWORD pcsc_cchReaders = 0;
1060 return SCARD_E_INVALID_PARAMETER;
1062 if (!g_PCSC.pfnSCardListReaders)
1063 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
1065 mszGroups =
nullptr;
1067 if (*pcchReaders == SCARD_AUTOALLOCATE)
1068 pcchReadersAlloc = TRUE;
1070 pcsc_cchReaders = pcchReadersAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcchReaders;
1072 if (pcchReadersAlloc && !g_SCardAutoAllocate)
1074 pcsc_cchReaders = 0;
1075 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups,
nullptr, &pcsc_cchReaders);
1077 if (status == SCARD_S_SUCCESS)
1079 char* tmp = calloc(1, pcsc_cchReaders);
1082 return SCARD_E_NO_MEMORY;
1084 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, tmp, &pcsc_cchReaders);
1086 if (status != SCARD_S_SUCCESS)
1092 PCSC_AddMemoryBlock(hContext, tmp);
1094 *(WINPR_PACKED_ALIGN_CAST(
char**, mszReaders)) = tmp;
1099 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, &pcsc_cchReaders);
1102 *pcchReaders = (DWORD)pcsc_cchReaders;
1103 return PCSC_MapErrorCodeToWinSCard(status);
1107static LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
1108 LPDWORD pcchReaders)
1110 LONG status = SCARD_S_SUCCESS;
1111 BOOL nullCardContext = FALSE;
1113 if (!g_PCSC.pfnSCardListReaders)
1114 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
1118 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1120 if (status != SCARD_S_SUCCESS)
1124 nullCardContext = TRUE;
1127 if (!PCSC_LockCardContext(hContext))
1129 status = SCARD_E_INVALID_HANDLE;
1133 status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders);
1135 if (!PCSC_UnlockCardContext(hContext))
1136 status = SCARD_E_INVALID_HANDLE;
1139 if (nullCardContext)
1141 const LONG rc = PCSC_SCardReleaseContext(hContext);
1142 if (rc != SCARD_S_SUCCESS)
1150static LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, LPCWSTR mszGroups,
1151 LPWSTR mszReaders, LPDWORD pcchReaders)
1153 LPSTR mszGroupsA =
nullptr;
1154 LPSTR mszReadersA =
nullptr;
1155 LONG status = SCARD_S_SUCCESS;
1156 BOOL nullCardContext = FALSE;
1158 if (!g_PCSC.pfnSCardListReaders)
1159 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
1163 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1165 if (status != SCARD_S_SUCCESS)
1169 nullCardContext = TRUE;
1172 if (!PCSC_LockCardContext(hContext))
1174 status = SCARD_E_INVALID_HANDLE;
1180 mszGroupsA = ConvertWCharToUtf8Alloc(mszGroups,
nullptr);
1183 status = SCARD_E_NO_MEMORY;
1193 cnv.ppc = &mszReadersA;
1195 status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, cnv.pc, pcchReaders);
1197 if (status == SCARD_S_SUCCESS)
1200 WCHAR* str = ConvertMszUtf8NToWCharAlloc(mszReadersA, *pcchReaders, &size);
1201 PCSC_SCardFreeMemory_Internal(hContext, mszReadersA);
1202 if (!str || (size > UINT32_MAX))
1204 status = SCARD_E_NO_MEMORY;
1209 *(WINPR_PACKED_ALIGN_CAST(LPWSTR*, mszReaders)) = str;
1210 *pcchReaders = (DWORD)size;
1211 PCSC_AddMemoryBlock(hContext, str);
1215 if (!PCSC_UnlockCardContext(hContext))
1216 status = SCARD_E_INVALID_HANDLE;
1219 if (nullCardContext)
1221 const LONG rc = PCSC_SCardReleaseContext(hContext);
1222 if (rc != SCARD_S_SUCCESS)
1233 const char* cardName;
1236static PcscKnownAtr knownAtrs[] = {
1238 { { 0x3B, 0xFD, 0x13, 0x00, 0x00, 0x81, 0x31, 0xFE, 0x15, 0x80, 0x73, 0xC0,
1239 0x21, 0xC0, 0x57, 0x59, 0x75, 0x62, 0x69, 0x4B, 0x65, 0x79, 0x40 },
1241 "NIST SP 800-73 [PIV]" },
1243 { { 0x3B, 0xFC, 0x18, 0x00, 0x00, 0x81, 0x31, 0x80, 0x45, 0x90, 0x67,
1244 0x46, 0x4A, 0x00, 0x64, 0x16, 0x06, 0xF2, 0x72, 0x7E, 0x00, 0xE0 },
1246 "PIVKey Feitian (E0)" }
1250#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a)[0])
1254static const char* findCardByAtr(LPCBYTE pbAtr)
1256 for (
size_t i = 0; i < ARRAY_LENGTH(knownAtrs); i++)
1258 if (memcmp(knownAtrs[i].atr, pbAtr, knownAtrs[i].atrLen) == 0)
1259 return knownAtrs[i].cardName;
1266static LONG WINAPI PCSC_SCardListCardsA(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, LPCBYTE pbAtr,
1267 LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
1268 CHAR* mszCards, LPDWORD pcchCards)
1270 const char* cardName =
nullptr;
1271 DWORD outputLen = 1;
1272 CHAR* output =
nullptr;
1273 BOOL autoAllocate = 0;
1275 if (!pbAtr || rgquidInterfaces || cguidInterfaceCount)
1276 return SCARD_E_UNSUPPORTED_FEATURE;
1279 return SCARD_E_INVALID_PARAMETER;
1281 autoAllocate = (*pcchCards == SCARD_AUTOALLOCATE);
1283 cardName = findCardByAtr(pbAtr);
1285 outputLen += strlen(cardName) + 1;
1287 *pcchCards = outputLen;
1290 output = malloc(outputLen);
1292 return SCARD_E_NO_MEMORY;
1294 *(WINPR_PACKED_ALIGN_CAST(LPSTR*, mszCards)) = output;
1299 return SCARD_S_SUCCESS;
1301 if (*pcchCards < outputLen)
1302 return SCARD_E_INSUFFICIENT_BUFFER;
1309 size_t toCopy = strlen(cardName) + 1;
1310 memcpy(output, cardName, toCopy);
1316 return SCARD_S_SUCCESS;
1319WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardListCardsW(
1320 WINPR_ATTR_UNUSED SCARDCONTEXT hContext, LPCBYTE pbAtr, LPCGUID rgquidInterfaces,
1321 DWORD cguidInterfaceCount, WCHAR* mszCards, LPDWORD pcchCards)
1323 const char* cardName =
nullptr;
1324 DWORD outputLen = 1;
1325 WCHAR* output =
nullptr;
1326 BOOL autoAllocate = 0;
1328 if (!pbAtr || rgquidInterfaces || cguidInterfaceCount)
1329 return SCARD_E_UNSUPPORTED_FEATURE;
1332 return SCARD_E_INVALID_PARAMETER;
1334 autoAllocate = (*pcchCards == SCARD_AUTOALLOCATE);
1336 cardName = findCardByAtr(pbAtr);
1338 outputLen += strlen(cardName) + 1;
1340 *pcchCards = outputLen;
1343 output = calloc(outputLen,
sizeof(WCHAR));
1345 return SCARD_E_NO_MEMORY;
1347 *(WINPR_PACKED_ALIGN_CAST(LPWSTR*, mszCards)) = output;
1352 return SCARD_S_SUCCESS;
1354 if (*pcchCards < outputLen)
1355 return SCARD_E_INSUFFICIENT_BUFFER;
1362 size_t toCopy = strlen(cardName) + 1;
1363 if (ConvertUtf8ToWChar(cardName, output, toCopy) < 0)
1364 return SCARD_F_INTERNAL_ERROR;
1370 return SCARD_S_SUCCESS;
1375PCSC_SCardListInterfacesA(SCARDCONTEXT hContext, LPCSTR szCard, LPGUID pguidInterfaces,
1376 LPDWORD pcguidInterfaces )
1378 WINPR_UNUSED(hContext);
1379 WINPR_UNUSED(szCard);
1380 WINPR_UNUSED(pguidInterfaces);
1381 WINPR_UNUSED(pcguidInterfaces);
1382 return SCARD_E_UNSUPPORTED_FEATURE;
1387PCSC_SCardListInterfacesW(SCARDCONTEXT hContext, LPCWSTR szCard, LPGUID pguidInterfaces,
1388 LPDWORD pcguidInterfaces )
1390 WINPR_UNUSED(hContext);
1391 WINPR_UNUSED(szCard);
1392 WINPR_UNUSED(pguidInterfaces);
1393 WINPR_UNUSED(pcguidInterfaces);
1394 return SCARD_E_UNSUPPORTED_FEATURE;
1397WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetProviderIdA(SCARDCONTEXT hContext,
1399 LPGUID pguidProviderId)
1401 WINPR_UNUSED(hContext);
1402 WINPR_UNUSED(szCard);
1403 WINPR_UNUSED(pguidProviderId);
1404 return SCARD_E_UNSUPPORTED_FEATURE;
1407WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetProviderIdW(SCARDCONTEXT hContext,
1409 LPGUID pguidProviderId)
1411 WINPR_UNUSED(hContext);
1412 WINPR_UNUSED(szCard);
1413 WINPR_UNUSED(pguidProviderId);
1414 return SCARD_E_UNSUPPORTED_FEATURE;
1417WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetCardTypeProviderNameA(
1418 SCARDCONTEXT hContext, LPCSTR szCardName, DWORD dwProviderId,
1420 LPDWORD pcchProvider )
1422 WINPR_UNUSED(hContext);
1423 WINPR_UNUSED(szCardName);
1424 WINPR_UNUSED(dwProviderId);
1425 WINPR_UNUSED(szProvider);
1426 WINPR_UNUSED(pcchProvider);
1427 return SCARD_E_UNSUPPORTED_FEATURE;
1430WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetCardTypeProviderNameW(
1431 SCARDCONTEXT hContext, LPCWSTR szCardName, DWORD dwProviderId,
1433 LPDWORD pcchProvider )
1435 WINPR_UNUSED(hContext);
1436 WINPR_UNUSED(szCardName);
1437 WINPR_UNUSED(dwProviderId);
1438 WINPR_UNUSED(szProvider);
1439 WINPR_UNUSED(pcchProvider);
1440 return SCARD_E_UNSUPPORTED_FEATURE;
1443WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderGroupA(SCARDCONTEXT hContext,
1446 WINPR_UNUSED(hContext);
1447 WINPR_UNUSED(szGroupName);
1448 return SCARD_E_UNSUPPORTED_FEATURE;
1451WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderGroupW(SCARDCONTEXT hContext,
1452 LPCWSTR szGroupName)
1454 WINPR_UNUSED(hContext);
1455 WINPR_UNUSED(szGroupName);
1456 return SCARD_E_UNSUPPORTED_FEATURE;
1459WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderGroupA(SCARDCONTEXT hContext,
1462 WINPR_UNUSED(hContext);
1463 WINPR_UNUSED(szGroupName);
1464 return SCARD_E_UNSUPPORTED_FEATURE;
1467WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderGroupW(SCARDCONTEXT hContext,
1468 LPCWSTR szGroupName)
1470 WINPR_UNUSED(hContext);
1471 WINPR_UNUSED(szGroupName);
1472 return SCARD_E_UNSUPPORTED_FEATURE;
1475WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderA(SCARDCONTEXT hContext,
1476 LPCSTR szReaderName,
1477 LPCSTR szDeviceName)
1479 WINPR_UNUSED(hContext);
1480 WINPR_UNUSED(szReaderName);
1481 WINPR_UNUSED(szDeviceName);
1482 return SCARD_E_UNSUPPORTED_FEATURE;
1485WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderW(SCARDCONTEXT hContext,
1486 LPCWSTR szReaderName,
1487 LPCWSTR szDeviceName)
1489 WINPR_UNUSED(hContext);
1490 WINPR_UNUSED(szReaderName);
1491 WINPR_UNUSED(szDeviceName);
1492 return SCARD_E_UNSUPPORTED_FEATURE;
1495WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderA(SCARDCONTEXT hContext,
1496 LPCSTR szReaderName)
1498 WINPR_UNUSED(hContext);
1499 WINPR_UNUSED(szReaderName);
1500 return SCARD_E_UNSUPPORTED_FEATURE;
1503WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderW(SCARDCONTEXT hContext,
1504 LPCWSTR szReaderName)
1506 WINPR_UNUSED(hContext);
1507 WINPR_UNUSED(szReaderName);
1508 return SCARD_E_UNSUPPORTED_FEATURE;
1511WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardAddReaderToGroupA(SCARDCONTEXT hContext,
1512 LPCSTR szReaderName,
1515 WINPR_UNUSED(hContext);
1516 WINPR_UNUSED(szReaderName);
1517 WINPR_UNUSED(szGroupName);
1518 return SCARD_E_UNSUPPORTED_FEATURE;
1521WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardAddReaderToGroupW(SCARDCONTEXT hContext,
1522 LPCWSTR szReaderName,
1523 LPCWSTR szGroupName)
1525 WINPR_UNUSED(hContext);
1526 WINPR_UNUSED(szReaderName);
1527 WINPR_UNUSED(szGroupName);
1528 return SCARD_E_UNSUPPORTED_FEATURE;
1531WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardRemoveReaderFromGroupA(SCARDCONTEXT hContext,
1532 LPCSTR szReaderName,
1535 WINPR_UNUSED(hContext);
1536 WINPR_UNUSED(szReaderName);
1537 WINPR_UNUSED(szGroupName);
1538 return SCARD_E_UNSUPPORTED_FEATURE;
1541WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardRemoveReaderFromGroupW(SCARDCONTEXT hContext,
1542 LPCWSTR szReaderName,
1543 LPCWSTR szGroupName)
1545 WINPR_UNUSED(hContext);
1546 WINPR_UNUSED(szReaderName);
1547 WINPR_UNUSED(szGroupName);
1548 return SCARD_E_UNSUPPORTED_FEATURE;
1551WINPR_ATTR_NODISCARD
static LONG WINAPI
1552PCSC_SCardIntroduceCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName, LPCGUID pguidPrimaryProvider,
1553 LPCGUID rgguidInterfaces, DWORD dwInterfaceCount, LPCBYTE pbAtr,
1554 LPCBYTE pbAtrMask, DWORD cbAtrLen)
1556 WINPR_UNUSED(hContext);
1557 WINPR_UNUSED(szCardName);
1558 WINPR_UNUSED(pguidPrimaryProvider);
1559 WINPR_UNUSED(rgguidInterfaces);
1560 WINPR_UNUSED(dwInterfaceCount);
1561 WINPR_UNUSED(pbAtr);
1562 WINPR_UNUSED(pbAtrMask);
1563 WINPR_UNUSED(cbAtrLen);
1564 return SCARD_E_UNSUPPORTED_FEATURE;
1567WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceCardTypeW(
1568 SCARDCONTEXT hContext, LPCWSTR szCardName, LPCGUID pguidPrimaryProvider,
1569 LPCGUID rgguidInterfaces, DWORD dwInterfaceCount, LPCBYTE pbAtr, LPCBYTE pbAtrMask,
1572 WINPR_UNUSED(hContext);
1573 WINPR_UNUSED(szCardName);
1574 WINPR_UNUSED(pguidPrimaryProvider);
1575 WINPR_UNUSED(rgguidInterfaces);
1576 WINPR_UNUSED(dwInterfaceCount);
1577 WINPR_UNUSED(pbAtr);
1578 WINPR_UNUSED(pbAtrMask);
1579 WINPR_UNUSED(cbAtrLen);
1580 return SCARD_E_UNSUPPORTED_FEATURE;
1583WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetCardTypeProviderNameA(SCARDCONTEXT hContext,
1588 WINPR_UNUSED(hContext);
1589 WINPR_UNUSED(szCardName);
1590 WINPR_UNUSED(dwProviderId);
1591 WINPR_UNUSED(szProvider);
1592 return SCARD_E_UNSUPPORTED_FEATURE;
1595WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetCardTypeProviderNameW(SCARDCONTEXT hContext,
1600 WINPR_UNUSED(hContext);
1601 WINPR_UNUSED(szCardName);
1602 WINPR_UNUSED(dwProviderId);
1603 WINPR_UNUSED(szProvider);
1604 return SCARD_E_UNSUPPORTED_FEATURE;
1607WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetCardTypeA(SCARDCONTEXT hContext,
1610 WINPR_UNUSED(hContext);
1611 WINPR_UNUSED(szCardName);
1612 return SCARD_E_UNSUPPORTED_FEATURE;
1615WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetCardTypeW(SCARDCONTEXT hContext,
1618 WINPR_UNUSED(hContext);
1619 WINPR_UNUSED(szCardName);
1620 return SCARD_E_UNSUPPORTED_FEATURE;
1623static LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPVOID pvMem)
1625 PCSC_LONG status = SCARD_S_SUCCESS;
1627 if (PCSC_RemoveMemoryBlock(hContext, pvMem))
1628 status = SCARD_S_SUCCESS;
1631 if (g_PCSC.pfnSCardFreeMemory)
1633 status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
1637 return PCSC_MapErrorCodeToWinSCard(status);
1640WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPVOID pvMem)
1642 LONG status = SCARD_S_SUCCESS;
1646 if (!PCSC_LockCardContext(hContext))
1647 return SCARD_E_INVALID_HANDLE;
1650 status = PCSC_SCardFreeMemory_Internal(hContext, pvMem);
1654 if (!PCSC_UnlockCardContext(hContext))
1655 return SCARD_E_INVALID_HANDLE;
1662static HANDLE WINAPI PCSC_SCardAccessStartedEvent(
void)
1665 SCARDCONTEXT hContext = 0;
1667 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1669 if (status != SCARD_S_SUCCESS)
1672 status = PCSC_SCardReleaseContext(hContext);
1674 if (status != SCARD_S_SUCCESS)
1677 if (!g_StartedEvent)
1679 if (!(g_StartedEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
1682 if (!SetEvent(g_StartedEvent))
1684 (void)CloseHandle(g_StartedEvent);
1689 g_StartedEventRefCount++;
1690 return g_StartedEvent;
1693static void WINAPI PCSC_SCardReleaseStartedEvent(
void)
1695 g_StartedEventRefCount--;
1697 if (g_StartedEventRefCount == 0)
1701 (void)CloseHandle(g_StartedEvent);
1702 g_StartedEvent =
nullptr;
1707WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardLocateCardsA(SCARDCONTEXT hContext,
1712 WINPR_UNUSED(hContext);
1713 WINPR_UNUSED(mszCards);
1714 WINPR_UNUSED(rgReaderStates);
1715 WINPR_UNUSED(cReaders);
1716 return SCARD_E_UNSUPPORTED_FEATURE;
1719WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardLocateCardsW(SCARDCONTEXT hContext,
1724 WINPR_UNUSED(hContext);
1725 WINPR_UNUSED(mszCards);
1726 WINPR_UNUSED(rgReaderStates);
1727 WINPR_UNUSED(cReaders);
1728 return SCARD_E_UNSUPPORTED_FEATURE;
1731WINPR_ATTR_NODISCARD
static LONG WINAPI
1732PCSC_SCardLocateCardsByATRA(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs,
1735 WINPR_UNUSED(hContext);
1736 WINPR_UNUSED(rgAtrMasks);
1737 WINPR_UNUSED(cAtrs);
1738 WINPR_UNUSED(rgReaderStates);
1739 WINPR_UNUSED(cReaders);
1740 return SCARD_E_UNSUPPORTED_FEATURE;
1743WINPR_ATTR_NODISCARD
static LONG WINAPI
1744PCSC_SCardLocateCardsByATRW(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs,
1747 WINPR_UNUSED(hContext);
1748 WINPR_UNUSED(rgAtrMasks);
1749 WINPR_UNUSED(cAtrs);
1750 WINPR_UNUSED(rgReaderStates);
1751 WINPR_UNUSED(cReaders);
1752 return SCARD_E_UNSUPPORTED_FEATURE;
1755WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetStatusChange_Internal(
1758 INT64* map =
nullptr;
1759 PCSC_DWORD cMappedReaders = 0;
1761 PCSC_LONG status = SCARD_S_SUCCESS;
1762 PCSC_DWORD pcsc_dwTimeout = (PCSC_DWORD)dwTimeout;
1763 PCSC_DWORD pcsc_cReaders = (PCSC_DWORD)cReaders;
1765 if (!g_PCSC.pfnSCardGetStatusChange)
1766 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetStatusChange");
1769 return SCARD_S_SUCCESS;
1772 pcsc_dwTimeout = pcsc_dwTimeout ? pcsc_dwTimeout : 1;
1786 map = (INT64*)calloc(pcsc_cReaders,
sizeof(INT64));
1789 return SCARD_E_NO_MEMORY;
1796 return SCARD_E_NO_MEMORY;
1800 for (PCSC_DWORD i = 0; i < pcsc_cReaders; i++)
1802 if (!g_PnP_Notification)
1805 if (!reader->szReader)
1807 if (0 == _stricmp(reader->szReader, SMARTCARD_PNP_NOTIFICATION_A))
1815 states[j].szReader = rgReaderStates[i].szReader;
1816 states[j].dwCurrentState = rgReaderStates[i].dwCurrentState;
1817 states[j].pvUserData = rgReaderStates[i].pvUserData;
1818 states[j].dwEventState = rgReaderStates[i].dwEventState;
1819 states[j].cbAtr = rgReaderStates[i].cbAtr;
1820 CopyMemory(&(states[j].rgbAtr), &(rgReaderStates[i].rgbAtr), PCSC_MAX_ATR_SIZE);
1826 if (cMappedReaders > 0)
1828 status = g_PCSC.pfnSCardGetStatusChange(hContext, pcsc_dwTimeout, states, cMappedReaders);
1832 status = SCARD_S_SUCCESS;
1835 for (PCSC_DWORD i = 0; i < pcsc_cReaders; i++)
1840 PCSC_DWORD k = (PCSC_DWORD)map[i];
1841 rgReaderStates[i].dwCurrentState = (DWORD)states[k].dwCurrentState;
1842 rgReaderStates[i].cbAtr = (DWORD)states[k].cbAtr;
1843 CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[k].rgbAtr), PCSC_MAX_ATR_SIZE);
1844 rgReaderStates[i].dwEventState = (DWORD)states[k].dwEventState;
1847 if ((status == SCARD_S_SUCCESS) && (states[k].dwEventState & SCARD_STATE_EMPTY))
1848 PCSC_ResetTransmitCount(rgReaderStates[i].szReader);
1853 return PCSC_MapErrorCodeToWinSCard(status);
1857static LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext, DWORD dwTimeout,
1860 LONG status = SCARD_S_SUCCESS;
1862 if (!PCSC_LockCardContext(hContext))
1863 return SCARD_E_INVALID_HANDLE;
1865 status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, rgReaderStates, cReaders);
1867 if (!PCSC_UnlockCardContext(hContext))
1868 return SCARD_E_INVALID_HANDLE;
1874static LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext, DWORD dwTimeout,
1878 LONG status = SCARD_S_SUCCESS;
1880 if (!g_PCSC.pfnSCardGetStatusChange)
1881 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetStatusChange");
1883 if (!PCSC_LockCardContext(hContext))
1884 return SCARD_E_INVALID_HANDLE;
1890 if (!PCSC_UnlockCardContext(hContext))
1891 return SCARD_E_INVALID_HANDLE;
1892 return SCARD_E_NO_MEMORY;
1895 for (DWORD index = 0; index < cReaders; index++)
1900 cur->szReader = ConvertWCharToUtf8Alloc(curReader->szReader,
nullptr);
1901 cur->pvUserData = curReader->pvUserData;
1902 cur->dwCurrentState = curReader->dwCurrentState;
1903 cur->dwEventState = curReader->dwEventState;
1904 cur->cbAtr = curReader->cbAtr;
1905 CopyMemory(&(cur->rgbAtr), &(curReader->rgbAtr), ARRAYSIZE(cur->rgbAtr));
1908 status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, states, cReaders);
1910 for (DWORD index = 0; index < cReaders; index++)
1912 free((
void*)states[index].szReader);
1913 rgReaderStates[index].pvUserData = states[index].pvUserData;
1914 rgReaderStates[index].dwCurrentState = states[index].dwCurrentState;
1915 rgReaderStates[index].dwEventState = states[index].dwEventState;
1916 rgReaderStates[index].cbAtr = states[index].cbAtr;
1917 CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36);
1922 if (!PCSC_UnlockCardContext(hContext))
1923 return SCARD_E_INVALID_HANDLE;
1928static LONG WINAPI PCSC_SCardCancel(SCARDCONTEXT hContext)
1930 PCSC_LONG status = SCARD_S_SUCCESS;
1932 if (!g_PCSC.pfnSCardCancel)
1933 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardCancel");
1935 status = g_PCSC.pfnSCardCancel(hContext);
1936 return PCSC_MapErrorCodeToWinSCard(status);
1939WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnect_Internal(
1940 SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
1941 LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
1944 const char* szReaderPCSC =
nullptr;
1945 PCSC_LONG status = SCARD_S_SUCCESS;
1946 PCSC_SCARDHANDLE* pCard =
nullptr;
1947 PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD)dwShareMode;
1948 PCSC_DWORD pcsc_dwPreferredProtocols = 0;
1949 PCSC_DWORD pcsc_dwActiveProtocol = 0;
1951 if (!g_PCSC.pfnSCardConnect)
1952 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardConnect");
1954 if (!g_PCSC.pfnSCardEstablishContext)
1955 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEstablishContext");
1957 if (!PCSC_GetCardContextData(hContext))
1958 return SCARD_E_INVALID_HANDLE;
1960 shared = (dwShareMode == SCARD_SHARE_DIRECT) != 0;
1961 PCSC_WaitForCardAccess(hContext, 0, shared);
1962 szReaderPCSC = szReader;
1971 if (pcsc_dwShareMode == SCARD_SHARE_DIRECT && dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED)
1972 pcsc_dwPreferredProtocols = SCARD_PROTOCOL_UNDEFINED;
1974 pcsc_dwPreferredProtocols =
1975 (PCSC_DWORD)PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
1979 SCARDCONTEXT hPrivateContext = 0;
1981 g_PCSC.pfnSCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hPrivateContext);
1982 if (status != SCARD_S_SUCCESS)
1983 return PCSC_MapErrorCodeToWinSCard(status);
1985 status = g_PCSC.pfnSCardConnect(hPrivateContext, szReaderPCSC, pcsc_dwShareMode,
1986 pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol);
1988 if (status != SCARD_S_SUCCESS)
1990 PCSC_ReleasePrivateContext(hPrivateContext);
1991 return PCSC_MapErrorCodeToWinSCard(status);
1994 if (!PCSC_LockCardContext(hContext))
1997 PCSC_ReleasePrivateContext(hPrivateContext);
1998 return SCARD_E_INVALID_HANDLE;
2001 pCard = PCSC_ConnectCardHandle(hContext, *phCard, szReader);
2004 *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwActiveProtocol);
2005 pCard->shared = shared;
2006 pCard->hPrivateContext = hPrivateContext;
2008 PCSC_WaitForCardAccess(hContext, pCard->hSharedContext, shared);
2011 const BOOL unlocked = PCSC_UnlockCardContext(hContext);
2014 PCSC_ReleasePrivateContext(hPrivateContext);
2015 return SCARD_E_NO_MEMORY;
2019 PCSC_DisconnectCardHandle(pCard);
2020 PCSC_ReleasePrivateContext(hPrivateContext);
2021 return SCARD_E_INVALID_HANDLE;
2025 return SCARD_S_SUCCESS;
2028WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext, LPCSTR szReader,
2030 DWORD dwPreferredProtocols,
2031 LPSCARDHANDLE phCard,
2032 LPDWORD pdwActiveProtocol)
2034 return PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode, dwPreferredProtocols, phCard,
2038WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext, LPCWSTR szReader,
2040 DWORD dwPreferredProtocols,
2041 LPSCARDHANDLE phCard,
2042 LPDWORD pdwActiveProtocol)
2044 LPSTR szReaderA =
nullptr;
2045 LONG status = SCARD_S_SUCCESS;
2049 szReaderA = ConvertWCharToUtf8Alloc(szReader,
nullptr);
2051 return SCARD_E_INSUFFICIENT_BUFFER;
2054 status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode, dwPreferredProtocols,
2055 phCard, pdwActiveProtocol);
2060WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
2061 DWORD dwPreferredProtocols,
2062 DWORD dwInitialization,
2063 LPDWORD pdwActiveProtocol)
2065 PCSC_LONG status = SCARD_S_SUCCESS;
2066 PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD)dwShareMode;
2067 PCSC_DWORD pcsc_dwPreferredProtocols = 0;
2068 PCSC_DWORD pcsc_dwInitialization = (PCSC_DWORD)dwInitialization;
2069 PCSC_DWORD pcsc_dwActiveProtocol = 0;
2071 if (!g_PCSC.pfnSCardReconnect)
2072 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardReconnect");
2074 const BOOL shared = (dwShareMode == SCARD_SHARE_DIRECT) != 0;
2075 PCSC_WaitForCardAccess(0, hCard, shared);
2076 pcsc_dwPreferredProtocols = (PCSC_DWORD)PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
2077 status = g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode, pcsc_dwPreferredProtocols,
2078 pcsc_dwInitialization, &pcsc_dwActiveProtocol);
2080 *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwActiveProtocol);
2081 return PCSC_MapErrorCodeToWinSCard(status);
2084WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
2086 PCSC_LONG status = SCARD_S_SUCCESS;
2087 PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD)dwDisposition;
2089 if (!g_PCSC.pfnSCardDisconnect)
2090 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardDisconnect");
2092 status = g_PCSC.pfnSCardDisconnect(hCard, pcsc_dwDisposition);
2095 PCSC_ReleaseCardAccess(0, hCard);
2097 if (status == SCARD_S_SUCCESS)
2099 PCSC_SCARDHANDLE* pCard = PCSC_GetCardHandleData(hCard);
2100 const SCARDCONTEXT hPrivateContext = pCard ? pCard->hPrivateContext : 0;
2101 PCSC_DisconnectCardHandle(pCard);
2102 PCSC_ReleasePrivateContext(hPrivateContext);
2105 return PCSC_MapErrorCodeToWinSCard(status);
2108WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardBeginTransaction(SCARDHANDLE hCard)
2110 PCSC_LONG status = SCARD_S_SUCCESS;
2111 PCSC_SCARDHANDLE* pCard =
nullptr;
2112 PCSC_SCARDCONTEXT* pContext =
nullptr;
2114 if (!g_PCSC.pfnSCardBeginTransaction)
2115 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardBeginTransaction");
2117 pCard = PCSC_GetCardHandleData(hCard);
2120 return SCARD_E_INVALID_HANDLE;
2122 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
2125 return SCARD_E_INVALID_HANDLE;
2128 if (pCard->isTransactionLocked)
2129 return SCARD_S_SUCCESS;
2131 status = g_PCSC.pfnSCardBeginTransaction(hCard);
2133 if (status == SCARD_S_SUCCESS)
2134 pCard->isTransactionLocked = TRUE;
2135 return PCSC_MapErrorCodeToWinSCard(status);
2138WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard,
2139 DWORD dwDisposition)
2141 PCSC_LONG status = SCARD_S_SUCCESS;
2142 PCSC_SCARDHANDLE* pCard =
nullptr;
2143 PCSC_SCARDCONTEXT* pContext =
nullptr;
2144 PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD)dwDisposition;
2146 if (!g_PCSC.pfnSCardEndTransaction)
2147 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEndTransaction");
2149 pCard = PCSC_GetCardHandleData(hCard);
2152 return SCARD_E_INVALID_HANDLE;
2154 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
2157 return SCARD_E_INVALID_HANDLE;
2159 PCSC_ReleaseCardAccess(0, hCard);
2161 if (!pCard->isTransactionLocked)
2162 return SCARD_S_SUCCESS;
2164 status = g_PCSC.pfnSCardEndTransaction(hCard, pcsc_dwDisposition);
2166 pCard->isTransactionLocked = FALSE;
2167 return PCSC_MapErrorCodeToWinSCard(status);
2170static LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
2172 WINPR_UNUSED(hCard);
2173 return SCARD_S_SUCCESS;
2180WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatus_Internal(
2181 SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
2182 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen, BOOL unicode)
2184 PCSC_SCARDHANDLE* pCard =
nullptr;
2185 SCARDCONTEXT hContext = 0;
2186 PCSC_LONG status = 0;
2187 PCSC_DWORD pcsc_cchReaderLen = 0;
2188 PCSC_DWORD pcsc_cbAtrLen = 0;
2189 PCSC_DWORD pcsc_dwState = 0;
2190 PCSC_DWORD pcsc_dwProtocol = 0;
2191 BOOL allocateReader = FALSE;
2192 BOOL allocateAtr = FALSE;
2193 LPSTR readerNames = mszReaderNames;
2195 LPSTR tReader =
nullptr;
2196 LPBYTE tATR =
nullptr;
2198 if (!g_PCSC.pfnSCardStatus)
2199 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardStatus");
2201 pCard = PCSC_GetCardHandleData(hCard);
2204 return SCARD_E_INVALID_VALUE;
2206 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2207 hContext = PCSC_GetCardContextFromHandle(hCard);
2210 return SCARD_E_INVALID_VALUE;
2212 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &pcsc_cchReaderLen,
nullptr,
nullptr,
nullptr,
2215 if (status != STATUS_SUCCESS)
2216 return PCSC_MapErrorCodeToWinSCard(status);
2218 pcsc_cchReaderLen++;
2221 pcsc_cchReaderLen *= 2;
2225 if (*pcchReaderLen == SCARD_AUTOALLOCATE)
2226 allocateReader = TRUE;
2227 else if (mszReaderNames && (*pcchReaderLen < pcsc_cchReaderLen))
2228 return SCARD_E_INSUFFICIENT_BUFFER;
2230 pcsc_cchReaderLen = *pcchReaderLen;
2235 if (*pcbAtrLen == SCARD_AUTOALLOCATE)
2237 else if (pbAtr && (*pcbAtrLen < pcsc_cbAtrLen))
2238 return SCARD_E_INSUFFICIENT_BUFFER;
2240 pcsc_cbAtrLen = *pcbAtrLen;
2243 if (allocateReader && pcsc_cchReaderLen > 0 && mszReaderNames)
2250 if (OSXVersion == 0x10100000)
2251 pcsc_cchReaderLen++;
2254 tReader = calloc(
sizeof(CHAR), pcsc_cchReaderLen + 1);
2258 status = ERROR_NOT_ENOUGH_MEMORY;
2262 readerNames = tReader;
2265 if (allocateAtr && pcsc_cbAtrLen > 0 && pbAtr)
2267 tATR = calloc(1, pcsc_cbAtrLen);
2271 status = ERROR_NOT_ENOUGH_MEMORY;
2278 status = g_PCSC.pfnSCardStatus(hCard, readerNames, &pcsc_cchReaderLen, &pcsc_dwState,
2279 &pcsc_dwProtocol, atr, &pcsc_cbAtrLen);
2281 if (status != STATUS_SUCCESS)
2286 PCSC_AddMemoryBlock(hContext, tATR);
2287 *(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAtr)) = tATR;
2295 WCHAR* tmp = ConvertMszUtf8NToWCharAlloc(tReader, pcsc_cchReaderLen + 1, &size);
2299 status = ERROR_NOT_ENOUGH_MEMORY;
2305 PCSC_AddMemoryBlock(hContext, tmp);
2306 *(WINPR_PACKED_ALIGN_CAST(WCHAR**, mszReaderNames)) = tmp;
2310 tReader[pcsc_cchReaderLen - 1] =
'\0';
2311 PCSC_AddMemoryBlock(hContext, tReader);
2312 *(WINPR_PACKED_ALIGN_CAST(
char**, mszReaderNames)) = tReader;
2316 pcsc_dwState &= 0xFFFF;
2319 *pdwState = PCSC_ConvertCardStateToWinSCard((DWORD)pcsc_dwState, status);
2322 *pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwProtocol);
2325 *pcbAtrLen = (DWORD)pcsc_cbAtrLen;
2329 WINPR_ASSERT(pcsc_cchReaderLen < UINT32_MAX);
2330 *pcchReaderLen = (DWORD)pcsc_cchReaderLen + 1u;
2333 return (LONG)status;
2337 return (LONG)status;
2340WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, LPDWORD pdwState,
2341 LPDWORD pdwProtocol, LPBYTE pbAtr,
2344 DWORD cchReaderLen = 0;
2345 SCARDCONTEXT hContext = 0;
2346 LPSTR mszReaderNames =
nullptr;
2347 PCSC_LONG status = SCARD_S_SUCCESS;
2348 PCSC_SCARDHANDLE* pCard =
nullptr;
2349 DWORD pcsc_dwState = 0;
2350 DWORD pcsc_dwProtocol = 0;
2351 DWORD pcsc_cbAtrLen = 0;
2354 pcsc_cbAtrLen = (DWORD)*pcbAtrLen;
2356 if (!g_PCSC.pfnSCardStatus)
2357 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardStatus");
2359 pCard = PCSC_GetCardHandleData(hCard);
2362 return SCARD_E_INVALID_VALUE;
2364 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2365 hContext = PCSC_GetCardContextFromHandle(hCard);
2368 return SCARD_E_INVALID_VALUE;
2370 cchReaderLen = SCARD_AUTOALLOCATE;
2371 status = PCSC_SCardStatus_Internal(hCard, (LPSTR)&mszReaderNames, &cchReaderLen, &pcsc_dwState,
2372 &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen, FALSE);
2375 PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames);
2377 *pdwState = pcsc_dwState;
2378 *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(pcsc_dwProtocol);
2380 *pcbAtrLen = pcsc_cbAtrLen;
2381 return PCSC_MapErrorCodeToWinSCard(status);
2384WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard, LPSTR mszReaderNames,
2385 LPDWORD pcchReaderLen, LPDWORD pdwState,
2386 LPDWORD pdwProtocol, LPBYTE pbAtr,
2390 return PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol,
2391 pbAtr, pcbAtrLen, FALSE);
2394WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard, LPWSTR mszReaderNames,
2395 LPDWORD pcchReaderLen, LPDWORD pdwState,
2396 LPDWORD pdwProtocol, LPBYTE pbAtr,
2400 return PCSC_SCardStatus_Internal(hCard, (LPSTR)mszReaderNames, pcchReaderLen, pdwState,
2401 pdwProtocol, pbAtr, pcbAtrLen, TRUE);
2404WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardTransmit(
2405 SCARDHANDLE hCard,
LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength,
2408 PCSC_LONG status = SCARD_S_SUCCESS;
2409 PCSC_SCARDHANDLE* pCard =
nullptr;
2410 PCSC_DWORD cbExtraBytes = 0;
2411 BYTE* pbExtraBytes =
nullptr;
2412 BYTE* pcsc_pbExtraBytes =
nullptr;
2413 PCSC_DWORD pcsc_cbSendLength = (PCSC_DWORD)cbSendLength;
2414 PCSC_DWORD pcsc_cbRecvLength = 0;
2422 } sendPci, recvPci, inRecvPci, inSendPci;
2424 sendPci.ps =
nullptr;
2425 recvPci.ps =
nullptr;
2426 inRecvPci.lps = pioRecvPci;
2427 inSendPci.lpcs = pioSendPci;
2429 if (!g_PCSC.pfnSCardTransmit)
2430 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardTransmit");
2432 pCard = PCSC_GetCardHandleData(hCard);
2435 return SCARD_E_INVALID_VALUE;
2437 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2440 return SCARD_E_INVALID_PARAMETER;
2442 if (*pcbRecvLength == SCARD_AUTOALLOCATE)
2443 return SCARD_E_INVALID_PARAMETER;
2445 pcsc_cbRecvLength = (PCSC_DWORD)*pcbRecvLength;
2447 if (!inSendPci.lpcs)
2449 PCSC_DWORD dwState = 0;
2450 PCSC_DWORD cbAtrLen = 0;
2451 PCSC_DWORD dwProtocol = 0;
2452 PCSC_DWORD cchReaderLen = 0;
2457 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReaderLen, &dwState, &dwProtocol,
2458 nullptr, &cbAtrLen);
2460 if (status == SCARD_S_SUCCESS)
2462 if (dwProtocol == SCARD_PROTOCOL_T0)
2463 sendPci.pcs = PCSC_SCARD_PCI_T0;
2464 else if (dwProtocol == SCARD_PROTOCOL_T1)
2465 sendPci.pcs = PCSC_SCARD_PCI_T1;
2466 else if (dwProtocol == PCSC_SCARD_PROTOCOL_RAW)
2467 sendPci.pcs = PCSC_SCARD_PCI_RAW;
2476 return SCARD_E_NO_MEMORY;
2478 sendPci.ps->dwProtocol = (PCSC_DWORD)inSendPci.lpcs->dwProtocol;
2482 CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
2495 return SCARD_E_NO_MEMORY;
2498 recvPci.ps->dwProtocol = (PCSC_DWORD)inRecvPci.lps->dwProtocol;
2502 CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
2505 status = g_PCSC.pfnSCardTransmit(hCard, sendPci.ps, pbSendBuffer, pcsc_cbSendLength, recvPci.ps,
2506 pbRecvBuffer, &pcsc_cbRecvLength);
2508 *pcbRecvLength = (DWORD)pcsc_cbRecvLength;
2510 if (status == SCARD_S_SUCCESS)
2511 PCSC_AddTransmitCount(pCard->szReader);
2522 CopyMemory(pbExtraBytes, pcsc_pbExtraBytes, cbExtraBytes);
2527 return PCSC_MapErrorCodeToWinSCard(status);
2530WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard,
2531 LPDWORD pcTransmitCount)
2533 PCSC_SCARDHANDLE* pCard =
nullptr;
2535 if (!pcTransmitCount)
2536 return SCARD_E_INVALID_PARAMETER;
2538 pCard = PCSC_GetCardHandleData(hCard);
2541 return SCARD_E_INVALID_VALUE;
2543 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2544 *pcTransmitCount = PCSC_GetTransmitCountOfReader(pCard->szReader);
2545 return SCARD_S_SUCCESS;
2548WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
2549 LPCVOID lpInBuffer, DWORD cbInBufferSize,
2550 LPVOID lpOutBuffer, DWORD cbOutBufferSize,
2551 LPDWORD lpBytesReturned)
2553 DWORD IoCtlFunction = 0;
2554 DWORD IoCtlDeviceType = 0;
2555 BOOL getFeatureRequest = FALSE;
2556 PCSC_LONG status = SCARD_S_SUCCESS;
2557 PCSC_SCARDHANDLE* pCard =
nullptr;
2558 PCSC_DWORD pcsc_dwControlCode = 0;
2559 PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD)cbInBufferSize;
2560 PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD)cbOutBufferSize;
2561 PCSC_DWORD pcsc_BytesReturned = 0;
2563 if (!g_PCSC.pfnSCardControl)
2564 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardControl");
2566 pCard = PCSC_GetCardHandleData(hCard);
2569 return SCARD_E_INVALID_VALUE;
2571 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2582 IoCtlFunction = FUNCTION_FROM_CTL_CODE(dwControlCode);
2583 IoCtlDeviceType = DEVICE_TYPE_FROM_CTL_CODE(dwControlCode);
2585 if (dwControlCode == IOCTL_SMARTCARD_GET_FEATURE_REQUEST)
2586 getFeatureRequest = TRUE;
2588 if (IoCtlDeviceType == FILE_DEVICE_SMARTCARD)
2589 dwControlCode = PCSC_SCARD_CTL_CODE(IoCtlFunction);
2591 pcsc_dwControlCode = (PCSC_DWORD)dwControlCode;
2592 status = g_PCSC.pfnSCardControl(hCard, pcsc_dwControlCode, lpInBuffer, pcsc_cbInBufferSize,
2593 lpOutBuffer, pcsc_cbOutBufferSize, &pcsc_BytesReturned);
2595 *lpBytesReturned = (DWORD)pcsc_BytesReturned;
2597 if (getFeatureRequest)
2603 return SCARD_E_UNEXPECTED;
2607 for (DWORD index = 0; index < count; index++)
2609 if (tlv[index].length != 4)
2610 return SCARD_E_UNEXPECTED;
2614 return PCSC_MapErrorCodeToWinSCard(status);
2617WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard,
2618 DWORD dwAttrId, LPBYTE pbAttr,
2621 SCARDCONTEXT hContext = 0;
2622 BOOL pcbAttrLenAlloc = FALSE;
2623 PCSC_LONG status = SCARD_S_SUCCESS;
2624 PCSC_SCARDHANDLE* pCard =
nullptr;
2625 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
2626 PCSC_DWORD pcsc_cbAttrLen = 0;
2628 if (!g_PCSC.pfnSCardGetAttrib)
2629 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetAttrib");
2631 pCard = PCSC_GetCardHandleData(hCard);
2634 return SCARD_E_INVALID_VALUE;
2636 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2637 hContext = PCSC_GetCardContextFromHandle(hCard);
2640 return SCARD_E_INVALID_HANDLE;
2643 return SCARD_E_INVALID_PARAMETER;
2645 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2648 return SCARD_E_INVALID_PARAMETER;
2649 pcbAttrLenAlloc = TRUE;
2652 pcsc_cbAttrLen = pcbAttrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcbAttrLen;
2654 if (pcbAttrLenAlloc && !g_SCardAutoAllocate)
2657 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId,
nullptr, &pcsc_cbAttrLen);
2659 if (status == SCARD_S_SUCCESS)
2661 BYTE* tmp = (BYTE*)calloc(1, pcsc_cbAttrLen);
2664 return SCARD_E_NO_MEMORY;
2666 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, tmp, &pcsc_cbAttrLen);
2668 if (status != SCARD_S_SUCCESS)
2674 PCSC_AddMemoryBlock(hContext, tmp);
2675 *(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAttr)) = tmp;
2680 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, pbAttr, &pcsc_cbAttrLen);
2683 if (status == SCARD_S_SUCCESS)
2684 *pcbAttrLen = (DWORD)pcsc_cbAttrLen;
2685 return PCSC_MapErrorCodeToWinSCard(status);
2688WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard,
2693 char* namePCSC =
nullptr;
2694 char* pbAttrA =
nullptr;
2696 SCARDCONTEXT hContext = PCSC_GetCardContextFromHandle(hCard);
2699 return SCARD_E_INVALID_HANDLE;
2702 return SCARD_E_INVALID_PARAMETER;
2703 const DWORD cbAttrLen = *pcbAttrLen;
2704 *pcbAttrLen = SCARD_AUTOALLOCATE;
2705 LONG status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A,
2706 (LPBYTE)&pbAttrA, pcbAttrLen);
2708 if (status != SCARD_S_SUCCESS)
2710 WCHAR* pbAttrW =
nullptr;
2712 *pcbAttrLen = SCARD_AUTOALLOCATE;
2713 status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W,
2714 (LPBYTE)&pbAttrW, pcbAttrLen);
2716 if (status != SCARD_S_SUCCESS)
2719 namePCSC = ConvertMszWCharNToUtf8Alloc(pbAttrW, *pcbAttrLen,
nullptr);
2720 PCSC_SCardFreeMemory_Internal(hContext, pbAttrW);
2724 namePCSC = strndup(pbAttrA, *pcbAttrLen);
2727 return SCARD_E_NO_MEMORY;
2729 PCSC_SCardFreeMemory_Internal(hContext, pbAttrA);
2732 size_t length = strnlen(namePCSC, *pcbAttrLen);
2734 if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W)
2737 WCHAR* friendlyNameW = ConvertUtf8NToWCharAlloc(namePCSC, length, &size);
2741 status = SCARD_E_NO_MEMORY;
2746 if (cbAttrLen == SCARD_AUTOALLOCATE)
2748 WINPR_ASSERT(length <= UINT32_MAX /
sizeof(WCHAR));
2749 *(WINPR_PACKED_ALIGN_CAST(WCHAR**, pbAttr)) = friendlyNameW;
2750 *pcbAttrLen = (UINT32)length *
sizeof(WCHAR);
2751 PCSC_AddMemoryBlock(hContext, friendlyNameW);
2755 const size_t wlen = length *
sizeof(WCHAR);
2756 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(uint32_t, wlen);
2757 if ((wlen > cbAttrLen) && pbAttr)
2758 status = SCARD_E_INSUFFICIENT_BUFFER;
2760 CopyMemory(pbAttr, friendlyNameW, (length *
sizeof(WCHAR)));
2762 free(friendlyNameW);
2770 if (cbAttrLen == SCARD_AUTOALLOCATE)
2772 *(WINPR_PACKED_ALIGN_CAST(CHAR**, pbAttr)) = namePCSC;
2773 WINPR_ASSERT(length <= UINT32_MAX);
2774 *pcbAttrLen = (UINT32)length;
2775 PCSC_AddMemoryBlock(hContext, namePCSC);
2779 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(uint32_t, length);
2780 if ((length > cbAttrLen) && pbAttr)
2781 status = SCARD_E_INSUFFICIENT_BUFFER;
2783 CopyMemory(pbAttr, namePCSC, length);
2792static LONG PCSC_ReadDeviceSystemNameGet(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2793 DWORD dwAttrId, LPBYTE* pbAttr, LPDWORD pcbAttrLen)
2795 PCSC_DWORD cchReader = 0;
2796 PCSC_DWORD cbAtr = 0;
2797 PCSC_DWORD dwState = 0;
2798 PCSC_DWORD dwProtocol = 0;
2800 const PCSC_LONG rc =
2801 g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReader, &dwState, &dwProtocol,
nullptr, &cbAtr);
2802 if (rc != SCARD_S_SUCCESS)
2805 void* tmp = calloc(cchReader + 1,
sizeof(CHAR));
2807 return SCARD_E_NO_MEMORY;
2808 const PCSC_LONG rc2 =
2809 g_PCSC.pfnSCardStatus(hCard, tmp, &cchReader, &dwState, &dwProtocol,
nullptr, &cbAtr);
2810 if (rc2 != SCARD_S_SUCCESS)
2816 if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2819 void* data = ConvertMszUtf8NToWCharAlloc(tmp, cchReader, &len);
2823 return SCARD_E_NO_MEMORY;
2825 len *=
sizeof(WCHAR);
2827 cchReader = WINPR_ASSERTING_INT_CAST(PCSC_DWORD, len);
2833 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, cchReader);
2834 return SCARD_S_SUCCESS;
2837static LONG PCSC_ReadDeviceSystemName(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2838 DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
2840 BYTE* tmp =
nullptr;
2841 DWORD cbAttrLen = 0;
2842 const LONG rc = PCSC_ReadDeviceSystemNameGet(hContext, hCard, dwAttrId, &tmp, &cbAttrLen);
2843 if (rc != SCARD_S_SUCCESS)
2846 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2848 if (!PCSC_AddMemoryBlock(hContext, tmp))
2851 return SCARD_E_NO_MEMORY;
2854 *pcbAttrLen = cbAttrLen;
2855 *(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAttr)) = tmp;
2856 return SCARD_S_SUCCESS;
2860 memcpy(pbAttr, tmp, MIN(cbAttrLen, *pcbAttrLen));
2865 if (cbAttrLen > *pcbAttrLen)
2866 return SCARD_E_INSUFFICIENT_BUFFER;
2869 *pcbAttrLen = cbAttrLen;
2871 return SCARD_S_SUCCESS;
2874WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
2875 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2877 DWORD cbAttrLen = 0;
2878 SCARDCONTEXT hContext = 0;
2879 BOOL pcbAttrLenAlloc = FALSE;
2880 PCSC_LONG status = SCARD_S_SUCCESS;
2882 if (
nullptr == pcbAttrLen)
2883 return SCARD_E_INVALID_PARAMETER;
2885 cbAttrLen = *pcbAttrLen;
2887 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2889 if (
nullptr == pbAttr)
2890 return SCARD_E_INVALID_PARAMETER;
2892 pcbAttrLenAlloc = TRUE;
2893 *(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAttr)) =
nullptr;
2901 if (*pcbAttrLen > PCSC_MAX_BUFFER_SIZE)
2902 *pcbAttrLen = PCSC_MAX_BUFFER_SIZE;
2905 hContext = PCSC_GetCardContextFromHandle(hCard);
2908 return SCARD_E_INVALID_HANDLE;
2910 if ((dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) ||
2911 (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W))
2913 return PCSC_SCardGetAttrib_FriendlyName(hCard, dwAttrId, pbAttr, pcbAttrLen);
2916 status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen);
2918 if (status == SCARD_S_SUCCESS)
2920 if (dwAttrId == SCARD_ATTR_VENDOR_NAME)
2924 const char* vendorName =
nullptr;
2931 if (pcbAttrLenAlloc)
2932 vendorName = (
char*)*(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAttr));
2934 vendorName = (
char*)pbAttr;
2938 size_t len = strnlen(vendorName, *pcbAttrLen);
2939 WINPR_ASSERT(len < UINT32_MAX);
2940 *pcbAttrLen = (DWORD)len + 1;
2949 if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
2951 if (!pcbAttrLenAlloc)
2953 PCSC_DWORD dwState = 0;
2954 PCSC_DWORD cbAtrLen = 0;
2955 PCSC_DWORD dwProtocol = 0;
2956 PCSC_DWORD cchReaderLen = 0;
2957 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReaderLen, &dwState, &dwProtocol,
2958 nullptr, &cbAtrLen);
2960 if (status == SCARD_S_SUCCESS)
2962 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2963 return SCARD_E_INSUFFICIENT_BUFFER;
2966 *(WINPR_PACKED_ALIGN_CAST(DWORD*, pbAttr)) =
2967 PCSC_ConvertProtocolsToWinSCard(dwProtocol);
2968 *pcbAttrLen =
sizeof(DWORD);
2972 else if (dwAttrId == SCARD_ATTR_CHANNEL_ID)
2974 if (!pcbAttrLenAlloc)
2976 UINT32 channelType = 0x20;
2977 UINT32 channelNumber = 0;
2979 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2980 return SCARD_E_INSUFFICIENT_BUFFER;
2982 status = SCARD_S_SUCCESS;
2984 *(WINPR_PACKED_ALIGN_CAST(DWORD*, pbAttr)) =
2985 (channelType << 16u) | channelNumber;
2986 *pcbAttrLen =
sizeof(DWORD);
2989 else if (dwAttrId == SCARD_ATTR_VENDOR_IFD_TYPE)
2992 else if (dwAttrId == SCARD_ATTR_DEFAULT_CLK)
2995 else if (dwAttrId == SCARD_ATTR_DEFAULT_DATA_RATE)
2998 else if (dwAttrId == SCARD_ATTR_MAX_CLK)
3001 else if (dwAttrId == SCARD_ATTR_MAX_DATA_RATE)
3004 else if (dwAttrId == SCARD_ATTR_MAX_IFSD)
3007 else if (dwAttrId == SCARD_ATTR_CHARACTERISTICS)
3010 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_A)
3012 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
3014 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
3016 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
3018 else if (dwAttrId == SCARD_ATTR_DEVICE_UNIT)
3021 else if (dwAttrId == SCARD_ATTR_POWER_MGMT_SUPPORT)
3024 else if (dwAttrId == SCARD_ATTR_CURRENT_CLK)
3027 else if (dwAttrId == SCARD_ATTR_CURRENT_F)
3030 else if (dwAttrId == SCARD_ATTR_CURRENT_D)
3033 else if (dwAttrId == SCARD_ATTR_CURRENT_N)
3036 else if (dwAttrId == SCARD_ATTR_CURRENT_CWT)
3039 else if (dwAttrId == SCARD_ATTR_CURRENT_BWT)
3042 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSC)
3045 else if (dwAttrId == SCARD_ATTR_CURRENT_EBC_ENCODING)
3048 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSD)
3051 else if (dwAttrId == SCARD_ATTR_ICC_TYPE_PER_ATR)
3056 return WINPR_ASSERTING_INT_CAST(LONG, status);
3059WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
3060 LPCBYTE pbAttr, DWORD cbAttrLen)
3062 PCSC_LONG status = SCARD_S_SUCCESS;
3063 PCSC_SCARDHANDLE* pCard =
nullptr;
3064 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
3065 PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD)cbAttrLen;
3067 if (!g_PCSC.pfnSCardSetAttrib)
3068 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardSetAttrib");
3070 pCard = PCSC_GetCardHandleData(hCard);
3073 return SCARD_E_INVALID_VALUE;
3075 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
3076 status = g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
3077 return PCSC_MapErrorCodeToWinSCard(status);
3080WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc)
3082 WINPR_UNUSED(pDlgStruc);
3084 return SCARD_E_UNSUPPORTED_FEATURE;
3087WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pDlgStruc)
3089 WINPR_UNUSED(pDlgStruc);
3090 return SCARD_E_UNSUPPORTED_FEATURE;
3093WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_GetOpenCardNameA(
LPOPENCARDNAMEA pDlgStruc)
3095 WINPR_UNUSED(pDlgStruc);
3096 return SCARD_E_UNSUPPORTED_FEATURE;
3099WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_GetOpenCardNameW(
LPOPENCARDNAMEW pDlgStruc)
3101 WINPR_UNUSED(pDlgStruc);
3102 return SCARD_E_UNSUPPORTED_FEATURE;
3105WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardDlgExtendedError(
void)
3108 return SCARD_E_UNSUPPORTED_FEATURE;
3112static char* card_id_and_name_a(
const UUID* CardIdentifier, LPCSTR LookupName)
3114 if (!CardIdentifier || !LookupName)
3117 size_t len = strlen(LookupName) + 34;
3118 char*
id = malloc(len);
3122 (void)snprintf(
id, len,
"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X\\%s",
3123 CardIdentifier->Data1, CardIdentifier->Data2, CardIdentifier->Data3,
3124 CardIdentifier->Data4[0], CardIdentifier->Data4[1], CardIdentifier->Data4[2],
3125 CardIdentifier->Data4[3], CardIdentifier->Data4[4], CardIdentifier->Data4[5],
3126 CardIdentifier->Data4[6], CardIdentifier->Data4[7], LookupName);
3131static char* card_id_and_name_w(
const UUID* CardIdentifier, LPCWSTR LookupName)
3133 char* res =
nullptr;
3134 char* tmp = ConvertWCharToUtf8Alloc(LookupName,
nullptr);
3137 res = card_id_and_name_a(CardIdentifier, tmp);
3142WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReadCacheA(SCARDCONTEXT hContext,
3143 UUID* CardIdentifier,
3144 DWORD FreshnessCounter,
3145 LPSTR LookupName, PBYTE Data,
3148 PCSC_CACHE_ITEM* data =
nullptr;
3149 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3151 return SCARD_E_INVALID_HANDLE;
3153 char*
id = card_id_and_name_a(CardIdentifier, LookupName);
3155 data = HashTable_GetItemValue(ctx->cache,
id);
3161 return SCARD_W_CACHE_ITEM_NOT_FOUND;
3164 if (FreshnessCounter != data->freshness)
3167 return SCARD_W_CACHE_ITEM_STALE;
3170 if (*DataLen == SCARD_AUTOALLOCATE)
3172 BYTE* mem = calloc(1, data->len);
3174 return SCARD_E_NO_MEMORY;
3176 if (!PCSC_AddMemoryBlock(hContext, mem))
3179 return SCARD_E_NO_MEMORY;
3182 memcpy(mem, data->data, data->len);
3183 *(WINPR_PACKED_ALIGN_CAST(BYTE**, Data)) = mem;
3187 if (data->len > *DataLen)
3188 return SCARD_E_INSUFFICIENT_BUFFER;
3189 memcpy(Data, data->data, data->len);
3192 *DataLen = data->len;
3193 return SCARD_S_SUCCESS;
3196WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReadCacheW(SCARDCONTEXT hContext,
3197 UUID* CardIdentifier,
3198 DWORD FreshnessCounter,
3199 LPWSTR LookupName, PBYTE Data,
3202 PCSC_CACHE_ITEM* data =
nullptr;
3203 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3205 return SCARD_E_INVALID_HANDLE;
3207 char*
id = card_id_and_name_w(CardIdentifier, LookupName);
3209 data = HashTable_GetItemValue(ctx->cache,
id);
3215 return SCARD_W_CACHE_ITEM_NOT_FOUND;
3218 if (FreshnessCounter != data->freshness)
3221 return SCARD_W_CACHE_ITEM_STALE;
3224 if (*DataLen == SCARD_AUTOALLOCATE)
3226 BYTE* mem = calloc(1, data->len);
3228 return SCARD_E_NO_MEMORY;
3230 if (!PCSC_AddMemoryBlock(hContext, mem))
3233 return SCARD_E_NO_MEMORY;
3236 memcpy(mem, data->data, data->len);
3237 *(WINPR_PACKED_ALIGN_CAST(BYTE**, Data)) = mem;
3241 if (data->len > *DataLen)
3242 return SCARD_E_INSUFFICIENT_BUFFER;
3243 memcpy(Data, data->data, data->len);
3245 *DataLen = data->len;
3246 return SCARD_S_SUCCESS;
3249WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardWriteCacheA(SCARDCONTEXT hContext,
3250 UUID* CardIdentifier,
3251 DWORD FreshnessCounter,
3252 LPSTR LookupName, PBYTE Data,
3255 PCSC_CACHE_ITEM* data =
nullptr;
3256 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3260 return SCARD_E_FILE_NOT_FOUND;
3262 id = card_id_and_name_a(CardIdentifier, LookupName);
3265 return SCARD_E_NO_MEMORY;
3267 data = malloc(
sizeof(PCSC_CACHE_ITEM));
3271 return SCARD_E_NO_MEMORY;
3273 data->data = calloc(DataLen, 1);
3278 return SCARD_E_NO_MEMORY;
3280 data->len = DataLen;
3281 data->freshness = FreshnessCounter;
3282 memcpy(data->data, Data, data->len);
3284 HashTable_Remove(ctx->cache,
id);
3285 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
3290 pcsc_cache_item_free(data);
3291 return SCARD_E_NO_MEMORY;
3295 return SCARD_S_SUCCESS;
3298WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardWriteCacheW(SCARDCONTEXT hContext,
3299 UUID* CardIdentifier,
3300 DWORD FreshnessCounter,
3301 LPWSTR LookupName, PBYTE Data,
3304 PCSC_CACHE_ITEM* data =
nullptr;
3305 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3308 return SCARD_E_FILE_NOT_FOUND;
3310 id = card_id_and_name_w(CardIdentifier, LookupName);
3313 return SCARD_E_NO_MEMORY;
3315 data = malloc(
sizeof(PCSC_CACHE_ITEM));
3319 return SCARD_E_NO_MEMORY;
3321 data->data = malloc(DataLen);
3326 return SCARD_E_NO_MEMORY;
3328 data->len = DataLen;
3329 data->freshness = FreshnessCounter;
3330 memcpy(data->data, Data, data->len);
3332 HashTable_Remove(ctx->cache,
id);
3333 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
3338 pcsc_cache_item_free(data);
3339 return SCARD_E_NO_MEMORY;
3343 return SCARD_S_SUCCESS;
3346WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetReaderIconA(
3347 SCARDCONTEXT hContext, LPCSTR szReaderName,
3348 LPBYTE pbIcon , LPDWORD pcbIcon)
3350 WINPR_UNUSED(hContext);
3351 WINPR_UNUSED(szReaderName);
3352 WINPR_UNUSED(pbIcon);
3353 WINPR_ASSERT(pcbIcon);
3355 return SCARD_E_UNSUPPORTED_FEATURE;
3358WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetReaderIconW(
3359 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3360 LPBYTE pbIcon , LPDWORD pcbIcon)
3362 WINPR_UNUSED(hContext);
3363 WINPR_UNUSED(szReaderName);
3364 WINPR_UNUSED(pbIcon);
3365 WINPR_ASSERT(pcbIcon);
3367 return SCARD_E_UNSUPPORTED_FEATURE;
3370WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetDeviceTypeIdA(SCARDCONTEXT hContext,
3371 LPCSTR szReaderName,
3372 LPDWORD pdwDeviceTypeId)
3374 WINPR_UNUSED(hContext);
3375 WINPR_UNUSED(szReaderName);
3376 WINPR_UNUSED(pdwDeviceTypeId);
3377 if (pdwDeviceTypeId)
3378 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3379 return SCARD_S_SUCCESS;
3383static LONG WINAPI PCSC_SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
3384 LPDWORD pdwDeviceTypeId)
3386 WINPR_UNUSED(hContext);
3387 WINPR_UNUSED(szReaderName);
3388 if (pdwDeviceTypeId)
3389 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3390 return SCARD_S_SUCCESS;
3394static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdA(
3395 SCARDCONTEXT hContext, LPCSTR szReaderName,
3396 LPSTR szDeviceInstanceId ,
3397 LPDWORD pcchDeviceInstanceId )
3399 WINPR_UNUSED(hContext);
3400 WINPR_UNUSED(szReaderName);
3401 WINPR_UNUSED(szDeviceInstanceId);
3402 WINPR_UNUSED(pcchDeviceInstanceId);
3403 return SCARD_E_UNSUPPORTED_FEATURE;
3407static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdW(
3408 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3409 LPWSTR szDeviceInstanceId ,
3410 LPDWORD pcchDeviceInstanceId )
3412 WINPR_UNUSED(hContext);
3413 WINPR_UNUSED(szReaderName);
3414 WINPR_UNUSED(szDeviceInstanceId);
3415 WINPR_UNUSED(pcchDeviceInstanceId);
3416 return SCARD_E_UNSUPPORTED_FEATURE;
3420static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdA(
3421 SCARDCONTEXT hContext, LPCSTR szDeviceInstanceId,
3423 LPDWORD pcchReaders )
3425 WINPR_UNUSED(hContext);
3426 WINPR_UNUSED(szDeviceInstanceId);
3427 WINPR_UNUSED(mszReaders);
3428 WINPR_UNUSED(pcchReaders);
3429 return SCARD_E_UNSUPPORTED_FEATURE;
3433static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdW(
3434 SCARDCONTEXT hContext, LPCWSTR szDeviceInstanceId,
3436 LPDWORD pcchReaders )
3438 WINPR_UNUSED(hContext);
3439 WINPR_UNUSED(szDeviceInstanceId);
3440 WINPR_UNUSED(mszReaders);
3441 WINPR_UNUSED(pcchReaders);
3442 return SCARD_E_UNSUPPORTED_FEATURE;
3446static LONG WINAPI PCSC_SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent)
3449 WINPR_UNUSED(hContext);
3450 WINPR_UNUSED(dwEvent);
3451 return SCARD_E_UNSUPPORTED_FEATURE;
3456unsigned int determineMacOSXVersion(
void)
3460 char* kernelVersion =
nullptr;
3461 char* tok =
nullptr;
3462 unsigned int version = 0;
3463 long majorVersion = 0;
3464 long minorVersion = 0;
3465 long patchVersion = 0;
3467 char* context =
nullptr;
3469 mib[1] = KERN_OSRELEASE;
3471 if (sysctl(mib, 2,
nullptr, &len,
nullptr, 0) != 0)
3474 kernelVersion = calloc(len,
sizeof(
char));
3479 if (sysctl(mib, 2, kernelVersion, &len,
nullptr, 0) != 0)
3481 free(kernelVersion);
3485 tok = strtok_s(kernelVersion,
".", &context);
3493 majorVersion = strtol(tok,
nullptr, 0);
3501 minorVersion = strtol(tok,
nullptr, 0);
3509 patchVersion = strtol(tok,
nullptr, 0);
3517 tok = strtok_s(
nullptr,
".", &context);
3524 if (majorVersion < 5)
3526 if (minorVersion < 4)
3527 version = 0x10000000;
3529 version = 0x10010000;
3533 switch (majorVersion)
3536 version = 0x10010000;
3540 version = 0x10020000;
3544 version = 0x10030000;
3548 version = 0x10040000;
3552 version = 0x10050000;
3556 version = 0x10060000;
3560 version = 0x10070000;
3564 version = 0x10080000;
3568 version = 0x10090000;
3572 version = 0x10100000;
3576 version |= (minorVersion << 8) | (patchVersion);
3580 free(kernelVersion);
3589 PCSC_SCardEstablishContext,
3590 PCSC_SCardReleaseContext,
3591 PCSC_SCardIsValidContext,
3592 PCSC_SCardListReaderGroupsA,
3593 PCSC_SCardListReaderGroupsW,
3594 PCSC_SCardListReadersA,
3595 PCSC_SCardListReadersW,
3596 PCSC_SCardListCardsA,
3597 PCSC_SCardListCardsW,
3598 PCSC_SCardListInterfacesA,
3599 PCSC_SCardListInterfacesW,
3600 PCSC_SCardGetProviderIdA,
3601 PCSC_SCardGetProviderIdW,
3602 PCSC_SCardGetCardTypeProviderNameA,
3603 PCSC_SCardGetCardTypeProviderNameW,
3604 PCSC_SCardIntroduceReaderGroupA,
3605 PCSC_SCardIntroduceReaderGroupW,
3606 PCSC_SCardForgetReaderGroupA,
3607 PCSC_SCardForgetReaderGroupW,
3608 PCSC_SCardIntroduceReaderA,
3609 PCSC_SCardIntroduceReaderW,
3610 PCSC_SCardForgetReaderA,
3611 PCSC_SCardForgetReaderW,
3612 PCSC_SCardAddReaderToGroupA,
3613 PCSC_SCardAddReaderToGroupW,
3614 PCSC_SCardRemoveReaderFromGroupA,
3615 PCSC_SCardRemoveReaderFromGroupW,
3616 PCSC_SCardIntroduceCardTypeA,
3617 PCSC_SCardIntroduceCardTypeW,
3618 PCSC_SCardSetCardTypeProviderNameA,
3619 PCSC_SCardSetCardTypeProviderNameW,
3620 PCSC_SCardForgetCardTypeA,
3621 PCSC_SCardForgetCardTypeW,
3622 PCSC_SCardFreeMemory,
3623 PCSC_SCardAccessStartedEvent,
3624 PCSC_SCardReleaseStartedEvent,
3625 PCSC_SCardLocateCardsA,
3626 PCSC_SCardLocateCardsW,
3627 PCSC_SCardLocateCardsByATRA,
3628 PCSC_SCardLocateCardsByATRW,
3629 PCSC_SCardGetStatusChangeA,
3630 PCSC_SCardGetStatusChangeW,
3634 PCSC_SCardReconnect,
3635 PCSC_SCardDisconnect,
3636 PCSC_SCardBeginTransaction,
3637 PCSC_SCardEndTransaction,
3638 PCSC_SCardCancelTransaction,
3643 PCSC_SCardGetTransmitCount,
3645 PCSC_SCardGetAttrib,
3646 PCSC_SCardSetAttrib,
3647 PCSC_SCardUIDlgSelectCardA,
3648 PCSC_SCardUIDlgSelectCardW,
3649 PCSC_GetOpenCardNameA,
3650 PCSC_GetOpenCardNameW,
3651 PCSC_SCardDlgExtendedError,
3652 PCSC_SCardReadCacheA,
3653 PCSC_SCardReadCacheW,
3654 PCSC_SCardWriteCacheA,
3655 PCSC_SCardWriteCacheW,
3656 PCSC_SCardGetReaderIconA,
3657 PCSC_SCardGetReaderIconW,
3658 PCSC_SCardGetDeviceTypeIdA,
3659 PCSC_SCardGetDeviceTypeIdW,
3660 PCSC_SCardGetReaderDeviceInstanceIdA,
3661 PCSC_SCardGetReaderDeviceInstanceIdW,
3662 PCSC_SCardListReadersWithDeviceInstanceIdA,
3663 PCSC_SCardListReadersWithDeviceInstanceIdW,
3669 return &PCSC_SCardApiFunctionTable;
3672int PCSC_InitializeSCardApi(
void)
3675 SetEnvironmentVariableA(
"PCSCLITE_NO_BLOCKING",
"1");
3677 g_PCSCModule = LoadLibraryX(
"/System/Library/Frameworks/PCSC.framework/PCSC");
3678 OSXVersion = determineMacOSXVersion();
3680 if (OSXVersion == 0)
3684 g_PCSCModule = LoadLibraryA(
"libpcsclite.so.1");
3687 g_PCSCModule = LoadLibraryA(
"libpcsclite.so");
3696#undef SCardListReaderGroups
3697#undef SCardListReaders
3698#undef SCardListCards
3699#undef SCardListInterfaces
3700#undef SCardGetProviderId
3701#undef SCardGetCardTypeProviderName
3702#undef SCardIntroduceReaderGroup
3703#undef SCardForgetReaderGroup
3704#undef SCardIntroduceReader
3705#undef SCardForgetReader
3706#undef SCardAddReaderToGroup
3707#undef SCardRemoveReaderFromGroup
3708#undef SCardIntroduceCardType
3709#undef SCardSetCardTypeProviderName
3710#undef SCardForgetCardType
3711#undef SCardLocateCards
3712#undef SCardLocateCardsByATR
3713#undef SCardGetStatusChange
3716#undef SCardUIDlgSelectCard
3717#undef GetOpenCardName
3718#undef SCardReadCache
3719#undef SCardWriteCache
3720#undef SCardGetReaderIcon
3721#undef SCardGetDeviceTypeId
3722#undef SCardGetReaderDeviceInstanceId
3723#undef SCardListReadersWithDeviceInstanceId
3725 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEstablishContext);
3726 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReleaseContext);
3727 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardIsValidContext);
3728 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardConnect);
3729 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReconnect);
3730 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardDisconnect);
3731 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardBeginTransaction);
3732 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEndTransaction);
3733 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardStatus);
3734 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetStatusChange);
3738 if (OSXVersion >= 0x10050600)
3740 WINSCARD_LOAD_PROC_EX(g_PCSCModule, g_PCSC, SCardControl, SCardControl132);
3744 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3747 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3749 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardTransmit);
3750 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaderGroups);
3751 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaders);
3752 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardCancel);
3753 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetAttrib);
3754 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardSetAttrib);
3755 g_PCSC.pfnSCardFreeMemory =
nullptr;
3757 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardFreeMemory);
3760 if (g_PCSC.pfnSCardFreeMemory)
3761 g_SCardAutoAllocate = TRUE;
3763#ifdef DISABLE_PCSC_SCARD_AUTOALLOCATE
3764 g_PCSC.pfnSCardFreeMemory =
nullptr;
3765 g_SCardAutoAllocate = FALSE;
3768 g_PnP_Notification = FALSE;
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree