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);
681static void PCSC_SetTransactionLocked(SCARDHANDLE hCard, BOOL locked)
686 ListDictionary_Lock(g_CardHandles);
687 PCSC_SCARDHANDLE* pCard = ListDictionary_GetItemValue(g_CardHandles, (
void*)hCard);
689 pCard->isTransactionLocked = locked;
690 ListDictionary_Unlock(g_CardHandles);
693static void PCSC_AddTransmitCountOfHandle(SCARDHANDLE hCard)
698 ListDictionary_Lock(g_CardHandles);
699 const PCSC_SCARDHANDLE* pCard = ListDictionary_GetItemValue(g_CardHandles, (
void*)hCard);
701 PCSC_AddTransmitCount(pCard->szReader);
702 ListDictionary_Unlock(g_CardHandles);
706static SCARDCONTEXT PCSC_GetCardContextFromHandle(SCARDHANDLE hCard)
708 PCSC_SCARDHANDLE* pCard =
nullptr;
709 pCard = PCSC_GetCardHandleData(hCard);
714 return pCard->hSharedContext;
717static BOOL PCSC_WaitForCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard, BOOL shared)
720 PCSC_SCARDHANDLE* pCard =
nullptr;
721 PCSC_SCARDCONTEXT* pContext =
nullptr;
726 pContext = PCSC_GetCardContextData(hContext);
731 if (!pContext->owner)
738 pCard = PCSC_GetCardHandleData(hCard);
743 shared = pCard->shared;
744 hContext = pCard->hSharedContext;
745 pContext = PCSC_GetCardContextData(hContext);
750 if (!pContext->owner)
754 pContext->owner = hCard;
759 if (pContext->owner == hCard)
771static BOOL PCSC_ReleaseCardAccess(SCARDCONTEXT hContext, SCARDHANDLE hCard)
773 PCSC_SCARDHANDLE* pCard =
nullptr;
774 PCSC_SCARDCONTEXT* pContext =
nullptr;
779 pContext = PCSC_GetCardContextData(hContext);
784 hCard = pContext->owner;
789 pCard = PCSC_GetCardHandleData(hCard);
799 pCard = PCSC_GetCardHandleData(hCard);
804 hContext = pCard->hSharedContext;
805 pContext = PCSC_GetCardContextData(hContext);
810 if (pContext->owner == hCard)
819static void PCSC_DisconnectCardHandle(PCSC_SCARDHANDLE* pCard)
824 PCSC_SCARDCONTEXT* pContext = PCSC_GetCardContextData(pCard->hSharedContext);
826 ListDictionary_Remove(g_CardHandles, (
void*)pCard->hCard);
830 WLog_ERR(TAG,
"PCSC_DisconnectCardHandle: null pContext!");
834 pContext->dwCardHandleCount--;
837WINPR_ATTR_MALLOC(PCSC_DisconnectCardHandle, 1)
838static PCSC_SCARDHANDLE* PCSC_ConnectCardHandle(SCARDCONTEXT hSharedContext, SCARDHANDLE hCard,
844 PCSC_SCARDCONTEXT* pContext = PCSC_GetCardContextData(hSharedContext);
848 WLog_ERR(TAG,
"PCSC_ConnectCardHandle: null pContext!");
852 PCSC_SCARDHANDLE* pCard = (PCSC_SCARDHANDLE*)calloc(1,
sizeof(PCSC_SCARDHANDLE));
857 pCard->hSharedContext = hSharedContext;
858 pCard->hCard = hCard;
861 pCard->szReader = _strdup(szReader);
862 if (!pCard->szReader)
866 if (!ListDictionary_Add(g_CardHandles, (
void*)hCard, (
void*)pCard))
869 pContext->dwCardHandleCount++;
872 cardHandleFreeVoid(pCard);
876static BOOL PCSC_AddMemoryBlock(SCARDCONTEXT hContext,
void* pvMem)
880 return ListDictionary_Add(g_MemoryBlocks, pvMem, (
void*)hContext);
884static void* PCSC_RemoveMemoryBlock(SCARDCONTEXT hContext,
void* pvMem)
886 WINPR_UNUSED(hContext);
891 return ListDictionary_Take(g_MemoryBlocks, pvMem);
898static LONG WINAPI PCSC_SCardEstablishContext_Internal(DWORD dwScope, LPCVOID pvReserved1,
900 LPSCARDCONTEXT phContext)
902 WINPR_UNUSED(dwScope);
903 PCSC_LONG status = SCARD_S_SUCCESS;
905 if (!g_PCSC.pfnSCardEstablishContext)
906 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEstablishContext");
909 g_PCSC.pfnSCardEstablishContext(SCARD_SCOPE_SYSTEM, pvReserved1, pvReserved2, phContext);
910 return PCSC_MapErrorCodeToWinSCard(status);
914static LONG WINAPI PCSC_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
915 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
919 status = PCSC_SCardEstablishContext_Internal(dwScope, pvReserved1, pvReserved2, phContext);
921 if (status == SCARD_S_SUCCESS)
922 PCSC_EstablishCardContext(*phContext);
928static LONG WINAPI PCSC_SCardReleaseContext_Internal(SCARDCONTEXT hContext)
930 PCSC_LONG status = SCARD_S_SUCCESS;
932 if (!g_PCSC.pfnSCardReleaseContext)
933 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardReleaseContext");
937 WLog_ERR(TAG,
"SCardReleaseContext: null hContext");
938 return PCSC_MapErrorCodeToWinSCard(SCARD_E_INVALID_HANDLE);
941 status = g_PCSC.pfnSCardReleaseContext(hContext);
942 return PCSC_MapErrorCodeToWinSCard(status);
946static LONG WINAPI PCSC_SCardReleaseContext(SCARDCONTEXT hContext)
948 LONG status = SCARD_S_SUCCESS;
950 status = PCSC_SCardReleaseContext_Internal(hContext);
951 PCSC_ReleaseCardContext(hContext);
957static LONG WINAPI PCSC_SCardIsValidContext(SCARDCONTEXT hContext)
959 PCSC_LONG status = SCARD_S_SUCCESS;
961 if (!g_PCSC.pfnSCardIsValidContext)
962 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardIsValidContext");
964 status = g_PCSC.pfnSCardIsValidContext(hContext);
965 return PCSC_MapErrorCodeToWinSCard(status);
969static LONG WINAPI PCSC_SCardListReaderGroups_Internal(SCARDCONTEXT hContext, LPSTR mszGroups,
972 PCSC_LONG status = SCARD_S_SUCCESS;
973 BOOL pcchGroupsAlloc = FALSE;
974 PCSC_DWORD pcsc_cchGroups = 0;
977 return SCARD_E_INVALID_PARAMETER;
979 if (!g_PCSC.pfnSCardListReaderGroups)
980 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
982 if (*pcchGroups == SCARD_AUTOALLOCATE)
983 pcchGroupsAlloc = TRUE;
985 pcsc_cchGroups = pcchGroupsAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcchGroups;
987 if (pcchGroupsAlloc && !g_SCardAutoAllocate)
990 status = g_PCSC.pfnSCardListReaderGroups(hContext,
nullptr, &pcsc_cchGroups);
992 if (status == SCARD_S_SUCCESS)
994 LPSTR tmp = calloc(1, pcsc_cchGroups);
997 return SCARD_E_NO_MEMORY;
999 status = g_PCSC.pfnSCardListReaderGroups(hContext, tmp, &pcsc_cchGroups);
1001 if (status != SCARD_S_SUCCESS)
1007 PCSC_AddMemoryBlock(hContext, tmp);
1009 *(WINPR_PACKED_ALIGN_CAST(LPSTR*, mszGroups)) = tmp;
1014 status = g_PCSC.pfnSCardListReaderGroups(hContext, mszGroups, &pcsc_cchGroups);
1017 *pcchGroups = (DWORD)pcsc_cchGroups;
1018 return PCSC_MapErrorCodeToWinSCard(status);
1022static LONG WINAPI PCSC_SCardListReaderGroupsA(SCARDCONTEXT hContext, LPSTR mszGroups,
1025 LONG status = SCARD_S_SUCCESS;
1027 if (!g_PCSC.pfnSCardListReaderGroups)
1028 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
1030 if (!PCSC_LockCardContext(hContext))
1031 return SCARD_E_INVALID_HANDLE;
1033 status = PCSC_SCardListReaderGroups_Internal(hContext, mszGroups, pcchGroups);
1035 if (!PCSC_UnlockCardContext(hContext))
1036 return SCARD_E_INVALID_HANDLE;
1042static LONG WINAPI PCSC_SCardListReaderGroupsW(SCARDCONTEXT hContext, LPWSTR mszGroups,
1045 LPSTR mszGroupsA =
nullptr;
1046 LPSTR* pMszGroupsA = &mszGroupsA;
1047 LONG status = SCARD_S_SUCCESS;
1049 if (!g_PCSC.pfnSCardListReaderGroups)
1050 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaderGroups");
1052 if (!PCSC_LockCardContext(hContext))
1053 return SCARD_E_INVALID_HANDLE;
1055 status = PCSC_SCardListReaderGroups_Internal(hContext, (LPSTR)&mszGroupsA, pcchGroups);
1057 if (status == SCARD_S_SUCCESS)
1060 WCHAR* str = ConvertMszUtf8NToWCharAlloc(*pMszGroupsA, *pcchGroups, &size);
1063 status = SCARD_E_NO_MEMORY;
1066 *(WINPR_PACKED_ALIGN_CAST(WCHAR**, mszGroups)) = str;
1067 *pcchGroups = (DWORD)size;
1068 PCSC_AddMemoryBlock(hContext, str);
1069 PCSC_SCardFreeMemory_Internal(hContext, *pMszGroupsA);
1073 if (!PCSC_UnlockCardContext(hContext))
1074 return SCARD_E_INVALID_HANDLE;
1080static LONG WINAPI PCSC_SCardListReaders_Internal(SCARDCONTEXT hContext, LPCSTR mszGroups,
1081 LPSTR mszReaders, LPDWORD pcchReaders)
1083 PCSC_LONG status = SCARD_S_SUCCESS;
1084 BOOL pcchReadersAlloc = FALSE;
1085 PCSC_DWORD pcsc_cchReaders = 0;
1087 return SCARD_E_INVALID_PARAMETER;
1089 if (!g_PCSC.pfnSCardListReaders)
1090 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
1092 mszGroups =
nullptr;
1094 if (*pcchReaders == SCARD_AUTOALLOCATE)
1095 pcchReadersAlloc = TRUE;
1097 pcsc_cchReaders = pcchReadersAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcchReaders;
1099 if (pcchReadersAlloc && !g_SCardAutoAllocate)
1101 pcsc_cchReaders = 0;
1102 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups,
nullptr, &pcsc_cchReaders);
1104 if (status == SCARD_S_SUCCESS)
1106 char* tmp = calloc(1, pcsc_cchReaders);
1109 return SCARD_E_NO_MEMORY;
1111 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, tmp, &pcsc_cchReaders);
1113 if (status != SCARD_S_SUCCESS)
1119 PCSC_AddMemoryBlock(hContext, tmp);
1121 *(WINPR_PACKED_ALIGN_CAST(
char**, mszReaders)) = tmp;
1126 status = g_PCSC.pfnSCardListReaders(hContext, mszGroups, mszReaders, &pcsc_cchReaders);
1129 *pcchReaders = (DWORD)pcsc_cchReaders;
1130 return PCSC_MapErrorCodeToWinSCard(status);
1134static LONG WINAPI PCSC_SCardListReadersA(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
1135 LPDWORD pcchReaders)
1137 LONG status = SCARD_S_SUCCESS;
1138 BOOL nullCardContext = FALSE;
1140 if (!g_PCSC.pfnSCardListReaders)
1141 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
1145 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1147 if (status != SCARD_S_SUCCESS)
1151 nullCardContext = TRUE;
1154 if (!PCSC_LockCardContext(hContext))
1156 status = SCARD_E_INVALID_HANDLE;
1160 status = PCSC_SCardListReaders_Internal(hContext, mszGroups, mszReaders, pcchReaders);
1162 if (!PCSC_UnlockCardContext(hContext))
1163 status = SCARD_E_INVALID_HANDLE;
1166 if (nullCardContext)
1168 const LONG rc = PCSC_SCardReleaseContext(hContext);
1169 if (rc != SCARD_S_SUCCESS)
1177static LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, LPCWSTR mszGroups,
1178 LPWSTR mszReaders, LPDWORD pcchReaders)
1180 LPSTR mszGroupsA =
nullptr;
1181 LPSTR mszReadersA =
nullptr;
1182 LONG status = SCARD_S_SUCCESS;
1183 BOOL nullCardContext = FALSE;
1185 if (!g_PCSC.pfnSCardListReaders)
1186 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardListReaders");
1190 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1192 if (status != SCARD_S_SUCCESS)
1196 nullCardContext = TRUE;
1199 if (!PCSC_LockCardContext(hContext))
1201 status = SCARD_E_INVALID_HANDLE;
1207 mszGroupsA = ConvertWCharToUtf8Alloc(mszGroups,
nullptr);
1210 status = SCARD_E_NO_MEMORY;
1220 cnv.ppc = &mszReadersA;
1222 status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, cnv.pc, pcchReaders);
1224 if (status == SCARD_S_SUCCESS)
1227 WCHAR* str = ConvertMszUtf8NToWCharAlloc(mszReadersA, *pcchReaders, &size);
1228 PCSC_SCardFreeMemory_Internal(hContext, mszReadersA);
1229 if (!str || (size > UINT32_MAX))
1231 status = SCARD_E_NO_MEMORY;
1236 *(WINPR_PACKED_ALIGN_CAST(LPWSTR*, mszReaders)) = str;
1237 *pcchReaders = (DWORD)size;
1238 PCSC_AddMemoryBlock(hContext, str);
1242 if (!PCSC_UnlockCardContext(hContext))
1243 status = SCARD_E_INVALID_HANDLE;
1246 if (nullCardContext)
1248 const LONG rc = PCSC_SCardReleaseContext(hContext);
1249 if (rc != SCARD_S_SUCCESS)
1260 const char* cardName;
1263static PcscKnownAtr knownAtrs[] = {
1265 { { 0x3B, 0xFD, 0x13, 0x00, 0x00, 0x81, 0x31, 0xFE, 0x15, 0x80, 0x73, 0xC0,
1266 0x21, 0xC0, 0x57, 0x59, 0x75, 0x62, 0x69, 0x4B, 0x65, 0x79, 0x40 },
1268 "NIST SP 800-73 [PIV]" },
1270 { { 0x3B, 0xFC, 0x18, 0x00, 0x00, 0x81, 0x31, 0x80, 0x45, 0x90, 0x67,
1271 0x46, 0x4A, 0x00, 0x64, 0x16, 0x06, 0xF2, 0x72, 0x7E, 0x00, 0xE0 },
1273 "PIVKey Feitian (E0)" }
1277#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a)[0])
1281static const char* findCardByAtr(LPCBYTE pbAtr)
1283 for (
size_t i = 0; i < ARRAY_LENGTH(knownAtrs); i++)
1285 if (memcmp(knownAtrs[i].atr, pbAtr, knownAtrs[i].atrLen) == 0)
1286 return knownAtrs[i].cardName;
1293static LONG WINAPI PCSC_SCardListCardsA(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, LPCBYTE pbAtr,
1294 LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
1295 CHAR* mszCards, LPDWORD pcchCards)
1297 const char* cardName =
nullptr;
1298 DWORD outputLen = 1;
1299 CHAR* output =
nullptr;
1300 BOOL autoAllocate = 0;
1302 if (!pbAtr || rgquidInterfaces || cguidInterfaceCount)
1303 return SCARD_E_UNSUPPORTED_FEATURE;
1306 return SCARD_E_INVALID_PARAMETER;
1308 autoAllocate = (*pcchCards == SCARD_AUTOALLOCATE);
1310 cardName = findCardByAtr(pbAtr);
1312 outputLen += strlen(cardName) + 1;
1314 *pcchCards = outputLen;
1317 output = malloc(outputLen);
1319 return SCARD_E_NO_MEMORY;
1321 *(WINPR_PACKED_ALIGN_CAST(LPSTR*, mszCards)) = output;
1326 return SCARD_S_SUCCESS;
1328 if (*pcchCards < outputLen)
1329 return SCARD_E_INSUFFICIENT_BUFFER;
1336 size_t toCopy = strlen(cardName) + 1;
1337 memcpy(output, cardName, toCopy);
1343 return SCARD_S_SUCCESS;
1346WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardListCardsW(
1347 WINPR_ATTR_UNUSED SCARDCONTEXT hContext, LPCBYTE pbAtr, LPCGUID rgquidInterfaces,
1348 DWORD cguidInterfaceCount, WCHAR* mszCards, LPDWORD pcchCards)
1350 const char* cardName =
nullptr;
1351 DWORD outputLen = 1;
1352 WCHAR* output =
nullptr;
1353 BOOL autoAllocate = 0;
1355 if (!pbAtr || rgquidInterfaces || cguidInterfaceCount)
1356 return SCARD_E_UNSUPPORTED_FEATURE;
1359 return SCARD_E_INVALID_PARAMETER;
1361 autoAllocate = (*pcchCards == SCARD_AUTOALLOCATE);
1363 cardName = findCardByAtr(pbAtr);
1365 outputLen += strlen(cardName) + 1;
1367 *pcchCards = outputLen;
1370 output = calloc(outputLen,
sizeof(WCHAR));
1372 return SCARD_E_NO_MEMORY;
1374 *(WINPR_PACKED_ALIGN_CAST(LPWSTR*, mszCards)) = output;
1379 return SCARD_S_SUCCESS;
1381 if (*pcchCards < outputLen)
1382 return SCARD_E_INSUFFICIENT_BUFFER;
1389 size_t toCopy = strlen(cardName) + 1;
1390 if (ConvertUtf8ToWChar(cardName, output, toCopy) < 0)
1391 return SCARD_F_INTERNAL_ERROR;
1397 return SCARD_S_SUCCESS;
1402PCSC_SCardListInterfacesA(SCARDCONTEXT hContext, LPCSTR szCard, LPGUID pguidInterfaces,
1403 LPDWORD pcguidInterfaces )
1405 WINPR_UNUSED(hContext);
1406 WINPR_UNUSED(szCard);
1407 WINPR_UNUSED(pguidInterfaces);
1408 WINPR_UNUSED(pcguidInterfaces);
1409 return SCARD_E_UNSUPPORTED_FEATURE;
1414PCSC_SCardListInterfacesW(SCARDCONTEXT hContext, LPCWSTR szCard, LPGUID pguidInterfaces,
1415 LPDWORD pcguidInterfaces )
1417 WINPR_UNUSED(hContext);
1418 WINPR_UNUSED(szCard);
1419 WINPR_UNUSED(pguidInterfaces);
1420 WINPR_UNUSED(pcguidInterfaces);
1421 return SCARD_E_UNSUPPORTED_FEATURE;
1424WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetProviderIdA(SCARDCONTEXT hContext,
1426 LPGUID pguidProviderId)
1428 WINPR_UNUSED(hContext);
1429 WINPR_UNUSED(szCard);
1430 WINPR_UNUSED(pguidProviderId);
1431 return SCARD_E_UNSUPPORTED_FEATURE;
1434WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetProviderIdW(SCARDCONTEXT hContext,
1436 LPGUID pguidProviderId)
1438 WINPR_UNUSED(hContext);
1439 WINPR_UNUSED(szCard);
1440 WINPR_UNUSED(pguidProviderId);
1441 return SCARD_E_UNSUPPORTED_FEATURE;
1444WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetCardTypeProviderNameA(
1445 SCARDCONTEXT hContext, LPCSTR szCardName, DWORD dwProviderId,
1447 LPDWORD pcchProvider )
1449 WINPR_UNUSED(hContext);
1450 WINPR_UNUSED(szCardName);
1451 WINPR_UNUSED(dwProviderId);
1452 WINPR_UNUSED(szProvider);
1453 WINPR_UNUSED(pcchProvider);
1454 return SCARD_E_UNSUPPORTED_FEATURE;
1457WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetCardTypeProviderNameW(
1458 SCARDCONTEXT hContext, LPCWSTR szCardName, DWORD dwProviderId,
1460 LPDWORD pcchProvider )
1462 WINPR_UNUSED(hContext);
1463 WINPR_UNUSED(szCardName);
1464 WINPR_UNUSED(dwProviderId);
1465 WINPR_UNUSED(szProvider);
1466 WINPR_UNUSED(pcchProvider);
1467 return SCARD_E_UNSUPPORTED_FEATURE;
1470WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderGroupA(SCARDCONTEXT hContext,
1473 WINPR_UNUSED(hContext);
1474 WINPR_UNUSED(szGroupName);
1475 return SCARD_E_UNSUPPORTED_FEATURE;
1478WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderGroupW(SCARDCONTEXT hContext,
1479 LPCWSTR szGroupName)
1481 WINPR_UNUSED(hContext);
1482 WINPR_UNUSED(szGroupName);
1483 return SCARD_E_UNSUPPORTED_FEATURE;
1486WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderGroupA(SCARDCONTEXT hContext,
1489 WINPR_UNUSED(hContext);
1490 WINPR_UNUSED(szGroupName);
1491 return SCARD_E_UNSUPPORTED_FEATURE;
1494WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderGroupW(SCARDCONTEXT hContext,
1495 LPCWSTR szGroupName)
1497 WINPR_UNUSED(hContext);
1498 WINPR_UNUSED(szGroupName);
1499 return SCARD_E_UNSUPPORTED_FEATURE;
1502WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderA(SCARDCONTEXT hContext,
1503 LPCSTR szReaderName,
1504 LPCSTR szDeviceName)
1506 WINPR_UNUSED(hContext);
1507 WINPR_UNUSED(szReaderName);
1508 WINPR_UNUSED(szDeviceName);
1509 return SCARD_E_UNSUPPORTED_FEATURE;
1512WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceReaderW(SCARDCONTEXT hContext,
1513 LPCWSTR szReaderName,
1514 LPCWSTR szDeviceName)
1516 WINPR_UNUSED(hContext);
1517 WINPR_UNUSED(szReaderName);
1518 WINPR_UNUSED(szDeviceName);
1519 return SCARD_E_UNSUPPORTED_FEATURE;
1522WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderA(SCARDCONTEXT hContext,
1523 LPCSTR szReaderName)
1525 WINPR_UNUSED(hContext);
1526 WINPR_UNUSED(szReaderName);
1527 return SCARD_E_UNSUPPORTED_FEATURE;
1530WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetReaderW(SCARDCONTEXT hContext,
1531 LPCWSTR szReaderName)
1533 WINPR_UNUSED(hContext);
1534 WINPR_UNUSED(szReaderName);
1535 return SCARD_E_UNSUPPORTED_FEATURE;
1538WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardAddReaderToGroupA(SCARDCONTEXT hContext,
1539 LPCSTR szReaderName,
1542 WINPR_UNUSED(hContext);
1543 WINPR_UNUSED(szReaderName);
1544 WINPR_UNUSED(szGroupName);
1545 return SCARD_E_UNSUPPORTED_FEATURE;
1548WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardAddReaderToGroupW(SCARDCONTEXT hContext,
1549 LPCWSTR szReaderName,
1550 LPCWSTR szGroupName)
1552 WINPR_UNUSED(hContext);
1553 WINPR_UNUSED(szReaderName);
1554 WINPR_UNUSED(szGroupName);
1555 return SCARD_E_UNSUPPORTED_FEATURE;
1558WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardRemoveReaderFromGroupA(SCARDCONTEXT hContext,
1559 LPCSTR szReaderName,
1562 WINPR_UNUSED(hContext);
1563 WINPR_UNUSED(szReaderName);
1564 WINPR_UNUSED(szGroupName);
1565 return SCARD_E_UNSUPPORTED_FEATURE;
1568WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardRemoveReaderFromGroupW(SCARDCONTEXT hContext,
1569 LPCWSTR szReaderName,
1570 LPCWSTR szGroupName)
1572 WINPR_UNUSED(hContext);
1573 WINPR_UNUSED(szReaderName);
1574 WINPR_UNUSED(szGroupName);
1575 return SCARD_E_UNSUPPORTED_FEATURE;
1578WINPR_ATTR_NODISCARD
static LONG WINAPI
1579PCSC_SCardIntroduceCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName, LPCGUID pguidPrimaryProvider,
1580 LPCGUID rgguidInterfaces, DWORD dwInterfaceCount, LPCBYTE pbAtr,
1581 LPCBYTE pbAtrMask, DWORD cbAtrLen)
1583 WINPR_UNUSED(hContext);
1584 WINPR_UNUSED(szCardName);
1585 WINPR_UNUSED(pguidPrimaryProvider);
1586 WINPR_UNUSED(rgguidInterfaces);
1587 WINPR_UNUSED(dwInterfaceCount);
1588 WINPR_UNUSED(pbAtr);
1589 WINPR_UNUSED(pbAtrMask);
1590 WINPR_UNUSED(cbAtrLen);
1591 return SCARD_E_UNSUPPORTED_FEATURE;
1594WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardIntroduceCardTypeW(
1595 SCARDCONTEXT hContext, LPCWSTR szCardName, LPCGUID pguidPrimaryProvider,
1596 LPCGUID rgguidInterfaces, DWORD dwInterfaceCount, LPCBYTE pbAtr, LPCBYTE pbAtrMask,
1599 WINPR_UNUSED(hContext);
1600 WINPR_UNUSED(szCardName);
1601 WINPR_UNUSED(pguidPrimaryProvider);
1602 WINPR_UNUSED(rgguidInterfaces);
1603 WINPR_UNUSED(dwInterfaceCount);
1604 WINPR_UNUSED(pbAtr);
1605 WINPR_UNUSED(pbAtrMask);
1606 WINPR_UNUSED(cbAtrLen);
1607 return SCARD_E_UNSUPPORTED_FEATURE;
1610WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetCardTypeProviderNameA(SCARDCONTEXT hContext,
1615 WINPR_UNUSED(hContext);
1616 WINPR_UNUSED(szCardName);
1617 WINPR_UNUSED(dwProviderId);
1618 WINPR_UNUSED(szProvider);
1619 return SCARD_E_UNSUPPORTED_FEATURE;
1622WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetCardTypeProviderNameW(SCARDCONTEXT hContext,
1627 WINPR_UNUSED(hContext);
1628 WINPR_UNUSED(szCardName);
1629 WINPR_UNUSED(dwProviderId);
1630 WINPR_UNUSED(szProvider);
1631 return SCARD_E_UNSUPPORTED_FEATURE;
1634WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetCardTypeA(SCARDCONTEXT hContext,
1637 WINPR_UNUSED(hContext);
1638 WINPR_UNUSED(szCardName);
1639 return SCARD_E_UNSUPPORTED_FEATURE;
1642WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardForgetCardTypeW(SCARDCONTEXT hContext,
1645 WINPR_UNUSED(hContext);
1646 WINPR_UNUSED(szCardName);
1647 return SCARD_E_UNSUPPORTED_FEATURE;
1650static LONG WINAPI PCSC_SCardFreeMemory_Internal(SCARDCONTEXT hContext, LPVOID pvMem)
1652 PCSC_LONG status = SCARD_S_SUCCESS;
1654 if (PCSC_RemoveMemoryBlock(hContext, pvMem))
1655 status = SCARD_S_SUCCESS;
1658 if (g_PCSC.pfnSCardFreeMemory)
1660 status = g_PCSC.pfnSCardFreeMemory(hContext, pvMem);
1664 return PCSC_MapErrorCodeToWinSCard(status);
1667WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardFreeMemory(SCARDCONTEXT hContext, LPVOID pvMem)
1669 LONG status = SCARD_S_SUCCESS;
1673 if (!PCSC_LockCardContext(hContext))
1674 return SCARD_E_INVALID_HANDLE;
1677 status = PCSC_SCardFreeMemory_Internal(hContext, pvMem);
1681 if (!PCSC_UnlockCardContext(hContext))
1682 return SCARD_E_INVALID_HANDLE;
1689static HANDLE WINAPI PCSC_SCardAccessStartedEvent(
void)
1692 SCARDCONTEXT hContext = 0;
1694 status = PCSC_SCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hContext);
1696 if (status != SCARD_S_SUCCESS)
1699 status = PCSC_SCardReleaseContext(hContext);
1701 if (status != SCARD_S_SUCCESS)
1704 if (!g_StartedEvent)
1706 if (!(g_StartedEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
1709 if (!SetEvent(g_StartedEvent))
1711 (void)CloseHandle(g_StartedEvent);
1716 g_StartedEventRefCount++;
1717 return g_StartedEvent;
1720static void WINAPI PCSC_SCardReleaseStartedEvent(
void)
1722 g_StartedEventRefCount--;
1724 if (g_StartedEventRefCount == 0)
1728 (void)CloseHandle(g_StartedEvent);
1729 g_StartedEvent =
nullptr;
1734WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardLocateCardsA(SCARDCONTEXT hContext,
1739 WINPR_UNUSED(hContext);
1740 WINPR_UNUSED(mszCards);
1741 WINPR_UNUSED(rgReaderStates);
1742 WINPR_UNUSED(cReaders);
1743 return SCARD_E_UNSUPPORTED_FEATURE;
1746WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardLocateCardsW(SCARDCONTEXT hContext,
1751 WINPR_UNUSED(hContext);
1752 WINPR_UNUSED(mszCards);
1753 WINPR_UNUSED(rgReaderStates);
1754 WINPR_UNUSED(cReaders);
1755 return SCARD_E_UNSUPPORTED_FEATURE;
1758WINPR_ATTR_NODISCARD
static LONG WINAPI
1759PCSC_SCardLocateCardsByATRA(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs,
1762 WINPR_UNUSED(hContext);
1763 WINPR_UNUSED(rgAtrMasks);
1764 WINPR_UNUSED(cAtrs);
1765 WINPR_UNUSED(rgReaderStates);
1766 WINPR_UNUSED(cReaders);
1767 return SCARD_E_UNSUPPORTED_FEATURE;
1770WINPR_ATTR_NODISCARD
static LONG WINAPI
1771PCSC_SCardLocateCardsByATRW(SCARDCONTEXT hContext,
LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs,
1774 WINPR_UNUSED(hContext);
1775 WINPR_UNUSED(rgAtrMasks);
1776 WINPR_UNUSED(cAtrs);
1777 WINPR_UNUSED(rgReaderStates);
1778 WINPR_UNUSED(cReaders);
1779 return SCARD_E_UNSUPPORTED_FEATURE;
1782WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetStatusChange_Internal(
1785 INT64* map =
nullptr;
1786 PCSC_DWORD cMappedReaders = 0;
1788 PCSC_LONG status = SCARD_S_SUCCESS;
1789 PCSC_DWORD pcsc_dwTimeout = (PCSC_DWORD)dwTimeout;
1790 PCSC_DWORD pcsc_cReaders = (PCSC_DWORD)cReaders;
1792 if (!g_PCSC.pfnSCardGetStatusChange)
1793 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetStatusChange");
1796 return SCARD_S_SUCCESS;
1799 pcsc_dwTimeout = pcsc_dwTimeout ? pcsc_dwTimeout : 1;
1813 map = (INT64*)calloc(pcsc_cReaders,
sizeof(INT64));
1816 return SCARD_E_NO_MEMORY;
1823 return SCARD_E_NO_MEMORY;
1827 for (PCSC_DWORD i = 0; i < pcsc_cReaders; i++)
1829 if (!g_PnP_Notification)
1832 if (!reader->szReader)
1834 if (0 == _stricmp(reader->szReader, SMARTCARD_PNP_NOTIFICATION_A))
1842 states[j].szReader = rgReaderStates[i].szReader;
1843 states[j].dwCurrentState = rgReaderStates[i].dwCurrentState;
1844 states[j].pvUserData = rgReaderStates[i].pvUserData;
1845 states[j].dwEventState = rgReaderStates[i].dwEventState;
1846 states[j].cbAtr = rgReaderStates[i].cbAtr;
1847 CopyMemory(&(states[j].rgbAtr), &(rgReaderStates[i].rgbAtr), PCSC_MAX_ATR_SIZE);
1853 if (cMappedReaders > 0)
1855 status = g_PCSC.pfnSCardGetStatusChange(hContext, pcsc_dwTimeout, states, cMappedReaders);
1859 status = SCARD_S_SUCCESS;
1862 for (PCSC_DWORD i = 0; i < pcsc_cReaders; i++)
1867 PCSC_DWORD k = (PCSC_DWORD)map[i];
1868 rgReaderStates[i].dwCurrentState = (DWORD)states[k].dwCurrentState;
1869 rgReaderStates[i].cbAtr = (DWORD)states[k].cbAtr;
1870 CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[k].rgbAtr), PCSC_MAX_ATR_SIZE);
1871 rgReaderStates[i].dwEventState = (DWORD)states[k].dwEventState;
1874 if ((status == SCARD_S_SUCCESS) && (states[k].dwEventState & SCARD_STATE_EMPTY))
1875 PCSC_ResetTransmitCount(rgReaderStates[i].szReader);
1880 return PCSC_MapErrorCodeToWinSCard(status);
1884static LONG WINAPI PCSC_SCardGetStatusChangeA(SCARDCONTEXT hContext, DWORD dwTimeout,
1887 LONG status = SCARD_S_SUCCESS;
1889 if (!PCSC_LockCardContext(hContext))
1890 return SCARD_E_INVALID_HANDLE;
1892 status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, rgReaderStates, cReaders);
1894 if (!PCSC_UnlockCardContext(hContext))
1895 return SCARD_E_INVALID_HANDLE;
1901static LONG WINAPI PCSC_SCardGetStatusChangeW(SCARDCONTEXT hContext, DWORD dwTimeout,
1905 LONG status = SCARD_S_SUCCESS;
1907 if (!g_PCSC.pfnSCardGetStatusChange)
1908 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetStatusChange");
1910 if (!PCSC_LockCardContext(hContext))
1911 return SCARD_E_INVALID_HANDLE;
1917 if (!PCSC_UnlockCardContext(hContext))
1918 return SCARD_E_INVALID_HANDLE;
1919 return SCARD_E_NO_MEMORY;
1922 for (DWORD index = 0; index < cReaders; index++)
1927 cur->szReader = ConvertWCharToUtf8Alloc(curReader->szReader,
nullptr);
1928 cur->pvUserData = curReader->pvUserData;
1929 cur->dwCurrentState = curReader->dwCurrentState;
1930 cur->dwEventState = curReader->dwEventState;
1931 cur->cbAtr = curReader->cbAtr;
1932 CopyMemory(&(cur->rgbAtr), &(curReader->rgbAtr), ARRAYSIZE(cur->rgbAtr));
1935 status = PCSC_SCardGetStatusChange_Internal(hContext, dwTimeout, states, cReaders);
1937 for (DWORD index = 0; index < cReaders; index++)
1939 free((
void*)states[index].szReader);
1940 rgReaderStates[index].pvUserData = states[index].pvUserData;
1941 rgReaderStates[index].dwCurrentState = states[index].dwCurrentState;
1942 rgReaderStates[index].dwEventState = states[index].dwEventState;
1943 rgReaderStates[index].cbAtr = states[index].cbAtr;
1944 CopyMemory(&(rgReaderStates[index].rgbAtr), &(states[index].rgbAtr), 36);
1949 if (!PCSC_UnlockCardContext(hContext))
1950 return SCARD_E_INVALID_HANDLE;
1955static LONG WINAPI PCSC_SCardCancel(SCARDCONTEXT hContext)
1957 PCSC_LONG status = SCARD_S_SUCCESS;
1959 if (!g_PCSC.pfnSCardCancel)
1960 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardCancel");
1962 status = g_PCSC.pfnSCardCancel(hContext);
1963 return PCSC_MapErrorCodeToWinSCard(status);
1966WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnect_Internal(
1967 SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols,
1968 LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
1971 const char* szReaderPCSC =
nullptr;
1972 PCSC_LONG status = SCARD_S_SUCCESS;
1973 PCSC_SCARDHANDLE* pCard =
nullptr;
1974 PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD)dwShareMode;
1975 PCSC_DWORD pcsc_dwPreferredProtocols = 0;
1976 PCSC_DWORD pcsc_dwActiveProtocol = 0;
1978 if (!g_PCSC.pfnSCardConnect)
1979 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardConnect");
1981 if (!g_PCSC.pfnSCardEstablishContext)
1982 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEstablishContext");
1984 if (!PCSC_GetCardContextData(hContext))
1985 return SCARD_E_INVALID_HANDLE;
1987 shared = (dwShareMode == SCARD_SHARE_DIRECT) != 0;
1988 PCSC_WaitForCardAccess(hContext, 0, shared);
1989 szReaderPCSC = szReader;
1998 if (pcsc_dwShareMode == SCARD_SHARE_DIRECT && dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED)
1999 pcsc_dwPreferredProtocols = SCARD_PROTOCOL_UNDEFINED;
2001 pcsc_dwPreferredProtocols =
2002 (PCSC_DWORD)PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
2006 SCARDCONTEXT hPrivateContext = 0;
2008 g_PCSC.pfnSCardEstablishContext(SCARD_SCOPE_SYSTEM,
nullptr,
nullptr, &hPrivateContext);
2009 if (status != SCARD_S_SUCCESS)
2010 return PCSC_MapErrorCodeToWinSCard(status);
2012 status = g_PCSC.pfnSCardConnect(hPrivateContext, szReaderPCSC, pcsc_dwShareMode,
2013 pcsc_dwPreferredProtocols, phCard, &pcsc_dwActiveProtocol);
2015 if (status != SCARD_S_SUCCESS)
2017 PCSC_ReleasePrivateContext(hPrivateContext);
2018 return PCSC_MapErrorCodeToWinSCard(status);
2021 if (!PCSC_LockCardContext(hContext))
2024 PCSC_ReleasePrivateContext(hPrivateContext);
2025 return SCARD_E_INVALID_HANDLE;
2028 pCard = PCSC_ConnectCardHandle(hContext, *phCard, szReader);
2031 *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwActiveProtocol);
2032 pCard->shared = shared;
2033 pCard->hPrivateContext = hPrivateContext;
2035 PCSC_WaitForCardAccess(hContext, pCard->hSharedContext, shared);
2038 const BOOL unlocked = PCSC_UnlockCardContext(hContext);
2041 PCSC_ReleasePrivateContext(hPrivateContext);
2042 return SCARD_E_NO_MEMORY;
2046 PCSC_DisconnectCardHandle(pCard);
2047 PCSC_ReleasePrivateContext(hPrivateContext);
2048 return SCARD_E_INVALID_HANDLE;
2052 return SCARD_S_SUCCESS;
2055WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnectA(SCARDCONTEXT hContext, LPCSTR szReader,
2057 DWORD dwPreferredProtocols,
2058 LPSCARDHANDLE phCard,
2059 LPDWORD pdwActiveProtocol)
2061 return PCSC_SCardConnect_Internal(hContext, szReader, dwShareMode, dwPreferredProtocols, phCard,
2065WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardConnectW(SCARDCONTEXT hContext, LPCWSTR szReader,
2067 DWORD dwPreferredProtocols,
2068 LPSCARDHANDLE phCard,
2069 LPDWORD pdwActiveProtocol)
2071 LPSTR szReaderA =
nullptr;
2072 LONG status = SCARD_S_SUCCESS;
2076 szReaderA = ConvertWCharToUtf8Alloc(szReader,
nullptr);
2078 return SCARD_E_INSUFFICIENT_BUFFER;
2081 status = PCSC_SCardConnect_Internal(hContext, szReaderA, dwShareMode, dwPreferredProtocols,
2082 phCard, pdwActiveProtocol);
2087WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
2088 DWORD dwPreferredProtocols,
2089 DWORD dwInitialization,
2090 LPDWORD pdwActiveProtocol)
2092 PCSC_LONG status = SCARD_S_SUCCESS;
2093 PCSC_DWORD pcsc_dwShareMode = (PCSC_DWORD)dwShareMode;
2094 PCSC_DWORD pcsc_dwPreferredProtocols = 0;
2095 PCSC_DWORD pcsc_dwInitialization = (PCSC_DWORD)dwInitialization;
2096 PCSC_DWORD pcsc_dwActiveProtocol = 0;
2098 if (!g_PCSC.pfnSCardReconnect)
2099 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardReconnect");
2101 const BOOL shared = (dwShareMode == SCARD_SHARE_DIRECT) != 0;
2102 PCSC_WaitForCardAccess(0, hCard, shared);
2103 pcsc_dwPreferredProtocols = (PCSC_DWORD)PCSC_ConvertProtocolsFromWinSCard(dwPreferredProtocols);
2104 status = g_PCSC.pfnSCardReconnect(hCard, pcsc_dwShareMode, pcsc_dwPreferredProtocols,
2105 pcsc_dwInitialization, &pcsc_dwActiveProtocol);
2107 *pdwActiveProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwActiveProtocol);
2108 return PCSC_MapErrorCodeToWinSCard(status);
2111WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
2113 PCSC_LONG status = SCARD_S_SUCCESS;
2114 PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD)dwDisposition;
2116 if (!g_PCSC.pfnSCardDisconnect)
2117 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardDisconnect");
2119 status = g_PCSC.pfnSCardDisconnect(hCard, pcsc_dwDisposition);
2122 PCSC_ReleaseCardAccess(0, hCard);
2124 if (status == SCARD_S_SUCCESS)
2126 PCSC_SCARDHANDLE* pCard = PCSC_GetCardHandleData(hCard);
2127 const SCARDCONTEXT hPrivateContext = pCard ? pCard->hPrivateContext : 0;
2128 PCSC_DisconnectCardHandle(pCard);
2129 PCSC_ReleasePrivateContext(hPrivateContext);
2132 return PCSC_MapErrorCodeToWinSCard(status);
2135WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardBeginTransaction(SCARDHANDLE hCard)
2137 PCSC_LONG status = SCARD_S_SUCCESS;
2138 PCSC_SCARDHANDLE* pCard =
nullptr;
2139 PCSC_SCARDCONTEXT* pContext =
nullptr;
2141 if (!g_PCSC.pfnSCardBeginTransaction)
2142 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardBeginTransaction");
2144 pCard = PCSC_GetCardHandleData(hCard);
2147 return SCARD_E_INVALID_HANDLE;
2149 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
2152 return SCARD_E_INVALID_HANDLE;
2155 if (pCard->isTransactionLocked)
2156 return SCARD_S_SUCCESS;
2158 status = g_PCSC.pfnSCardBeginTransaction(hCard);
2160 if (status == SCARD_S_SUCCESS)
2161 PCSC_SetTransactionLocked(hCard, TRUE);
2162 return PCSC_MapErrorCodeToWinSCard(status);
2165WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardEndTransaction(SCARDHANDLE hCard,
2166 DWORD dwDisposition)
2168 PCSC_LONG status = SCARD_S_SUCCESS;
2169 PCSC_SCARDHANDLE* pCard =
nullptr;
2170 PCSC_SCARDCONTEXT* pContext =
nullptr;
2171 PCSC_DWORD pcsc_dwDisposition = (PCSC_DWORD)dwDisposition;
2173 if (!g_PCSC.pfnSCardEndTransaction)
2174 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardEndTransaction");
2176 pCard = PCSC_GetCardHandleData(hCard);
2179 return SCARD_E_INVALID_HANDLE;
2181 pContext = PCSC_GetCardContextData(pCard->hSharedContext);
2184 return SCARD_E_INVALID_HANDLE;
2186 PCSC_ReleaseCardAccess(0, hCard);
2188 if (!pCard->isTransactionLocked)
2189 return SCARD_S_SUCCESS;
2191 status = g_PCSC.pfnSCardEndTransaction(hCard, pcsc_dwDisposition);
2193 PCSC_SetTransactionLocked(hCard, FALSE);
2194 return PCSC_MapErrorCodeToWinSCard(status);
2197static LONG WINAPI PCSC_SCardCancelTransaction(SCARDHANDLE hCard)
2199 WINPR_UNUSED(hCard);
2200 return SCARD_S_SUCCESS;
2207WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatus_Internal(
2208 SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState,
2209 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen, BOOL unicode)
2211 PCSC_SCARDHANDLE* pCard =
nullptr;
2212 SCARDCONTEXT hContext = 0;
2213 PCSC_LONG status = 0;
2214 PCSC_DWORD pcsc_cchReaderLen = 0;
2215 PCSC_DWORD pcsc_cbAtrLen = 0;
2216 PCSC_DWORD pcsc_dwState = 0;
2217 PCSC_DWORD pcsc_dwProtocol = 0;
2218 BOOL allocateReader = FALSE;
2219 BOOL allocateAtr = FALSE;
2220 LPSTR readerNames = mszReaderNames;
2222 LPSTR tReader =
nullptr;
2223 LPBYTE tATR =
nullptr;
2225 if (!g_PCSC.pfnSCardStatus)
2226 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardStatus");
2228 pCard = PCSC_GetCardHandleData(hCard);
2231 return SCARD_E_INVALID_VALUE;
2233 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2234 hContext = PCSC_GetCardContextFromHandle(hCard);
2237 return SCARD_E_INVALID_VALUE;
2239 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &pcsc_cchReaderLen,
nullptr,
nullptr,
nullptr,
2242 if (status != STATUS_SUCCESS)
2243 return PCSC_MapErrorCodeToWinSCard(status);
2245 pcsc_cchReaderLen++;
2248 pcsc_cchReaderLen *= 2;
2252 if (*pcchReaderLen == SCARD_AUTOALLOCATE)
2253 allocateReader = TRUE;
2254 else if (mszReaderNames && (*pcchReaderLen < pcsc_cchReaderLen))
2255 return SCARD_E_INSUFFICIENT_BUFFER;
2257 pcsc_cchReaderLen = *pcchReaderLen;
2262 if (*pcbAtrLen == SCARD_AUTOALLOCATE)
2264 else if (pbAtr && (*pcbAtrLen < pcsc_cbAtrLen))
2265 return SCARD_E_INSUFFICIENT_BUFFER;
2267 pcsc_cbAtrLen = *pcbAtrLen;
2270 if (allocateReader && pcsc_cchReaderLen > 0 && mszReaderNames)
2277 if (OSXVersion == 0x10100000)
2278 pcsc_cchReaderLen++;
2281 tReader = calloc(
sizeof(CHAR), pcsc_cchReaderLen + 1);
2285 status = ERROR_NOT_ENOUGH_MEMORY;
2289 readerNames = tReader;
2292 if (allocateAtr && pcsc_cbAtrLen > 0 && pbAtr)
2294 tATR = calloc(1, pcsc_cbAtrLen);
2298 status = ERROR_NOT_ENOUGH_MEMORY;
2305 status = g_PCSC.pfnSCardStatus(hCard, readerNames, &pcsc_cchReaderLen, &pcsc_dwState,
2306 &pcsc_dwProtocol, atr, &pcsc_cbAtrLen);
2308 if (status != STATUS_SUCCESS)
2313 PCSC_AddMemoryBlock(hContext, tATR);
2314 *(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAtr)) = tATR;
2322 WCHAR* tmp = ConvertMszUtf8NToWCharAlloc(tReader, pcsc_cchReaderLen + 1, &size);
2326 status = ERROR_NOT_ENOUGH_MEMORY;
2332 PCSC_AddMemoryBlock(hContext, tmp);
2333 *(WINPR_PACKED_ALIGN_CAST(WCHAR**, mszReaderNames)) = tmp;
2337 tReader[pcsc_cchReaderLen - 1] =
'\0';
2338 PCSC_AddMemoryBlock(hContext, tReader);
2339 *(WINPR_PACKED_ALIGN_CAST(
char**, mszReaderNames)) = tReader;
2343 pcsc_dwState &= 0xFFFF;
2346 *pdwState = PCSC_ConvertCardStateToWinSCard((DWORD)pcsc_dwState, status);
2349 *pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwProtocol);
2352 *pcbAtrLen = (DWORD)pcsc_cbAtrLen;
2356 WINPR_ASSERT(pcsc_cchReaderLen < UINT32_MAX);
2357 *pcchReaderLen = (DWORD)pcsc_cchReaderLen + 1u;
2360 return (LONG)status;
2364 return (LONG)status;
2367WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, LPDWORD pdwState,
2368 LPDWORD pdwProtocol, LPBYTE pbAtr,
2371 DWORD cchReaderLen = 0;
2372 SCARDCONTEXT hContext = 0;
2373 LPSTR mszReaderNames =
nullptr;
2374 PCSC_LONG status = SCARD_S_SUCCESS;
2375 PCSC_SCARDHANDLE* pCard =
nullptr;
2376 DWORD pcsc_dwState = 0;
2377 DWORD pcsc_dwProtocol = 0;
2378 DWORD pcsc_cbAtrLen = 0;
2381 pcsc_cbAtrLen = (DWORD)*pcbAtrLen;
2383 if (!g_PCSC.pfnSCardStatus)
2384 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardStatus");
2386 pCard = PCSC_GetCardHandleData(hCard);
2389 return SCARD_E_INVALID_VALUE;
2391 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2392 hContext = PCSC_GetCardContextFromHandle(hCard);
2395 return SCARD_E_INVALID_VALUE;
2397 cchReaderLen = SCARD_AUTOALLOCATE;
2398 status = PCSC_SCardStatus_Internal(hCard, (LPSTR)&mszReaderNames, &cchReaderLen, &pcsc_dwState,
2399 &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen, FALSE);
2402 PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames);
2404 *pdwState = pcsc_dwState;
2405 *pdwProtocol = PCSC_ConvertProtocolsToWinSCard(pcsc_dwProtocol);
2407 *pcbAtrLen = pcsc_cbAtrLen;
2408 return PCSC_MapErrorCodeToWinSCard(status);
2411WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard, LPSTR mszReaderNames,
2412 LPDWORD pcchReaderLen, LPDWORD pdwState,
2413 LPDWORD pdwProtocol, LPBYTE pbAtr,
2417 return PCSC_SCardStatus_Internal(hCard, mszReaderNames, pcchReaderLen, pdwState, pdwProtocol,
2418 pbAtr, pcbAtrLen, FALSE);
2421WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardStatusW(SCARDHANDLE hCard, LPWSTR mszReaderNames,
2422 LPDWORD pcchReaderLen, LPDWORD pdwState,
2423 LPDWORD pdwProtocol, LPBYTE pbAtr,
2427 return PCSC_SCardStatus_Internal(hCard, (LPSTR)mszReaderNames, pcchReaderLen, pdwState,
2428 pdwProtocol, pbAtr, pcbAtrLen, TRUE);
2431WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardTransmit(
2432 SCARDHANDLE hCard,
LPCSCARD_IO_REQUEST pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength,
2435 PCSC_LONG status = SCARD_S_SUCCESS;
2436 PCSC_SCARDHANDLE* pCard =
nullptr;
2437 PCSC_DWORD cbExtraBytes = 0;
2438 BYTE* pbExtraBytes =
nullptr;
2439 BYTE* pcsc_pbExtraBytes =
nullptr;
2440 PCSC_DWORD pcsc_cbSendLength = (PCSC_DWORD)cbSendLength;
2441 PCSC_DWORD pcsc_cbRecvLength = 0;
2449 } sendPci, recvPci, inRecvPci, inSendPci;
2451 sendPci.ps =
nullptr;
2452 recvPci.ps =
nullptr;
2453 inRecvPci.lps = pioRecvPci;
2454 inSendPci.lpcs = pioSendPci;
2456 if (!g_PCSC.pfnSCardTransmit)
2457 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardTransmit");
2459 pCard = PCSC_GetCardHandleData(hCard);
2462 return SCARD_E_INVALID_VALUE;
2464 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2467 return SCARD_E_INVALID_PARAMETER;
2469 if (*pcbRecvLength == SCARD_AUTOALLOCATE)
2470 return SCARD_E_INVALID_PARAMETER;
2472 pcsc_cbRecvLength = (PCSC_DWORD)*pcbRecvLength;
2474 if (!inSendPci.lpcs)
2476 PCSC_DWORD dwState = 0;
2477 PCSC_DWORD cbAtrLen = 0;
2478 PCSC_DWORD dwProtocol = 0;
2479 PCSC_DWORD cchReaderLen = 0;
2484 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReaderLen, &dwState, &dwProtocol,
2485 nullptr, &cbAtrLen);
2487 if (status == SCARD_S_SUCCESS)
2489 if (dwProtocol == SCARD_PROTOCOL_T0)
2490 sendPci.pcs = PCSC_SCARD_PCI_T0;
2491 else if (dwProtocol == SCARD_PROTOCOL_T1)
2492 sendPci.pcs = PCSC_SCARD_PCI_T1;
2493 else if (dwProtocol == PCSC_SCARD_PROTOCOL_RAW)
2494 sendPci.pcs = PCSC_SCARD_PCI_RAW;
2503 return SCARD_E_NO_MEMORY;
2505 sendPci.ps->dwProtocol = (PCSC_DWORD)inSendPci.lpcs->dwProtocol;
2509 CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
2522 return SCARD_E_NO_MEMORY;
2525 recvPci.ps->dwProtocol = (PCSC_DWORD)inRecvPci.lps->dwProtocol;
2529 CopyMemory(pcsc_pbExtraBytes, pbExtraBytes, cbExtraBytes);
2532 status = g_PCSC.pfnSCardTransmit(hCard, sendPci.ps, pbSendBuffer, pcsc_cbSendLength, recvPci.ps,
2533 pbRecvBuffer, &pcsc_cbRecvLength);
2535 *pcbRecvLength = (DWORD)pcsc_cbRecvLength;
2537 if (status == SCARD_S_SUCCESS)
2538 PCSC_AddTransmitCountOfHandle(hCard);
2549 CopyMemory(pbExtraBytes, pcsc_pbExtraBytes, cbExtraBytes);
2554 return PCSC_MapErrorCodeToWinSCard(status);
2557WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetTransmitCount(SCARDHANDLE hCard,
2558 LPDWORD pcTransmitCount)
2560 PCSC_SCARDHANDLE* pCard =
nullptr;
2562 if (!pcTransmitCount)
2563 return SCARD_E_INVALID_PARAMETER;
2565 pCard = PCSC_GetCardHandleData(hCard);
2568 return SCARD_E_INVALID_VALUE;
2570 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2571 *pcTransmitCount = PCSC_GetTransmitCountOfReader(pCard->szReader);
2572 return SCARD_S_SUCCESS;
2575WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
2576 LPCVOID lpInBuffer, DWORD cbInBufferSize,
2577 LPVOID lpOutBuffer, DWORD cbOutBufferSize,
2578 LPDWORD lpBytesReturned)
2580 DWORD IoCtlFunction = 0;
2581 DWORD IoCtlDeviceType = 0;
2582 BOOL getFeatureRequest = FALSE;
2583 PCSC_LONG status = SCARD_S_SUCCESS;
2584 PCSC_SCARDHANDLE* pCard =
nullptr;
2585 PCSC_DWORD pcsc_dwControlCode = 0;
2586 PCSC_DWORD pcsc_cbInBufferSize = (PCSC_DWORD)cbInBufferSize;
2587 PCSC_DWORD pcsc_cbOutBufferSize = (PCSC_DWORD)cbOutBufferSize;
2588 PCSC_DWORD pcsc_BytesReturned = 0;
2590 if (!g_PCSC.pfnSCardControl)
2591 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardControl");
2593 pCard = PCSC_GetCardHandleData(hCard);
2596 return SCARD_E_INVALID_VALUE;
2598 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2609 IoCtlFunction = FUNCTION_FROM_CTL_CODE(dwControlCode);
2610 IoCtlDeviceType = DEVICE_TYPE_FROM_CTL_CODE(dwControlCode);
2612 if (dwControlCode == IOCTL_SMARTCARD_GET_FEATURE_REQUEST)
2613 getFeatureRequest = TRUE;
2615 if (IoCtlDeviceType == FILE_DEVICE_SMARTCARD)
2616 dwControlCode = PCSC_SCARD_CTL_CODE(IoCtlFunction);
2618 pcsc_dwControlCode = (PCSC_DWORD)dwControlCode;
2619 status = g_PCSC.pfnSCardControl(hCard, pcsc_dwControlCode, lpInBuffer, pcsc_cbInBufferSize,
2620 lpOutBuffer, pcsc_cbOutBufferSize, &pcsc_BytesReturned);
2622 *lpBytesReturned = (DWORD)pcsc_BytesReturned;
2624 if (getFeatureRequest)
2630 return SCARD_E_UNEXPECTED;
2634 for (DWORD index = 0; index < count; index++)
2636 if (tlv[index].length != 4)
2637 return SCARD_E_UNEXPECTED;
2641 return PCSC_MapErrorCodeToWinSCard(status);
2644WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard,
2645 DWORD dwAttrId, LPBYTE pbAttr,
2648 SCARDCONTEXT hContext = 0;
2649 BOOL pcbAttrLenAlloc = FALSE;
2650 PCSC_LONG status = SCARD_S_SUCCESS;
2651 PCSC_SCARDHANDLE* pCard =
nullptr;
2652 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
2653 PCSC_DWORD pcsc_cbAttrLen = 0;
2655 if (!g_PCSC.pfnSCardGetAttrib)
2656 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardGetAttrib");
2658 pCard = PCSC_GetCardHandleData(hCard);
2661 return SCARD_E_INVALID_VALUE;
2663 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
2664 hContext = PCSC_GetCardContextFromHandle(hCard);
2667 return SCARD_E_INVALID_HANDLE;
2670 return SCARD_E_INVALID_PARAMETER;
2672 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2675 return SCARD_E_INVALID_PARAMETER;
2676 pcbAttrLenAlloc = TRUE;
2679 pcsc_cbAttrLen = pcbAttrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcbAttrLen;
2681 if (pcbAttrLenAlloc && !g_SCardAutoAllocate)
2684 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId,
nullptr, &pcsc_cbAttrLen);
2686 if (status == SCARD_S_SUCCESS)
2688 BYTE* tmp = (BYTE*)calloc(1, pcsc_cbAttrLen);
2691 return SCARD_E_NO_MEMORY;
2693 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, tmp, &pcsc_cbAttrLen);
2695 if (status != SCARD_S_SUCCESS)
2701 PCSC_AddMemoryBlock(hContext, tmp);
2702 *(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAttr)) = tmp;
2707 status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, pbAttr, &pcsc_cbAttrLen);
2710 if (status == SCARD_S_SUCCESS)
2711 *pcbAttrLen = (DWORD)pcsc_cbAttrLen;
2712 return PCSC_MapErrorCodeToWinSCard(status);
2715WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib_FriendlyName(SCARDHANDLE hCard,
2720 char* namePCSC =
nullptr;
2721 char* pbAttrA =
nullptr;
2723 SCARDCONTEXT hContext = PCSC_GetCardContextFromHandle(hCard);
2726 return SCARD_E_INVALID_HANDLE;
2729 return SCARD_E_INVALID_PARAMETER;
2730 const DWORD cbAttrLen = *pcbAttrLen;
2731 *pcbAttrLen = SCARD_AUTOALLOCATE;
2732 LONG status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A,
2733 (LPBYTE)&pbAttrA, pcbAttrLen);
2735 if (status != SCARD_S_SUCCESS)
2737 WCHAR* pbAttrW =
nullptr;
2739 *pcbAttrLen = SCARD_AUTOALLOCATE;
2740 status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W,
2741 (LPBYTE)&pbAttrW, pcbAttrLen);
2743 if (status != SCARD_S_SUCCESS)
2746 namePCSC = ConvertMszWCharNToUtf8Alloc(pbAttrW, *pcbAttrLen,
nullptr);
2747 PCSC_SCardFreeMemory_Internal(hContext, pbAttrW);
2751 namePCSC = strndup(pbAttrA, *pcbAttrLen);
2754 return SCARD_E_NO_MEMORY;
2756 PCSC_SCardFreeMemory_Internal(hContext, pbAttrA);
2759 size_t length = strnlen(namePCSC, *pcbAttrLen);
2761 if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W)
2764 WCHAR* friendlyNameW = ConvertUtf8NToWCharAlloc(namePCSC, length, &size);
2768 status = SCARD_E_NO_MEMORY;
2773 if (cbAttrLen == SCARD_AUTOALLOCATE)
2775 WINPR_ASSERT(length <= UINT32_MAX /
sizeof(WCHAR));
2776 *(WINPR_PACKED_ALIGN_CAST(WCHAR**, pbAttr)) = friendlyNameW;
2777 *pcbAttrLen = (UINT32)length *
sizeof(WCHAR);
2778 PCSC_AddMemoryBlock(hContext, friendlyNameW);
2782 const size_t wlen = length *
sizeof(WCHAR);
2783 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(uint32_t, wlen);
2784 if ((wlen > cbAttrLen) && pbAttr)
2785 status = SCARD_E_INSUFFICIENT_BUFFER;
2787 CopyMemory(pbAttr, friendlyNameW, (length *
sizeof(WCHAR)));
2789 free(friendlyNameW);
2797 if (cbAttrLen == SCARD_AUTOALLOCATE)
2799 *(WINPR_PACKED_ALIGN_CAST(CHAR**, pbAttr)) = namePCSC;
2800 WINPR_ASSERT(length <= UINT32_MAX);
2801 *pcbAttrLen = (UINT32)length;
2802 PCSC_AddMemoryBlock(hContext, namePCSC);
2806 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(uint32_t, length);
2807 if ((length > cbAttrLen) && pbAttr)
2808 status = SCARD_E_INSUFFICIENT_BUFFER;
2810 CopyMemory(pbAttr, namePCSC, length);
2819static LONG PCSC_ReadDeviceSystemNameGet(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2820 DWORD dwAttrId, LPBYTE* pbAttr, LPDWORD pcbAttrLen)
2822 PCSC_DWORD cchReader = 0;
2823 PCSC_DWORD cbAtr = 0;
2824 PCSC_DWORD dwState = 0;
2825 PCSC_DWORD dwProtocol = 0;
2827 const PCSC_LONG rc =
2828 g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReader, &dwState, &dwProtocol,
nullptr, &cbAtr);
2829 if (rc != SCARD_S_SUCCESS)
2832 void* tmp = calloc(cchReader + 1,
sizeof(CHAR));
2834 return SCARD_E_NO_MEMORY;
2835 const PCSC_LONG rc2 =
2836 g_PCSC.pfnSCardStatus(hCard, tmp, &cchReader, &dwState, &dwProtocol,
nullptr, &cbAtr);
2837 if (rc2 != SCARD_S_SUCCESS)
2843 if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
2846 void* data = ConvertMszUtf8NToWCharAlloc(tmp, cchReader, &len);
2850 return SCARD_E_NO_MEMORY;
2852 len *=
sizeof(WCHAR);
2854 cchReader = WINPR_ASSERTING_INT_CAST(PCSC_DWORD, len);
2860 *pcbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, cchReader);
2861 return SCARD_S_SUCCESS;
2864static LONG PCSC_ReadDeviceSystemName(WINPR_ATTR_UNUSED SCARDCONTEXT hContext, SCARDHANDLE hCard,
2865 DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
2867 BYTE* tmp =
nullptr;
2868 DWORD cbAttrLen = 0;
2869 const LONG rc = PCSC_ReadDeviceSystemNameGet(hContext, hCard, dwAttrId, &tmp, &cbAttrLen);
2870 if (rc != SCARD_S_SUCCESS)
2873 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2875 if (!PCSC_AddMemoryBlock(hContext, tmp))
2878 return SCARD_E_NO_MEMORY;
2881 *pcbAttrLen = cbAttrLen;
2882 *(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAttr)) = tmp;
2883 return SCARD_S_SUCCESS;
2887 memcpy(pbAttr, tmp, MIN(cbAttrLen, *pcbAttrLen));
2892 if (cbAttrLen > *pcbAttrLen)
2893 return SCARD_E_INSUFFICIENT_BUFFER;
2896 *pcbAttrLen = cbAttrLen;
2898 return SCARD_S_SUCCESS;
2901WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
2902 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2904 DWORD cbAttrLen = 0;
2905 SCARDCONTEXT hContext = 0;
2906 BOOL pcbAttrLenAlloc = FALSE;
2907 PCSC_LONG status = SCARD_S_SUCCESS;
2909 if (
nullptr == pcbAttrLen)
2910 return SCARD_E_INVALID_PARAMETER;
2912 cbAttrLen = *pcbAttrLen;
2914 if (*pcbAttrLen == SCARD_AUTOALLOCATE)
2916 if (
nullptr == pbAttr)
2917 return SCARD_E_INVALID_PARAMETER;
2919 pcbAttrLenAlloc = TRUE;
2920 *(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAttr)) =
nullptr;
2928 if (*pcbAttrLen > PCSC_MAX_BUFFER_SIZE)
2929 *pcbAttrLen = PCSC_MAX_BUFFER_SIZE;
2932 hContext = PCSC_GetCardContextFromHandle(hCard);
2935 return SCARD_E_INVALID_HANDLE;
2937 if ((dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A) ||
2938 (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W))
2940 return PCSC_SCardGetAttrib_FriendlyName(hCard, dwAttrId, pbAttr, pcbAttrLen);
2943 status = PCSC_SCardGetAttrib_Internal(hCard, dwAttrId, pbAttr, pcbAttrLen);
2945 if (status == SCARD_S_SUCCESS)
2947 if (dwAttrId == SCARD_ATTR_VENDOR_NAME)
2951 const char* vendorName =
nullptr;
2958 if (pcbAttrLenAlloc)
2959 vendorName = (
char*)*(WINPR_PACKED_ALIGN_CAST(BYTE**, pbAttr));
2961 vendorName = (
char*)pbAttr;
2965 size_t len = strnlen(vendorName, *pcbAttrLen);
2966 WINPR_ASSERT(len < UINT32_MAX);
2967 *pcbAttrLen = (DWORD)len + 1;
2976 if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE)
2978 if (!pcbAttrLenAlloc)
2980 PCSC_DWORD dwState = 0;
2981 PCSC_DWORD cbAtrLen = 0;
2982 PCSC_DWORD dwProtocol = 0;
2983 PCSC_DWORD cchReaderLen = 0;
2984 status = g_PCSC.pfnSCardStatus(hCard,
nullptr, &cchReaderLen, &dwState, &dwProtocol,
2985 nullptr, &cbAtrLen);
2987 if (status == SCARD_S_SUCCESS)
2989 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
2990 return SCARD_E_INSUFFICIENT_BUFFER;
2993 *(WINPR_PACKED_ALIGN_CAST(DWORD*, pbAttr)) =
2994 PCSC_ConvertProtocolsToWinSCard(dwProtocol);
2995 *pcbAttrLen =
sizeof(DWORD);
2999 else if (dwAttrId == SCARD_ATTR_CHANNEL_ID)
3001 if (!pcbAttrLenAlloc)
3003 UINT32 channelType = 0x20;
3004 UINT32 channelNumber = 0;
3006 if ((cbAttrLen <
sizeof(DWORD)) && pbAttr)
3007 return SCARD_E_INSUFFICIENT_BUFFER;
3009 status = SCARD_S_SUCCESS;
3011 *(WINPR_PACKED_ALIGN_CAST(DWORD*, pbAttr)) =
3012 (channelType << 16u) | channelNumber;
3013 *pcbAttrLen =
sizeof(DWORD);
3016 else if (dwAttrId == SCARD_ATTR_VENDOR_IFD_TYPE)
3019 else if (dwAttrId == SCARD_ATTR_DEFAULT_CLK)
3022 else if (dwAttrId == SCARD_ATTR_DEFAULT_DATA_RATE)
3025 else if (dwAttrId == SCARD_ATTR_MAX_CLK)
3028 else if (dwAttrId == SCARD_ATTR_MAX_DATA_RATE)
3031 else if (dwAttrId == SCARD_ATTR_MAX_IFSD)
3034 else if (dwAttrId == SCARD_ATTR_CHARACTERISTICS)
3037 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_A)
3039 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
3041 else if (dwAttrId == SCARD_ATTR_DEVICE_SYSTEM_NAME_W)
3043 status = PCSC_ReadDeviceSystemName(hContext, hCard, dwAttrId, pbAttr, pcbAttrLen);
3045 else if (dwAttrId == SCARD_ATTR_DEVICE_UNIT)
3048 else if (dwAttrId == SCARD_ATTR_POWER_MGMT_SUPPORT)
3051 else if (dwAttrId == SCARD_ATTR_CURRENT_CLK)
3054 else if (dwAttrId == SCARD_ATTR_CURRENT_F)
3057 else if (dwAttrId == SCARD_ATTR_CURRENT_D)
3060 else if (dwAttrId == SCARD_ATTR_CURRENT_N)
3063 else if (dwAttrId == SCARD_ATTR_CURRENT_CWT)
3066 else if (dwAttrId == SCARD_ATTR_CURRENT_BWT)
3069 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSC)
3072 else if (dwAttrId == SCARD_ATTR_CURRENT_EBC_ENCODING)
3075 else if (dwAttrId == SCARD_ATTR_CURRENT_IFSD)
3078 else if (dwAttrId == SCARD_ATTR_ICC_TYPE_PER_ATR)
3083 return WINPR_ASSERTING_INT_CAST(LONG, status);
3086WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
3087 LPCBYTE pbAttr, DWORD cbAttrLen)
3089 PCSC_LONG status = SCARD_S_SUCCESS;
3090 PCSC_SCARDHANDLE* pCard =
nullptr;
3091 PCSC_DWORD pcsc_dwAttrId = (PCSC_DWORD)dwAttrId;
3092 PCSC_DWORD pcsc_cbAttrLen = (PCSC_DWORD)cbAttrLen;
3094 if (!g_PCSC.pfnSCardSetAttrib)
3095 return PCSC_SCard_LogError(
"g_PCSC.pfnSCardSetAttrib");
3097 pCard = PCSC_GetCardHandleData(hCard);
3100 return SCARD_E_INVALID_VALUE;
3102 PCSC_WaitForCardAccess(0, hCard, pCard->shared);
3103 status = g_PCSC.pfnSCardSetAttrib(hCard, pcsc_dwAttrId, pbAttr, pcsc_cbAttrLen);
3104 return PCSC_MapErrorCodeToWinSCard(status);
3107WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc)
3109 WINPR_UNUSED(pDlgStruc);
3111 return SCARD_E_UNSUPPORTED_FEATURE;
3114WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pDlgStruc)
3116 WINPR_UNUSED(pDlgStruc);
3117 return SCARD_E_UNSUPPORTED_FEATURE;
3120WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_GetOpenCardNameA(
LPOPENCARDNAMEA pDlgStruc)
3122 WINPR_UNUSED(pDlgStruc);
3123 return SCARD_E_UNSUPPORTED_FEATURE;
3126WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_GetOpenCardNameW(
LPOPENCARDNAMEW pDlgStruc)
3128 WINPR_UNUSED(pDlgStruc);
3129 return SCARD_E_UNSUPPORTED_FEATURE;
3132WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardDlgExtendedError(
void)
3135 return SCARD_E_UNSUPPORTED_FEATURE;
3139static char* card_id_and_name_a(
const UUID* CardIdentifier, LPCSTR LookupName)
3141 if (!CardIdentifier || !LookupName)
3144 size_t len = strlen(LookupName) + 34;
3145 char*
id = malloc(len);
3149 (void)snprintf(
id, len,
"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X\\%s",
3150 CardIdentifier->Data1, CardIdentifier->Data2, CardIdentifier->Data3,
3151 CardIdentifier->Data4[0], CardIdentifier->Data4[1], CardIdentifier->Data4[2],
3152 CardIdentifier->Data4[3], CardIdentifier->Data4[4], CardIdentifier->Data4[5],
3153 CardIdentifier->Data4[6], CardIdentifier->Data4[7], LookupName);
3158static char* card_id_and_name_w(
const UUID* CardIdentifier, LPCWSTR LookupName)
3160 char* res =
nullptr;
3161 char* tmp = ConvertWCharToUtf8Alloc(LookupName,
nullptr);
3164 res = card_id_and_name_a(CardIdentifier, tmp);
3169WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReadCacheA(SCARDCONTEXT hContext,
3170 UUID* CardIdentifier,
3171 DWORD FreshnessCounter,
3172 LPSTR LookupName, PBYTE Data,
3175 PCSC_CACHE_ITEM* data =
nullptr;
3176 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3178 return SCARD_E_INVALID_HANDLE;
3180 char*
id = card_id_and_name_a(CardIdentifier, LookupName);
3182 data = HashTable_GetItemValue(ctx->cache,
id);
3188 return SCARD_W_CACHE_ITEM_NOT_FOUND;
3191 if (FreshnessCounter != data->freshness)
3194 return SCARD_W_CACHE_ITEM_STALE;
3197 if (*DataLen == SCARD_AUTOALLOCATE)
3199 BYTE* mem = calloc(1, data->len);
3201 return SCARD_E_NO_MEMORY;
3203 if (!PCSC_AddMemoryBlock(hContext, mem))
3206 return SCARD_E_NO_MEMORY;
3209 memcpy(mem, data->data, data->len);
3210 *(WINPR_PACKED_ALIGN_CAST(BYTE**, Data)) = mem;
3214 if (data->len > *DataLen)
3215 return SCARD_E_INSUFFICIENT_BUFFER;
3216 memcpy(Data, data->data, data->len);
3219 *DataLen = data->len;
3220 return SCARD_S_SUCCESS;
3223WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardReadCacheW(SCARDCONTEXT hContext,
3224 UUID* CardIdentifier,
3225 DWORD FreshnessCounter,
3226 LPWSTR LookupName, PBYTE Data,
3229 PCSC_CACHE_ITEM* data =
nullptr;
3230 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3232 return SCARD_E_INVALID_HANDLE;
3234 char*
id = card_id_and_name_w(CardIdentifier, LookupName);
3236 data = HashTable_GetItemValue(ctx->cache,
id);
3242 return SCARD_W_CACHE_ITEM_NOT_FOUND;
3245 if (FreshnessCounter != data->freshness)
3248 return SCARD_W_CACHE_ITEM_STALE;
3251 if (*DataLen == SCARD_AUTOALLOCATE)
3253 BYTE* mem = calloc(1, data->len);
3255 return SCARD_E_NO_MEMORY;
3257 if (!PCSC_AddMemoryBlock(hContext, mem))
3260 return SCARD_E_NO_MEMORY;
3263 memcpy(mem, data->data, data->len);
3264 *(WINPR_PACKED_ALIGN_CAST(BYTE**, Data)) = mem;
3268 if (data->len > *DataLen)
3269 return SCARD_E_INSUFFICIENT_BUFFER;
3270 memcpy(Data, data->data, data->len);
3272 *DataLen = data->len;
3273 return SCARD_S_SUCCESS;
3276WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardWriteCacheA(SCARDCONTEXT hContext,
3277 UUID* CardIdentifier,
3278 DWORD FreshnessCounter,
3279 LPSTR LookupName, PBYTE Data,
3282 PCSC_CACHE_ITEM* data =
nullptr;
3283 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3287 return SCARD_E_FILE_NOT_FOUND;
3289 id = card_id_and_name_a(CardIdentifier, LookupName);
3292 return SCARD_E_NO_MEMORY;
3294 data = malloc(
sizeof(PCSC_CACHE_ITEM));
3298 return SCARD_E_NO_MEMORY;
3300 data->data = calloc(DataLen, 1);
3305 return SCARD_E_NO_MEMORY;
3307 data->len = DataLen;
3308 data->freshness = FreshnessCounter;
3309 memcpy(data->data, Data, data->len);
3311 HashTable_Remove(ctx->cache,
id);
3312 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
3317 pcsc_cache_item_free(data);
3318 return SCARD_E_NO_MEMORY;
3322 return SCARD_S_SUCCESS;
3325WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardWriteCacheW(SCARDCONTEXT hContext,
3326 UUID* CardIdentifier,
3327 DWORD FreshnessCounter,
3328 LPWSTR LookupName, PBYTE Data,
3331 PCSC_CACHE_ITEM* data =
nullptr;
3332 PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
3335 return SCARD_E_FILE_NOT_FOUND;
3337 id = card_id_and_name_w(CardIdentifier, LookupName);
3340 return SCARD_E_NO_MEMORY;
3342 data = malloc(
sizeof(PCSC_CACHE_ITEM));
3346 return SCARD_E_NO_MEMORY;
3348 data->data = malloc(DataLen);
3353 return SCARD_E_NO_MEMORY;
3355 data->len = DataLen;
3356 data->freshness = FreshnessCounter;
3357 memcpy(data->data, Data, data->len);
3359 HashTable_Remove(ctx->cache,
id);
3360 const BOOL rc = HashTable_Insert(ctx->cache,
id, data);
3365 pcsc_cache_item_free(data);
3366 return SCARD_E_NO_MEMORY;
3370 return SCARD_S_SUCCESS;
3373WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetReaderIconA(
3374 SCARDCONTEXT hContext, LPCSTR szReaderName,
3375 LPBYTE pbIcon , LPDWORD pcbIcon)
3377 WINPR_UNUSED(hContext);
3378 WINPR_UNUSED(szReaderName);
3379 WINPR_UNUSED(pbIcon);
3380 WINPR_ASSERT(pcbIcon);
3382 return SCARD_E_UNSUPPORTED_FEATURE;
3385WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetReaderIconW(
3386 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3387 LPBYTE pbIcon , LPDWORD pcbIcon)
3389 WINPR_UNUSED(hContext);
3390 WINPR_UNUSED(szReaderName);
3391 WINPR_UNUSED(pbIcon);
3392 WINPR_ASSERT(pcbIcon);
3394 return SCARD_E_UNSUPPORTED_FEATURE;
3397WINPR_ATTR_NODISCARD
static LONG WINAPI PCSC_SCardGetDeviceTypeIdA(SCARDCONTEXT hContext,
3398 LPCSTR szReaderName,
3399 LPDWORD pdwDeviceTypeId)
3401 WINPR_UNUSED(hContext);
3402 WINPR_UNUSED(szReaderName);
3403 WINPR_UNUSED(pdwDeviceTypeId);
3404 if (pdwDeviceTypeId)
3405 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3406 return SCARD_S_SUCCESS;
3410static LONG WINAPI PCSC_SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
3411 LPDWORD pdwDeviceTypeId)
3413 WINPR_UNUSED(hContext);
3414 WINPR_UNUSED(szReaderName);
3415 if (pdwDeviceTypeId)
3416 *pdwDeviceTypeId = SCARD_READER_TYPE_USB;
3417 return SCARD_S_SUCCESS;
3421static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdA(
3422 SCARDCONTEXT hContext, LPCSTR szReaderName,
3423 LPSTR szDeviceInstanceId ,
3424 LPDWORD pcchDeviceInstanceId )
3426 WINPR_UNUSED(hContext);
3427 WINPR_UNUSED(szReaderName);
3428 WINPR_UNUSED(szDeviceInstanceId);
3429 WINPR_UNUSED(pcchDeviceInstanceId);
3430 return SCARD_E_UNSUPPORTED_FEATURE;
3434static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdW(
3435 SCARDCONTEXT hContext, LPCWSTR szReaderName,
3436 LPWSTR szDeviceInstanceId ,
3437 LPDWORD pcchDeviceInstanceId )
3439 WINPR_UNUSED(hContext);
3440 WINPR_UNUSED(szReaderName);
3441 WINPR_UNUSED(szDeviceInstanceId);
3442 WINPR_UNUSED(pcchDeviceInstanceId);
3443 return SCARD_E_UNSUPPORTED_FEATURE;
3447static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdA(
3448 SCARDCONTEXT hContext, LPCSTR szDeviceInstanceId,
3450 LPDWORD pcchReaders )
3452 WINPR_UNUSED(hContext);
3453 WINPR_UNUSED(szDeviceInstanceId);
3454 WINPR_UNUSED(mszReaders);
3455 WINPR_UNUSED(pcchReaders);
3456 return SCARD_E_UNSUPPORTED_FEATURE;
3460static LONG WINAPI PCSC_SCardListReadersWithDeviceInstanceIdW(
3461 SCARDCONTEXT hContext, LPCWSTR szDeviceInstanceId,
3463 LPDWORD pcchReaders )
3465 WINPR_UNUSED(hContext);
3466 WINPR_UNUSED(szDeviceInstanceId);
3467 WINPR_UNUSED(mszReaders);
3468 WINPR_UNUSED(pcchReaders);
3469 return SCARD_E_UNSUPPORTED_FEATURE;
3473static LONG WINAPI PCSC_SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent)
3476 WINPR_UNUSED(hContext);
3477 WINPR_UNUSED(dwEvent);
3478 return SCARD_E_UNSUPPORTED_FEATURE;
3483unsigned int determineMacOSXVersion(
void)
3487 char* kernelVersion =
nullptr;
3488 char* tok =
nullptr;
3489 unsigned int version = 0;
3490 long majorVersion = 0;
3491 long minorVersion = 0;
3492 long patchVersion = 0;
3494 char* context =
nullptr;
3496 mib[1] = KERN_OSRELEASE;
3498 if (sysctl(mib, 2,
nullptr, &len,
nullptr, 0) != 0)
3501 kernelVersion = calloc(len,
sizeof(
char));
3506 if (sysctl(mib, 2, kernelVersion, &len,
nullptr, 0) != 0)
3508 free(kernelVersion);
3512 tok = strtok_s(kernelVersion,
".", &context);
3520 majorVersion = strtol(tok,
nullptr, 0);
3528 minorVersion = strtol(tok,
nullptr, 0);
3536 patchVersion = strtol(tok,
nullptr, 0);
3544 tok = strtok_s(
nullptr,
".", &context);
3551 if (majorVersion < 5)
3553 if (minorVersion < 4)
3554 version = 0x10000000;
3556 version = 0x10010000;
3560 switch (majorVersion)
3563 version = 0x10010000;
3567 version = 0x10020000;
3571 version = 0x10030000;
3575 version = 0x10040000;
3579 version = 0x10050000;
3583 version = 0x10060000;
3587 version = 0x10070000;
3591 version = 0x10080000;
3595 version = 0x10090000;
3599 version = 0x10100000;
3603 version |= (minorVersion << 8) | (patchVersion);
3607 free(kernelVersion);
3616 PCSC_SCardEstablishContext,
3617 PCSC_SCardReleaseContext,
3618 PCSC_SCardIsValidContext,
3619 PCSC_SCardListReaderGroupsA,
3620 PCSC_SCardListReaderGroupsW,
3621 PCSC_SCardListReadersA,
3622 PCSC_SCardListReadersW,
3623 PCSC_SCardListCardsA,
3624 PCSC_SCardListCardsW,
3625 PCSC_SCardListInterfacesA,
3626 PCSC_SCardListInterfacesW,
3627 PCSC_SCardGetProviderIdA,
3628 PCSC_SCardGetProviderIdW,
3629 PCSC_SCardGetCardTypeProviderNameA,
3630 PCSC_SCardGetCardTypeProviderNameW,
3631 PCSC_SCardIntroduceReaderGroupA,
3632 PCSC_SCardIntroduceReaderGroupW,
3633 PCSC_SCardForgetReaderGroupA,
3634 PCSC_SCardForgetReaderGroupW,
3635 PCSC_SCardIntroduceReaderA,
3636 PCSC_SCardIntroduceReaderW,
3637 PCSC_SCardForgetReaderA,
3638 PCSC_SCardForgetReaderW,
3639 PCSC_SCardAddReaderToGroupA,
3640 PCSC_SCardAddReaderToGroupW,
3641 PCSC_SCardRemoveReaderFromGroupA,
3642 PCSC_SCardRemoveReaderFromGroupW,
3643 PCSC_SCardIntroduceCardTypeA,
3644 PCSC_SCardIntroduceCardTypeW,
3645 PCSC_SCardSetCardTypeProviderNameA,
3646 PCSC_SCardSetCardTypeProviderNameW,
3647 PCSC_SCardForgetCardTypeA,
3648 PCSC_SCardForgetCardTypeW,
3649 PCSC_SCardFreeMemory,
3650 PCSC_SCardAccessStartedEvent,
3651 PCSC_SCardReleaseStartedEvent,
3652 PCSC_SCardLocateCardsA,
3653 PCSC_SCardLocateCardsW,
3654 PCSC_SCardLocateCardsByATRA,
3655 PCSC_SCardLocateCardsByATRW,
3656 PCSC_SCardGetStatusChangeA,
3657 PCSC_SCardGetStatusChangeW,
3661 PCSC_SCardReconnect,
3662 PCSC_SCardDisconnect,
3663 PCSC_SCardBeginTransaction,
3664 PCSC_SCardEndTransaction,
3665 PCSC_SCardCancelTransaction,
3670 PCSC_SCardGetTransmitCount,
3672 PCSC_SCardGetAttrib,
3673 PCSC_SCardSetAttrib,
3674 PCSC_SCardUIDlgSelectCardA,
3675 PCSC_SCardUIDlgSelectCardW,
3676 PCSC_GetOpenCardNameA,
3677 PCSC_GetOpenCardNameW,
3678 PCSC_SCardDlgExtendedError,
3679 PCSC_SCardReadCacheA,
3680 PCSC_SCardReadCacheW,
3681 PCSC_SCardWriteCacheA,
3682 PCSC_SCardWriteCacheW,
3683 PCSC_SCardGetReaderIconA,
3684 PCSC_SCardGetReaderIconW,
3685 PCSC_SCardGetDeviceTypeIdA,
3686 PCSC_SCardGetDeviceTypeIdW,
3687 PCSC_SCardGetReaderDeviceInstanceIdA,
3688 PCSC_SCardGetReaderDeviceInstanceIdW,
3689 PCSC_SCardListReadersWithDeviceInstanceIdA,
3690 PCSC_SCardListReadersWithDeviceInstanceIdW,
3696 return &PCSC_SCardApiFunctionTable;
3699int PCSC_InitializeSCardApi(
void)
3702 SetEnvironmentVariableA(
"PCSCLITE_NO_BLOCKING",
"1");
3704 g_PCSCModule = LoadLibraryX(
"/System/Library/Frameworks/PCSC.framework/PCSC");
3705 OSXVersion = determineMacOSXVersion();
3707 if (OSXVersion == 0)
3711 g_PCSCModule = LoadLibraryA(
"libpcsclite.so.1");
3714 g_PCSCModule = LoadLibraryA(
"libpcsclite.so");
3723#undef SCardListReaderGroups
3724#undef SCardListReaders
3725#undef SCardListCards
3726#undef SCardListInterfaces
3727#undef SCardGetProviderId
3728#undef SCardGetCardTypeProviderName
3729#undef SCardIntroduceReaderGroup
3730#undef SCardForgetReaderGroup
3731#undef SCardIntroduceReader
3732#undef SCardForgetReader
3733#undef SCardAddReaderToGroup
3734#undef SCardRemoveReaderFromGroup
3735#undef SCardIntroduceCardType
3736#undef SCardSetCardTypeProviderName
3737#undef SCardForgetCardType
3738#undef SCardLocateCards
3739#undef SCardLocateCardsByATR
3740#undef SCardGetStatusChange
3743#undef SCardUIDlgSelectCard
3744#undef GetOpenCardName
3745#undef SCardReadCache
3746#undef SCardWriteCache
3747#undef SCardGetReaderIcon
3748#undef SCardGetDeviceTypeId
3749#undef SCardGetReaderDeviceInstanceId
3750#undef SCardListReadersWithDeviceInstanceId
3752 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEstablishContext);
3753 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReleaseContext);
3754 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardIsValidContext);
3755 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardConnect);
3756 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardReconnect);
3757 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardDisconnect);
3758 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardBeginTransaction);
3759 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardEndTransaction);
3760 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardStatus);
3761 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetStatusChange);
3765 if (OSXVersion >= 0x10050600)
3767 WINSCARD_LOAD_PROC_EX(g_PCSCModule, g_PCSC, SCardControl, SCardControl132);
3771 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3774 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardControl);
3776 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardTransmit);
3777 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaderGroups);
3778 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardListReaders);
3779 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardCancel);
3780 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardGetAttrib);
3781 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardSetAttrib);
3782 g_PCSC.pfnSCardFreeMemory =
nullptr;
3784 WINSCARD_LOAD_PROC(g_PCSCModule, g_PCSC, SCardFreeMemory);
3787 if (g_PCSC.pfnSCardFreeMemory)
3788 g_SCardAutoAllocate = TRUE;
3790#ifdef DISABLE_PCSC_SCARD_AUTOALLOCATE
3791 g_PCSC.pfnSCardFreeMemory =
nullptr;
3792 g_SCardAutoAllocate = FALSE;
3795 g_PnP_Notification = FALSE;
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree